usb: dwc2: Fix some error handling paths
authorChristophe JAILLET <christophe.jaillet@wanadoo.fr>
Fri, 5 May 2023 17:15:08 +0000 (19:15 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 13 May 2023 09:58:11 +0000 (18:58 +0900)
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>
drivers/usb/dwc2/platform.c

index 5aee284..5cf0255 100644 (file)
@@ -203,6 +203,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;
@@ -213,6 +218,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))
@@ -220,6 +229,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
@@ -339,9 +352,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;
 }