pwm: omap-dmtimer: Simplify error handling
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Mon, 11 Nov 2019 09:03:55 +0000 (10:03 +0100)
committerThierry Reding <thierry.reding@gmail.com>
Mon, 20 Jan 2020 11:31:19 +0000 (12:31 +0100)
Instead of doing error handling in the middle of ->probe(), move error
handling and freeing the reference to timer to the end.

This fixes a resource leak as dm_timer wasn't freed when allocating
*omap failed.

Implementation note: The put: label was never reached without a goto and
ret being unequal to 0, so the removed return statement is fine.

Fixes: 6604c6556db9 ("pwm: Add PWM driver for OMAP using dual-mode timers")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
drivers/pwm/pwm-omap-dmtimer.c

index bdf94c78655f120f90c8139b0f9443725781876a..e36fcad668a68de84382c7e76b6ac42c86e89ba9 100644 (file)
@@ -298,15 +298,10 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
                goto put;
        }
 
-put:
-       of_node_put(timer);
-       if (ret < 0)
-               return ret;
-
        omap = devm_kzalloc(&pdev->dev, sizeof(*omap), GFP_KERNEL);
        if (!omap) {
-               pdata->free(dm_timer);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err_alloc_omap;
        }
 
        omap->pdata = pdata;
@@ -339,13 +334,28 @@ put:
        ret = pwmchip_add(&omap->chip);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to register PWM\n");
-               omap->pdata->free(omap->dm_timer);
-               return ret;
+               goto err_pwmchip_add;
        }
 
+       of_node_put(timer);
+
        platform_set_drvdata(pdev, omap);
 
        return 0;
+
+err_pwmchip_add:
+
+       /*
+        * *omap is allocated using devm_kzalloc,
+        * so no free necessary here
+        */
+err_alloc_omap:
+
+       pdata->free(dm_timer);
+put:
+       of_node_put(timer);
+
+       return ret;
 }
 
 static int pwm_omap_dmtimer_remove(struct platform_device *pdev)