lkml.org 
[lkml]   [2022]   [Sep]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 41/79] soc: brcmstb: pm-arm: Fix refcount leak and __iomem leak bugs
    Date
    From: Liang He <windhl@126.com>

    [ Upstream commit 1085f5080647f0c9f357c270a537869191f7f2a1 ]

    In brcmstb_pm_probe(), there are two kinds of leak bugs:

    (1) we need to add of_node_put() when for_each__matching_node() breaks
    (2) we need to add iounmap() for each iomap in fail path

    Fixes: 0b741b8234c8 ("soc: bcm: brcmstb: Add support for S2/S3/S5 suspend states (ARM)")
    Signed-off-by: Liang He <windhl@126.com>
    Link: https://lore.kernel.org/r/20220707015620.306468-1-windhl@126.com
    Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/soc/bcm/brcmstb/pm/pm-arm.c | 50 ++++++++++++++++++++++-------
    1 file changed, 39 insertions(+), 11 deletions(-)

    diff --git a/drivers/soc/bcm/brcmstb/pm/pm-arm.c b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
    index c6ec7d95bcfcc..722fd54e537cf 100644
    --- a/drivers/soc/bcm/brcmstb/pm/pm-arm.c
    +++ b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
    @@ -681,13 +681,14 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
    const struct of_device_id *of_id = NULL;
    struct device_node *dn;
    void __iomem *base;
    - int ret, i;
    + int ret, i, s;

    /* AON ctrl registers */
    base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 0, NULL);
    if (IS_ERR(base)) {
    pr_err("error mapping AON_CTRL\n");
    - return PTR_ERR(base);
    + ret = PTR_ERR(base);
    + goto aon_err;
    }
    ctrl.aon_ctrl_base = base;

    @@ -697,8 +698,10 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
    /* Assume standard offset */
    ctrl.aon_sram = ctrl.aon_ctrl_base +
    AON_CTRL_SYSTEM_DATA_RAM_OFS;
    + s = 0;
    } else {
    ctrl.aon_sram = base;
    + s = 1;
    }

    writel_relaxed(0, ctrl.aon_sram + AON_REG_PANIC);
    @@ -708,7 +711,8 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
    (const void **)&ddr_phy_data);
    if (IS_ERR(base)) {
    pr_err("error mapping DDR PHY\n");
    - return PTR_ERR(base);
    + ret = PTR_ERR(base);
    + goto ddr_phy_err;
    }
    ctrl.support_warm_boot = ddr_phy_data->supports_warm_boot;
    ctrl.pll_status_offset = ddr_phy_data->pll_status_offset;
    @@ -728,17 +732,20 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
    for_each_matching_node(dn, ddr_shimphy_dt_ids) {
    i = ctrl.num_memc;
    if (i >= MAX_NUM_MEMC) {
    + of_node_put(dn);
    pr_warn("too many MEMCs (max %d)\n", MAX_NUM_MEMC);
    break;
    }

    base = of_io_request_and_map(dn, 0, dn->full_name);
    if (IS_ERR(base)) {
    + of_node_put(dn);
    if (!ctrl.support_warm_boot)
    break;

    pr_err("error mapping DDR SHIMPHY %d\n", i);
    - return PTR_ERR(base);
    + ret = PTR_ERR(base);
    + goto ddr_shimphy_err;
    }
    ctrl.memcs[i].ddr_shimphy_base = base;
    ctrl.num_memc++;
    @@ -749,14 +756,18 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
    for_each_matching_node(dn, brcmstb_memc_of_match) {
    base = of_iomap(dn, 0);
    if (!base) {
    + of_node_put(dn);
    pr_err("error mapping DDR Sequencer %d\n", i);
    - return -ENOMEM;
    + ret = -ENOMEM;
    + goto brcmstb_memc_err;
    }

    of_id = of_match_node(brcmstb_memc_of_match, dn);
    if (!of_id) {
    iounmap(base);
    - return -EINVAL;
    + of_node_put(dn);
    + ret = -EINVAL;
    + goto brcmstb_memc_err;
    }

    ddr_seq_data = of_id->data;
    @@ -776,21 +787,24 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
    dn = of_find_matching_node(NULL, sram_dt_ids);
    if (!dn) {
    pr_err("SRAM not found\n");
    - return -EINVAL;
    + ret = -EINVAL;
    + goto brcmstb_memc_err;
    }

    ret = brcmstb_init_sram(dn);
    of_node_put(dn);
    if (ret) {
    pr_err("error setting up SRAM for PM\n");
    - return ret;
    + goto brcmstb_memc_err;
    }

    ctrl.pdev = pdev;

    ctrl.s3_params = kmalloc(sizeof(*ctrl.s3_params), GFP_KERNEL);
    - if (!ctrl.s3_params)
    - return -ENOMEM;
    + if (!ctrl.s3_params) {
    + ret = -ENOMEM;
    + goto s3_params_err;
    + }
    ctrl.s3_params_pa = dma_map_single(&pdev->dev, ctrl.s3_params,
    sizeof(*ctrl.s3_params),
    DMA_TO_DEVICE);
    @@ -810,7 +824,21 @@ static int brcmstb_pm_probe(struct platform_device *pdev)

    out:
    kfree(ctrl.s3_params);
    -
    +s3_params_err:
    + iounmap(ctrl.boot_sram);
    +brcmstb_memc_err:
    + for (i--; i >= 0; i--)
    + iounmap(ctrl.memcs[i].ddr_ctrl);
    +ddr_shimphy_err:
    + for (i = 0; i < ctrl.num_memc; i++)
    + iounmap(ctrl.memcs[i].ddr_shimphy_base);
    +
    + iounmap(ctrl.memcs[0].ddr_phy_base);
    +ddr_phy_err:
    + iounmap(ctrl.aon_ctrl_base);
    + if (s)
    + iounmap(ctrl.aon_sram);
    +aon_err:
    pr_warn("PM: initialization failed with code %d\n", ret);

    return ret;
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-09-13 16:47    [W:3.541 / U:0.120 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site