lkml.org 
[lkml]   [2022]   [Oct]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 6.0 210/862] MIPS: SGI-IP30: Fix platform-device leak in bridge_platform_create()
    Date
    From: Lin Yujun <linyujun809@huawei.com>

    [ Upstream commit 1e6d11fe72e311c1989991ee318d239f650fa318 ]

    In error case in bridge_platform_create after calling
    platform_device_add()/platform_device_add_data()/
    platform_device_add_resources(), release the failed
    'pdev' or it will be leak, call platform_device_put()
    to fix this problem.

    Besides, 'pdev' is divided into 'pdev_wd' and 'pdev_bd',
    use platform_device_unregister() to release sgi_w1
    resources when xtalk-bridge registration fails.

    Fixes: fd27234f24ae ("MIPS: add support for SGI Octane (IP30)")
    Signed-off-by: Lin Yujun <linyujun809@huawei.com>
    Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    arch/mips/sgi-ip30/ip30-xtalk.c | 70 +++++++++++++++++++++++----------
    1 file changed, 50 insertions(+), 20 deletions(-)

    diff --git a/arch/mips/sgi-ip30/ip30-xtalk.c b/arch/mips/sgi-ip30/ip30-xtalk.c
    index 8129524421cb..7ceb2b23ea1c 100644
    --- a/arch/mips/sgi-ip30/ip30-xtalk.c
    +++ b/arch/mips/sgi-ip30/ip30-xtalk.c
    @@ -40,12 +40,15 @@ static void bridge_platform_create(int widget, int masterwid)
    {
    struct xtalk_bridge_platform_data *bd;
    struct sgi_w1_platform_data *wd;
    - struct platform_device *pdev;
    + struct platform_device *pdev_wd;
    + struct platform_device *pdev_bd;
    struct resource w1_res;

    wd = kzalloc(sizeof(*wd), GFP_KERNEL);
    - if (!wd)
    - goto no_mem;
    + if (!wd) {
    + pr_warn("xtalk:%x bridge create out of memory\n", widget);
    + return;
    + }

    snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx",
    IP30_SWIN_BASE(widget));
    @@ -56,24 +59,35 @@ static void bridge_platform_create(int widget, int masterwid)
    w1_res.end = w1_res.start + 3;
    w1_res.flags = IORESOURCE_MEM;

    - pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
    - if (!pdev) {
    - kfree(wd);
    - goto no_mem;
    + pdev_wd = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
    + if (!pdev_wd) {
    + pr_warn("xtalk:%x bridge create out of memory\n", widget);
    + goto err_kfree_wd;
    + }
    + if (platform_device_add_resources(pdev_wd, &w1_res, 1)) {
    + pr_warn("xtalk:%x bridge failed to add platform resources.\n", widget);
    + goto err_put_pdev_wd;
    + }
    + if (platform_device_add_data(pdev_wd, wd, sizeof(*wd))) {
    + pr_warn("xtalk:%x bridge failed to add platform data.\n", widget);
    + goto err_put_pdev_wd;
    + }
    + if (platform_device_add(pdev_wd)) {
    + pr_warn("xtalk:%x bridge failed to add platform device.\n", widget);
    + goto err_put_pdev_wd;
    }
    - platform_device_add_resources(pdev, &w1_res, 1);
    - platform_device_add_data(pdev, wd, sizeof(*wd));
    /* platform_device_add_data() duplicates the data */
    kfree(wd);
    - platform_device_add(pdev);

    bd = kzalloc(sizeof(*bd), GFP_KERNEL);
    - if (!bd)
    - goto no_mem;
    - pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
    - if (!pdev) {
    - kfree(bd);
    - goto no_mem;
    + if (!bd) {
    + pr_warn("xtalk:%x bridge create out of memory\n", widget);
    + goto err_unregister_pdev_wd;
    + }
    + pdev_bd = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
    + if (!pdev_bd) {
    + pr_warn("xtalk:%x bridge create out of memory\n", widget);
    + goto err_kfree_bd;
    }

    bd->bridge_addr = IP30_RAW_SWIN_BASE(widget);
    @@ -93,15 +107,31 @@ static void bridge_platform_create(int widget, int masterwid)
    bd->io.flags = IORESOURCE_IO;
    bd->io_offset = IP30_SWIN_BASE(widget);

    - platform_device_add_data(pdev, bd, sizeof(*bd));
    + if (platform_device_add_data(pdev_bd, bd, sizeof(*bd))) {
    + pr_warn("xtalk:%x bridge failed to add platform data.\n", widget);
    + goto err_put_pdev_bd;
    + }
    + if (platform_device_add(pdev_bd)) {
    + pr_warn("xtalk:%x bridge failed to add platform device.\n", widget);
    + goto err_put_pdev_bd;
    + }
    /* platform_device_add_data() duplicates the data */
    kfree(bd);
    - platform_device_add(pdev);
    pr_info("xtalk:%x bridge widget\n", widget);
    return;

    -no_mem:
    - pr_warn("xtalk:%x bridge create out of memory\n", widget);
    +err_put_pdev_bd:
    + platform_device_put(pdev_bd);
    +err_kfree_bd:
    + kfree(bd);
    +err_unregister_pdev_wd:
    + platform_device_unregister(pdev_wd);
    + return;
    +err_put_pdev_wd:
    + platform_device_put(pdev_wd);
    +err_kfree_wd:
    + kfree(wd);
    + return;
    }

    static unsigned int __init xbow_widget_active(s8 wid)
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-10-19 10:56    [W:4.034 / U:0.128 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site