]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
pinmux: fix pinctrl_register error handling
authorAxel Lin <axel.lin@gmail.com>
Fri, 30 Sep 2011 13:08:34 +0000 (21:08 +0800)
committerLinus Walleij <linus.walleij@stericsson.com>
Wed, 5 Oct 2011 13:49:00 +0000 (15:49 +0200)
If device_register fails, current code kfree pctldev
multiple times. current code calls "put_device(&pctldev->dev);
kfree(pctldev);" before and after goto out_err.

The correct fix should be:
If device_register fails, we just need to call
put_device(&pctldev->dev); Since we have "release" callback
in pinctrl_type, we don't need to call kfree(pctldev) after
put_device().

If pinctrl_register_pins fails, we need to delete the
successfully registerd device from system by calling
device_del().

In pinctrl_unregister(), calling
device_unregister(&pctldev->dev) will free pctldev (by the
release callback).

We should not call kfree(pctldev) after device_unregister().

Signed-off-by: Axel Lin <axel.lin@gmail.com>
[Rebased to v9 patchset]
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/core.c

index ff0c68c41f46bb50b9f01fb0eec8ee1f0c3d0083..d269327bd04b53ba9e14476791425036d2e2ac9e 100644 (file)
@@ -537,9 +537,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
        ret = device_register(&pctldev->dev);
        if (ret != 0) {
                pr_err("error in device registration\n");
-               put_device(&pctldev->dev);
-               kfree(pctldev);
-               goto out_err;
+               goto out_reg_dev_err;
        }
        dev_set_drvdata(&pctldev->dev, pctldev);
 
@@ -551,7 +549,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
                pr_err("error during pin registration\n");
                pinctrl_free_pindescs(pctldev, pctldesc->pins,
                                      pctldesc->npins);
-               goto out_err;
+               goto out_reg_pins_err;
        }
 
        pinctrl_init_device_debugfs(pctldev);
@@ -561,7 +559,9 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
        pinmux_hog_maps(pctldev);
        return pctldev;
 
-out_err:
+out_reg_pins_err:
+       device_del(&pctldev->dev);
+out_reg_dev_err:
        put_device(&pctldev->dev);
        return ERR_PTR(ret);
 }
@@ -583,11 +583,10 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
        mutex_lock(&pinctrldev_list_mutex);
        list_del(&pctldev->node);
        mutex_unlock(&pinctrldev_list_mutex);
-       device_unregister(&pctldev->dev);
        /* Destroy descriptor tree */
        pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
                              pctldev->desc->npins);
-       kfree(pctldev);
+       device_unregister(&pctldev->dev);
 }
 EXPORT_SYMBOL_GPL(pinctrl_unregister);