From e2cb0eac3d1d1acc8203634f3243859d95e4b37c Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Mon, 28 Nov 2022 01:24:18 +0530 Subject: mailbox: qcom-apcs-ipc: Add SM4250 APCS IPC support Enable SM4250 APCS IPC support by adding the compatible. It reuses msm8994_apcs_data. Signed-off-by: Bhupesh Sharma Signed-off-by: Jassi Brar --- drivers/mailbox/qcom-apcs-ipc-mailbox.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c index f1f0e87a79e6..0e9f9cba8668 100644 --- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c +++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c @@ -156,6 +156,7 @@ static const struct of_device_id qcom_apcs_ipc_of_match[] = { { .compatible = "qcom,sc8180x-apss-shared", .data = &apps_shared_apcs_data }, { .compatible = "qcom,sdm660-apcs-hmss-global", .data = &msm8994_apcs_data }, { .compatible = "qcom,sdm845-apss-shared", .data = &apps_shared_apcs_data }, + { .compatible = "qcom,sm4250-apcs-hmss-global", .data = &msm8994_apcs_data }, { .compatible = "qcom,sm6125-apcs-hmss-global", .data = &msm8994_apcs_data }, { .compatible = "qcom,sm8150-apss-shared", .data = &apps_shared_apcs_data }, { .compatible = "qcom,sm6115-apcs-hmss-global", .data = &msm8994_apcs_data }, -- cgit v1.2.3 From 31c8d06e55acc325c64596f148d5405dbe4adf30 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Tue, 22 Nov 2022 21:22:44 +0100 Subject: mailbox: config: ti-msgmgr: Default set to ARCH_K3 for TI msg manager Defaulting the build to ARCH_K3 for the TI message manager driver. Signed-off-by: Nicolas Frayer Signed-off-by: Jassi Brar --- drivers/mailbox/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 05d6fae800e3..3515ab67da48 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -136,6 +136,7 @@ config STI_MBOX config TI_MESSAGE_MANAGER tristate "Texas Instruments Message Manager Driver" depends on ARCH_KEYSTONE || ARCH_K3 + default ARCH_K3 help An implementation of Message Manager slave driver for Keystone and K3 architecture SoCs from Texas Instruments. Message Manager -- cgit v1.2.3 From 8b9b08bd8d6adda032ae65a3a2f87ee989500c02 Mon Sep 17 00:00:00 2001 From: ye xingchen Date: Thu, 17 Nov 2022 19:29:11 +0800 Subject: mailbox: rockchip: Use device_get_match_data() to simplify the code Directly get the match data with device_get_match_data(). Signed-off-by: ye xingchen Signed-off-by: Jassi Brar --- drivers/mailbox/rockchip-mailbox.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/rockchip-mailbox.c b/drivers/mailbox/rockchip-mailbox.c index 979acc810f30..e02d3c9e3693 100644 --- a/drivers/mailbox/rockchip-mailbox.c +++ b/drivers/mailbox/rockchip-mailbox.c @@ -164,7 +164,6 @@ MODULE_DEVICE_TABLE(of, rockchp_mbox_of_match); static int rockchip_mbox_probe(struct platform_device *pdev) { struct rockchip_mbox *mb; - const struct of_device_id *match; const struct rockchip_mbox_data *drv_data; struct resource *res; int ret, irq, i; @@ -172,8 +171,7 @@ static int rockchip_mbox_probe(struct platform_device *pdev) if (!pdev->dev.of_node) return -ENODEV; - match = of_match_node(rockchip_mbox_of_match, pdev->dev.of_node); - drv_data = (const struct rockchip_mbox_data *)match->data; + drv_data = (const struct rockchip_mbox_data *) device_get_match_data(&pdev->dev); mb = devm_kzalloc(&pdev->dev, sizeof(*mb), GFP_KERNEL); if (!mb) -- cgit v1.2.3 From 23ba2e7fa282dd8e6c51c284ab1ea184c96c88b2 Mon Sep 17 00:00:00 2001 From: Yongqiang Niu Date: Thu, 15 Dec 2022 15:28:03 +0800 Subject: mailbox: mtk-cmdq: Use GCE_CTRL_BY_SW definition instead of number Use GCE_CTRL_BY_SW definition instead of number Signed-off-by: Yongqiang Niu Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu Signed-off-by: Jassi Brar --- drivers/mailbox/mtk-cmdq-mailbox.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 9465f9081515..c3cb24f51699 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -38,6 +38,7 @@ #define CMDQ_THR_PRIORITY 0x40 #define GCE_GCTL_VALUE 0x48 +#define GCE_CTRL_BY_SW GENMASK(2, 0) #define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200 #define CMDQ_THR_ENABLED 0x1 @@ -129,7 +130,8 @@ static void cmdq_init(struct cmdq *cmdq) WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks)); if (cmdq->control_by_sw) - writel(0x7, cmdq->base + GCE_GCTL_VALUE); + writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE); + writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES); for (i = 0; i <= CMDQ_MAX_EVENT; i++) writel(i, cmdq->base + CMDQ_SYNC_TOKEN_UPDATE); -- cgit v1.2.3 From 63f40a7f5dbdb70f8574754475346a9e72ccef6c Mon Sep 17 00:00:00 2001 From: Yongqiang Niu Date: Thu, 15 Dec 2022 15:28:04 +0800 Subject: mailbox: mtk-cmdq: add gce software ddr enable private data if gce work control by software, we need set software enable for MT8186 Soc there is a handshake flow between gce and ddr hardware, if not set ddr enable flag of gce, ddr will fall into idle mode, then gce instructions will not process done. we need set this flag of gce to tell ddr when gce is idle or busy controlled by software flow. 0x48[2:0] means control by software 0x48[18:16] means ddr enable 0x48[2:0] is pre-condition of 0x48[18:16]. if we want set 0x48[18:16] ddr enable, 0x48[2:0] must be set at same time. and only these bits is useful, other bits is useless bits Signed-off-by: Yongqiang Niu Reviewed-by: CK Hu Signed-off-by: Jassi Brar --- drivers/mailbox/mtk-cmdq-mailbox.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index c3cb24f51699..d2363c6b8b7a 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -39,6 +39,7 @@ #define GCE_GCTL_VALUE 0x48 #define GCE_CTRL_BY_SW GENMASK(2, 0) +#define GCE_DDR_EN GENMASK(18, 16) #define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200 #define CMDQ_THR_ENABLED 0x1 @@ -81,6 +82,7 @@ struct cmdq { bool suspended; u8 shift_pa; bool control_by_sw; + bool sw_ddr_en; u32 gce_num; }; @@ -88,6 +90,7 @@ struct gce_plat { u32 thread_nr; u8 shift; bool control_by_sw; + bool sw_ddr_en; u32 gce_num; }; @@ -127,10 +130,16 @@ static void cmdq_thread_resume(struct cmdq_thread *thread) static void cmdq_init(struct cmdq *cmdq) { int i; + u32 gctl_regval = 0; WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks)); if (cmdq->control_by_sw) - writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE); + gctl_regval = GCE_CTRL_BY_SW; + if (cmdq->sw_ddr_en) + gctl_regval |= GCE_DDR_EN; + + if (gctl_regval) + writel(gctl_regval, cmdq->base + GCE_GCTL_VALUE); writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES); for (i = 0; i <= CMDQ_MAX_EVENT; i++) @@ -545,6 +554,7 @@ static int cmdq_probe(struct platform_device *pdev) cmdq->thread_nr = plat_data->thread_nr; cmdq->shift_pa = plat_data->shift; cmdq->control_by_sw = plat_data->control_by_sw; + cmdq->sw_ddr_en = plat_data->sw_ddr_en; cmdq->gce_num = plat_data->gce_num; cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0); err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED, -- cgit v1.2.3 From 7abd037aa581dcdc16c30ebdea758a4e3877f8e1 Mon Sep 17 00:00:00 2001 From: Yongqiang Niu Date: Thu, 15 Dec 2022 15:28:05 +0800 Subject: mailbox: mtk-cmdq: add gce ddr enable support flow add gce ddr enable control flow when gce suspend/resume when all cmdq instruction task has been processed done, we need set this gce ddr enable to disable status to tell cmdq hardware gce there is none task need process, and the hardware can go into idle mode and no access ddr anymore, then the spm can go into suspend. the original issue is gce still access ddr when cmdq suspend function call, but there is no task run. so, we need control gce access ddr with this flow. when cmdq suspend function, there is no task need process, we can disable gce access ddr, to make sure system go into suspend success. Signed-off-by: Yongqiang Niu Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu Signed-off-by: Jassi Brar --- drivers/mailbox/mtk-cmdq-mailbox.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index d2363c6b8b7a..53904511598d 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -94,6 +94,18 @@ struct gce_plat { u32 gce_num; }; +static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable) +{ + WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks)); + + if (enable) + writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE); + else + writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE); + + clk_bulk_disable(cmdq->gce_num, cmdq->clocks); +} + u8 cmdq_get_shift_pa(struct mbox_chan *chan) { struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox); @@ -322,6 +334,9 @@ static int cmdq_suspend(struct device *dev) if (task_running) dev_warn(dev, "exist running task(s) in suspend\n"); + if (cmdq->sw_ddr_en) + cmdq_sw_ddr_enable(cmdq, false); + clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks); return 0; @@ -333,6 +348,10 @@ static int cmdq_resume(struct device *dev) WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks)); cmdq->suspended = false; + + if (cmdq->sw_ddr_en) + cmdq_sw_ddr_enable(cmdq, true); + return 0; } @@ -340,6 +359,9 @@ static int cmdq_remove(struct platform_device *pdev) { struct cmdq *cmdq = platform_get_drvdata(pdev); + if (cmdq->sw_ddr_en) + cmdq_sw_ddr_enable(cmdq, false); + clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks); return 0; } -- cgit v1.2.3 From 926d6214f66955f0c066175127cbcf2eaae5ad6b Mon Sep 17 00:00:00 2001 From: Yongqiang Niu Date: Thu, 15 Dec 2022 15:28:06 +0800 Subject: mailbox: mtk-cmdq: add MT8186 support add MT8186 cmdq support Signed-off-by: Yongqiang Niu Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: CK Hu Signed-off-by: Jassi Brar --- drivers/mailbox/mtk-cmdq-mailbox.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 53904511598d..c5229f377c5e 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -694,9 +694,18 @@ static const struct gce_plat gce_plat_v6 = { .gce_num = 2 }; +static const struct gce_plat gce_plat_v7 = { + .thread_nr = 24, + .shift = 3, + .control_by_sw = true, + .sw_ddr_en = true, + .gce_num = 1 +}; + static const struct of_device_id cmdq_of_ids[] = { {.compatible = "mediatek,mt8173-gce", .data = (void *)&gce_plat_v2}, {.compatible = "mediatek,mt8183-gce", .data = (void *)&gce_plat_v3}, + {.compatible = "mediatek,mt8186-gce", .data = (void *)&gce_plat_v7}, {.compatible = "mediatek,mt6779-gce", .data = (void *)&gce_plat_v4}, {.compatible = "mediatek,mt8192-gce", .data = (void *)&gce_plat_v5}, {.compatible = "mediatek,mt8195-gce", .data = (void *)&gce_plat_v6}, -- cgit v1.2.3 From ab47d0bfdf88faac0eb02749e5bfaa306e004300 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 23 Nov 2022 17:56:52 +0000 Subject: mailbox: mpfs: read the system controller's status Some services explicitly return an error code in their response, but others rely on the system controller to set a status in its status register. The meaning of the bits varies based on what service is requested, so pass it back up to the driver that requested the service in the first place. The field in the message struct already existed, but was unused until now. If the system controller is busy, in which case we should never actually be in the interrupt handler, or if the service fails the mailbox itself should not be read. Callers should check the status before operating on the response. There's an existing, but unused, #define for the mailbox mask - but it was incorrect. It was doing a GENMASK_ULL(32, 16) which should've just been a GENMASK(31, 16), so fix that up and start using it. Fixes: 83d7b1560810 ("mbox: add polarfire soc system controller mailbox") Signed-off-by: Conor Dooley Reviewed-by: Palmer Dabbelt Signed-off-by: Jassi Brar --- drivers/mailbox/mailbox-mpfs.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c index cfacb3f320a6..853901acaeec 100644 --- a/drivers/mailbox/mailbox-mpfs.c +++ b/drivers/mailbox/mailbox-mpfs.c @@ -2,7 +2,7 @@ /* * Microchip PolarFire SoC (MPFS) system controller/mailbox controller driver * - * Copyright (c) 2020 Microchip Corporation. All rights reserved. + * Copyright (c) 2020-2022 Microchip Corporation. All rights reserved. * * Author: Conor Dooley * @@ -56,7 +56,7 @@ #define SCB_STATUS_NOTIFY_MASK BIT(SCB_STATUS_NOTIFY) #define SCB_STATUS_POS (16) -#define SCB_STATUS_MASK GENMASK_ULL(SCB_STATUS_POS + SCB_MASK_WIDTH, SCB_STATUS_POS) +#define SCB_STATUS_MASK GENMASK(SCB_STATUS_POS + SCB_MASK_WIDTH - 1, SCB_STATUS_POS) struct mpfs_mbox { struct mbox_controller controller; @@ -130,13 +130,38 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan) struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; struct mpfs_mss_response *response = mbox->response; u16 num_words = ALIGN((response->resp_size), (4)) / 4U; - u32 i; + u32 i, status; if (!response->resp_msg) { dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM); return; } + /* + * The status is stored in bits 31:16 of the SERVICES_SR register. + * It is only valid when BUSY == 0. + * We should *never* get an interrupt while the controller is + * still in the busy state. If we do, something has gone badly + * wrong & the content of the mailbox would not be valid. + */ + if (mpfs_mbox_busy(mbox)) { + dev_err(mbox->dev, "got an interrupt but system controller is busy\n"); + response->resp_status = 0xDEAD; + return; + } + + status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); + + /* + * If the status of the individual servers is non-zero, the service has + * failed. The contents of the mailbox at this point are not be valid, + * so don't bother reading them. Set the status so that the driver + * implementing the service can handle the result. + */ + response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS; + if (response->resp_status) + return; + if (!mpfs_mbox_busy(mbox)) { for (i = 0; i < num_words; i++) { response->resp_msg[i] = -- cgit v1.2.3 From 165b7643f2df890066b1b4e8a387888a600ca9bf Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 25 Nov 2022 14:35:48 +0800 Subject: mailbox: arm_mhuv2: Fix return value check in mhuv2_probe() If devm_of_iomap() fails, it returns ERR_PTR() and never return NULL, so replace NULL pointer check with IS_ERR() to fix this problem. Fixes: 5a6338cce9f4 ("mailbox: arm_mhuv2: Add driver") Signed-off-by: Yang Yingliang Acked-by: Viresh Kumar Signed-off-by: Jassi Brar --- drivers/mailbox/arm_mhuv2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c index a47aef8df52f..c6d4957c4da8 100644 --- a/drivers/mailbox/arm_mhuv2.c +++ b/drivers/mailbox/arm_mhuv2.c @@ -1062,8 +1062,8 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id) int ret = -EINVAL; reg = devm_of_iomap(dev, dev->of_node, 0, NULL); - if (!reg) - return -ENOMEM; + if (IS_ERR(reg)) + return PTR_ERR(reg); mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL); if (!mhu) -- cgit v1.2.3 From acabe12c6106b105ac8285d6d5ba2aeeab74fd47 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 2 Nov 2022 11:07:36 +0100 Subject: mailbox: mtk-cmdq-mailbox: Use platform data directly instead of copying Copying platform data to struct cmdq serves to no purpose, as that data is never modified during runtime: it's worth at this point storing a pointer to gce_plat in gce and. Remove all duplicated `struct gce_plat` members from `struct gce` and reuse the platform data across the driver to save some memory. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Matthias Brugger Reviewed-by: Chun-Kuang Hu Signed-off-by: Jassi Brar --- drivers/mailbox/mtk-cmdq-mailbox.c | 88 +++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index c5229f377c5e..a460ee26eb11 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -75,15 +75,11 @@ struct cmdq { struct mbox_controller mbox; void __iomem *base; int irq; - u32 thread_nr; u32 irq_mask; + const struct gce_plat *pdata; struct cmdq_thread *thread; struct clk_bulk_data clocks[CMDQ_GCE_NUM_MAX]; bool suspended; - u8 shift_pa; - bool control_by_sw; - bool sw_ddr_en; - u32 gce_num; }; struct gce_plat { @@ -96,21 +92,21 @@ struct gce_plat { static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable) { - WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks)); + WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks)); if (enable) writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE); else writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE); - clk_bulk_disable(cmdq->gce_num, cmdq->clocks); + clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks); } u8 cmdq_get_shift_pa(struct mbox_chan *chan) { struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox); - return cmdq->shift_pa; + return cmdq->pdata->shift; } EXPORT_SYMBOL(cmdq_get_shift_pa); @@ -144,10 +140,10 @@ static void cmdq_init(struct cmdq *cmdq) int i; u32 gctl_regval = 0; - WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks)); - if (cmdq->control_by_sw) + WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks)); + if (cmdq->pdata->control_by_sw) gctl_regval = GCE_CTRL_BY_SW; - if (cmdq->sw_ddr_en) + if (cmdq->pdata->sw_ddr_en) gctl_regval |= GCE_DDR_EN; if (gctl_regval) @@ -156,7 +152,7 @@ static void cmdq_init(struct cmdq *cmdq) writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES); for (i = 0; i <= CMDQ_MAX_EVENT; i++) writel(i, cmdq->base + CMDQ_SYNC_TOKEN_UPDATE); - clk_bulk_disable(cmdq->gce_num, cmdq->clocks); + clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks); } static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread) @@ -201,7 +197,7 @@ static void cmdq_task_insert_into_thread(struct cmdq_task *task) prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = (u64)CMDQ_JUMP_BY_PA << 32 | - (task->pa_base >> task->cmdq->shift_pa); + (task->pa_base >> task->cmdq->pdata->shift); dma_sync_single_for_device(dev, prev_task->pa_base, prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); @@ -235,7 +231,7 @@ static void cmdq_task_handle_error(struct cmdq_task *task) next_task = list_first_entry_or_null(&thread->task_busy_list, struct cmdq_task, list_entry); if (next_task) - writel(next_task->pa_base >> cmdq->shift_pa, + writel(next_task->pa_base >> cmdq->pdata->shift, thread->base + CMDQ_THR_CURR_ADDR); cmdq_thread_resume(thread); } @@ -266,7 +262,7 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, else return; - curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->shift_pa; + curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->pdata->shift; list_for_each_entry_safe(task, tmp, &thread->task_busy_list, list_entry) { @@ -289,7 +285,7 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, if (list_empty(&thread->task_busy_list)) { cmdq_thread_disable(cmdq, thread); - clk_bulk_disable(cmdq->gce_num, cmdq->clocks); + clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks); } } @@ -303,7 +299,7 @@ static irqreturn_t cmdq_irq_handler(int irq, void *dev) if (!(irq_status ^ cmdq->irq_mask)) return IRQ_NONE; - for_each_clear_bit(bit, &irq_status, cmdq->thread_nr) { + for_each_clear_bit(bit, &irq_status, cmdq->pdata->thread_nr) { struct cmdq_thread *thread = &cmdq->thread[bit]; spin_lock_irqsave(&thread->chan->lock, flags); @@ -323,7 +319,7 @@ static int cmdq_suspend(struct device *dev) cmdq->suspended = true; - for (i = 0; i < cmdq->thread_nr; i++) { + for (i = 0; i < cmdq->pdata->thread_nr; i++) { thread = &cmdq->thread[i]; if (!list_empty(&thread->task_busy_list)) { task_running = true; @@ -334,10 +330,10 @@ static int cmdq_suspend(struct device *dev) if (task_running) dev_warn(dev, "exist running task(s) in suspend\n"); - if (cmdq->sw_ddr_en) + if (cmdq->pdata->sw_ddr_en) cmdq_sw_ddr_enable(cmdq, false); - clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks); + clk_bulk_unprepare(cmdq->pdata->gce_num, cmdq->clocks); return 0; } @@ -346,10 +342,10 @@ static int cmdq_resume(struct device *dev) { struct cmdq *cmdq = dev_get_drvdata(dev); - WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks)); + WARN_ON(clk_bulk_prepare(cmdq->pdata->gce_num, cmdq->clocks)); cmdq->suspended = false; - if (cmdq->sw_ddr_en) + if (cmdq->pdata->sw_ddr_en) cmdq_sw_ddr_enable(cmdq, true); return 0; @@ -359,10 +355,10 @@ static int cmdq_remove(struct platform_device *pdev) { struct cmdq *cmdq = platform_get_drvdata(pdev); - if (cmdq->sw_ddr_en) + if (cmdq->pdata->sw_ddr_en) cmdq_sw_ddr_enable(cmdq, false); - clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks); + clk_bulk_unprepare(cmdq->pdata->gce_num, cmdq->clocks); return 0; } @@ -388,7 +384,7 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) task->pkt = pkt; if (list_empty(&thread->task_busy_list)) { - WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks)); + WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks)); /* * The thread reset will clear thread related register to 0, @@ -398,9 +394,9 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) */ WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); - writel(task->pa_base >> cmdq->shift_pa, + writel(task->pa_base >> cmdq->pdata->shift, thread->base + CMDQ_THR_CURR_ADDR); - writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->shift_pa, + writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift, thread->base + CMDQ_THR_END_ADDR); writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); @@ -409,20 +405,20 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) } else { WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << - cmdq->shift_pa; + cmdq->pdata->shift; end_pa = readl(thread->base + CMDQ_THR_END_ADDR) << - cmdq->shift_pa; + cmdq->pdata->shift; /* check boundary */ if (curr_pa == end_pa - CMDQ_INST_SIZE || curr_pa == end_pa) { /* set to this task directly */ - writel(task->pa_base >> cmdq->shift_pa, + writel(task->pa_base >> cmdq->pdata->shift, thread->base + CMDQ_THR_CURR_ADDR); } else { cmdq_task_insert_into_thread(task); smp_mb(); /* modify jump before enable thread */ } - writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->shift_pa, + writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift, thread->base + CMDQ_THR_END_ADDR); cmdq_thread_resume(thread); } @@ -461,7 +457,7 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan) } cmdq_thread_disable(cmdq, thread); - clk_bulk_disable(cmdq->gce_num, cmdq->clocks); + clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks); done: /* @@ -501,7 +497,7 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout) cmdq_thread_resume(thread); cmdq_thread_disable(cmdq, thread); - clk_bulk_disable(cmdq->gce_num, cmdq->clocks); + clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks); out: spin_unlock_irqrestore(&thread->chan->lock, flags); @@ -548,7 +544,6 @@ static int cmdq_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct cmdq *cmdq; int err, i; - struct gce_plat *plat_data; struct device_node *phandle = dev->of_node; struct device_node *node; int alias_id = 0; @@ -567,18 +562,13 @@ static int cmdq_probe(struct platform_device *pdev) if (cmdq->irq < 0) return cmdq->irq; - plat_data = (struct gce_plat *)of_device_get_match_data(dev); - if (!plat_data) { + cmdq->pdata = device_get_match_data(dev); + if (!cmdq->pdata) { dev_err(dev, "failed to get match data\n"); return -EINVAL; } - cmdq->thread_nr = plat_data->thread_nr; - cmdq->shift_pa = plat_data->shift; - cmdq->control_by_sw = plat_data->control_by_sw; - cmdq->sw_ddr_en = plat_data->sw_ddr_en; - cmdq->gce_num = plat_data->gce_num; - cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0); + cmdq->irq_mask = GENMASK(cmdq->pdata->thread_nr - 1, 0); err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED, "mtk_cmdq", cmdq); if (err < 0) { @@ -589,10 +579,10 @@ static int cmdq_probe(struct platform_device *pdev) dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n", dev, cmdq->base, cmdq->irq); - if (cmdq->gce_num > 1) { + if (cmdq->pdata->gce_num > 1) { for_each_child_of_node(phandle->parent, node) { alias_id = of_alias_get_id(node, clk_name); - if (alias_id >= 0 && alias_id < cmdq->gce_num) { + if (alias_id >= 0 && alias_id < cmdq->pdata->gce_num) { cmdq->clocks[alias_id].id = clk_names[alias_id]; cmdq->clocks[alias_id].clk = of_clk_get(node, 0); if (IS_ERR(cmdq->clocks[alias_id].clk)) { @@ -614,12 +604,12 @@ static int cmdq_probe(struct platform_device *pdev) } cmdq->mbox.dev = dev; - cmdq->mbox.chans = devm_kcalloc(dev, cmdq->thread_nr, + cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr, sizeof(*cmdq->mbox.chans), GFP_KERNEL); if (!cmdq->mbox.chans) return -ENOMEM; - cmdq->mbox.num_chans = cmdq->thread_nr; + cmdq->mbox.num_chans = cmdq->pdata->thread_nr; cmdq->mbox.ops = &cmdq_mbox_chan_ops; cmdq->mbox.of_xlate = cmdq_xlate; @@ -627,12 +617,12 @@ static int cmdq_probe(struct platform_device *pdev) cmdq->mbox.txdone_irq = false; cmdq->mbox.txdone_poll = false; - cmdq->thread = devm_kcalloc(dev, cmdq->thread_nr, + cmdq->thread = devm_kcalloc(dev, cmdq->pdata->thread_nr, sizeof(*cmdq->thread), GFP_KERNEL); if (!cmdq->thread) return -ENOMEM; - for (i = 0; i < cmdq->thread_nr; i++) { + for (i = 0; i < cmdq->pdata->thread_nr; i++) { cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE + CMDQ_THR_SIZE * i; INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list); @@ -647,7 +637,7 @@ static int cmdq_probe(struct platform_device *pdev) platform_set_drvdata(pdev, cmdq); - WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks)); + WARN_ON(clk_bulk_prepare(cmdq->pdata->gce_num, cmdq->clocks)); cmdq_init(cmdq); -- cgit v1.2.3 From a6792a0cdef0b1c2d77920246283a72537e60e94 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Thu, 10 Nov 2022 23:08:22 +0800 Subject: mailbox: zynq-ipi: fix error handling while device_register() fails If device_register() fails, it has two issues: 1. The name allocated by dev_set_name() is leaked. 2. The parent of device is not NULL, device_unregister() is called in zynqmp_ipi_free_mboxes(), it will lead a kernel crash because of removing not added device. Call put_device() to give up the reference, so the name is freed in kobject_cleanup(). Add device registered check in zynqmp_ipi_free_mboxes() to avoid null-ptr-deref. Fixes: 4981b82ba2ff ("mailbox: ZynqMP IPI mailbox controller") Signed-off-by: Yang Yingliang Signed-off-by: Jassi Brar --- drivers/mailbox/zynqmp-ipi-mailbox.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c index 31a0fa914274..12e004ff1a14 100644 --- a/drivers/mailbox/zynqmp-ipi-mailbox.c +++ b/drivers/mailbox/zynqmp-ipi-mailbox.c @@ -493,6 +493,7 @@ static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox, ret = device_register(&ipi_mbox->dev); if (ret) { dev_err(dev, "Failed to register ipi mbox dev.\n"); + put_device(&ipi_mbox->dev); return ret; } mdev = &ipi_mbox->dev; @@ -619,7 +620,8 @@ static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata) ipi_mbox = &pdata->ipi_mboxes[i]; if (ipi_mbox->dev.parent) { mbox_controller_unregister(&ipi_mbox->mbox); - device_unregister(&ipi_mbox->dev); + if (device_is_registered(&ipi_mbox->dev)) + device_unregister(&ipi_mbox->dev); } } } -- cgit v1.2.3 From 16edcfef77147748c43c9c58ce18f59c61d1c357 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Wed, 30 Nov 2022 13:58:22 +0100 Subject: mailbox: mtk-cmdq: Do not request irq until we are ready If the system comes from kexec() the peripheral might trigger an IRQ befoe we are ready for it. Triggering a crash due to an access to invalid memory. Signed-off-by: Ricardo Ribalda Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Chun-Kuang Hu Signed-off-by: Jassi Brar --- drivers/mailbox/mtk-cmdq-mailbox.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index a460ee26eb11..b18d47ea13a0 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -569,12 +569,6 @@ static int cmdq_probe(struct platform_device *pdev) } cmdq->irq_mask = GENMASK(cmdq->pdata->thread_nr - 1, 0); - err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED, - "mtk_cmdq", cmdq); - if (err < 0) { - dev_err(dev, "failed to register ISR (%d)\n", err); - return err; - } dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n", dev, cmdq->base, cmdq->irq); @@ -641,6 +635,13 @@ static int cmdq_probe(struct platform_device *pdev) cmdq_init(cmdq); + err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED, + "mtk_cmdq", cmdq); + if (err < 0) { + dev_err(dev, "failed to register ISR (%d)\n", err); + return err; + } + return 0; } -- cgit v1.2.3