From: Axel Lin Date: Fri, 30 Sep 2011 13:08:34 +0000 (+0800) Subject: pinctrl: fix pinctrl_register error handling X-Git-Tag: next-20111011~4^2~1 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=06b080e3d8b849213b827b23f84eb90c21426b02;p=karo-tx-linux.git pinctrl: fix pinctrl_register error handling 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 [Rebased to v9 patchset] Signed-off-by: Linus Walleij --- diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index ff0c68c41f46..d269327bd04b 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -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);