media: platform: mtk-mdp3: fix error handling in mdp_cmdq_send()
authorMoudy Ho <moudy.ho@mediatek.com>
Thu, 20 Oct 2022 07:17:58 +0000 (15:17 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 31 Dec 2022 12:32:08 +0000 (13:32 +0100)
[ Upstream commit 64e0a0804b1a7a77ee364f44ffa6a8e0e7b157d2 ]

Increase and refine the goto label in mdp_cmdq_send() to avoid
double free and facilitate traceability.
Also, remove redundant work queue event in blocking function
mdp_cmdq_send().

Fixes: 61890ccaefaf ("media: platform: mtk-mdp3: add MediaTek MDP3 driver")
Signed-off-by: Moudy Ho <moudy.ho@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c

index 86c0546..e194dec 100644 (file)
@@ -252,10 +252,9 @@ static int mdp_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt,
        dma_addr_t dma_addr;
 
        pkt->va_base = kzalloc(size, GFP_KERNEL);
-       if (!pkt->va_base) {
-               kfree(pkt);
+       if (!pkt->va_base)
                return -ENOMEM;
-       }
+
        pkt->buf_size = size;
        pkt->cl = (void *)client;
 
@@ -368,25 +367,30 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
        cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
        if (!cmd) {
                ret = -ENOMEM;
-               goto err_cmdq_data;
+               goto err_cancel_job;
        }
 
-       if (mdp_cmdq_pkt_create(mdp->cmdq_clt, &cmd->pkt, SZ_16K)) {
-               ret = -ENOMEM;
-               goto err_cmdq_data;
-       }
+       ret = mdp_cmdq_pkt_create(mdp->cmdq_clt, &cmd->pkt, SZ_16K);
+       if (ret)
+               goto err_free_cmd;
 
        comps = kcalloc(param->config->num_components, sizeof(*comps),
                        GFP_KERNEL);
        if (!comps) {
                ret = -ENOMEM;
-               goto err_cmdq_data;
+               goto err_destroy_pkt;
        }
 
        path = kzalloc(sizeof(*path), GFP_KERNEL);
        if (!path) {
                ret = -ENOMEM;
-               goto err_cmdq_data;
+               goto err_free_comps;
+       }
+
+       ret = mtk_mutex_prepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
+       if (ret) {
+               dev_err(dev, "Fail to enable mutex clk\n");
+               goto err_free_path;
        }
 
        path->mdp_dev = mdp;
@@ -406,15 +410,13 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
        ret = mdp_path_ctx_init(mdp, path);
        if (ret) {
                dev_err(dev, "mdp_path_ctx_init error\n");
-               goto err_cmdq_data;
+               goto err_free_path;
        }
 
-       mtk_mutex_prepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
-
        ret = mdp_path_config(mdp, cmd, path);
        if (ret) {
                dev_err(dev, "mdp_path_config error\n");
-               goto err_cmdq_data;
+               goto err_free_path;
        }
        cmdq_pkt_finalize(&cmd->pkt);
 
@@ -433,7 +435,7 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
        ret = mdp_comp_clocks_on(&mdp->pdev->dev, cmd->comps, cmd->num_comps);
        if (ret) {
                dev_err(dev, "comp %d failed to enable clock!\n", ret);
-               goto err_clock_off;
+               goto err_free_path;
        }
 
        dma_sync_single_for_device(mdp->cmdq_clt->chan->mbox->dev,
@@ -450,17 +452,20 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
        return 0;
 
 err_clock_off:
-       mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
        mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
                            cmd->num_comps);
-err_cmdq_data:
+err_free_path:
+       mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
        kfree(path);
-       atomic_dec(&mdp->job_count);
-       wake_up(&mdp->callback_wq);
-       if (cmd && cmd->pkt.buf_size > 0)
-               mdp_cmdq_pkt_destroy(&cmd->pkt);
+err_free_comps:
        kfree(comps);
+err_destroy_pkt:
+       mdp_cmdq_pkt_destroy(&cmd->pkt);
+err_free_cmd:
        kfree(cmd);
+err_cancel_job:
+       atomic_dec(&mdp->job_count);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(mdp_cmdq_send);