diff options
author | Christophe JAILLET <christophe.jaillet@wanadoo.fr> | 2023-05-05 20:15:08 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-07-19 17:21:49 +0300 |
commit | b6e30a54a5925b2b733d02cce36a17538d43f855 (patch) | |
tree | 1e385bb6486ac35b3aa44902fa1f9047452119fb /drivers/usb | |
parent | 98b6582b37da030873056a4f3ac29c56183ad952 (diff) | |
download | linux-b6e30a54a5925b2b733d02cce36a17538d43f855.tar.xz |
usb: dwc2: Fix some error handling paths
[ Upstream commit ada050c69108bc34be13ecc11f7fad0f20ebadc4 ]
dwc2_driver_probe() calls dwc2_lowlevel_hw_init() which deassert some reset
lines.
Should an error happen in dwc2_lowlevel_hw_init() after calling
reset_control_deassert() or in the probe after calling
dwc2_lowlevel_hw_init(), the reset lines remain deasserted.
Add some devm_add_action_or_reset() calls to re-assert the lines if needed.
Update the remove function accordingly.
This change is compile-tested only.
Fixes: 83f8da562f8b ("usb: dwc2: Add reset control to dwc2")
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Link: https://lore.kernel.org/r/c64537b5339342bd00f7c2152b8fc23792b9f95a.1683306479.git.christophe.jaillet@wanadoo.fr
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/dwc2/platform.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index d1589ba7d322..58f53faab340 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -175,6 +175,11 @@ int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) return ret; } +static void dwc2_reset_control_assert(void *data) +{ + reset_control_assert(data); +} + static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) { int i, ret; @@ -185,6 +190,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) "error getting reset control\n"); reset_control_deassert(hsotg->reset); + ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert, + hsotg->reset); + if (ret) + return ret; hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc"); if (IS_ERR(hsotg->reset_ecc)) @@ -192,6 +201,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) "error getting reset control for ecc\n"); reset_control_deassert(hsotg->reset_ecc); + ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert, + hsotg->reset_ecc); + if (ret) + return ret; /* * Attempt to find a generic PHY, then look for an old style @@ -306,9 +319,6 @@ static int dwc2_driver_remove(struct platform_device *dev) if (hsotg->ll_hw_enabled) dwc2_lowlevel_hw_disable(hsotg); - reset_control_assert(hsotg->reset); - reset_control_assert(hsotg->reset_ecc); - return 0; } |