diff options
author | Axel Lin <axel.lin@ingics.com> | 2012-11-10 21:53:20 +0800 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-11-11 20:18:32 +0100 |
commit | e38d457de7be63e6ced1ea254aa51466deb1fef0 (patch) | |
tree | 6e18c36639a0de0e0f5ad44c50b67a2adf1e20a7 | |
parent | 89377aa5156a93e73a3f7c7ccdc0d0fecf65e0d2 (diff) |
pinctrl: pinmux: Release all taken pins in pinmux_enable_setting error paths
Currently pinmux_enable_setting does not release all taken pins if
ops->enable() returns error. This patch ensures all taken pins are
released in any error paths.
Signed-off-by: Axel Lin <axel.lin@ingics.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/pinmux.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 0ef01ee2835f..1a00658b3ea0 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -409,11 +409,7 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting) dev_err(pctldev->dev, "could not request pin %d on device %s\n", pins[i], pinctrl_dev_get_name(pctldev)); - /* On error release all taken pins */ - i--; /* this pin just failed */ - for (; i >= 0; i--) - pin_free(pctldev, pins[i], NULL); - return -ENODEV; + goto err_pin_request; } } @@ -429,8 +425,26 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting) desc->mux_setting = &(setting->data.mux); } - return ops->enable(pctldev, setting->data.mux.func, - setting->data.mux.group); + ret = ops->enable(pctldev, setting->data.mux.func, + setting->data.mux.group); + + if (ret) + goto err_enable; + + return 0; + +err_enable: + for (i = 0; i < num_pins; i++) { + desc = pin_desc_get(pctldev, pins[i]); + if (desc) + desc->mux_setting = NULL; + } +err_pin_request: + /* On error release all taken pins */ + while (--i >= 0) + pin_free(pctldev, pins[i], NULL); + + return ret; } void pinmux_disable_setting(struct pinctrl_setting const *setting) |