usb: dwc2: rework initialization of host and gadget in dual-role mode
authorMarek Szyprowski <m.szyprowski@samsung.com>
Tue, 10 Mar 2015 12:41:10 +0000 (13:41 +0100)
committerFelipe Balbi <balbi@ti.com>
Thu, 12 Mar 2015 17:18:49 +0000 (12:18 -0500)
If device is configured to work only in HOST or DEVICE mode, there is
no point in initializing both subdrivers. This patch also fixes
resource leakage if host subdriver fails to initialize.

Acked-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/dwc2/core.h
drivers/usb/dwc2/platform.c

index f74304b12652062d43335e266812fe4cb645a822..836c012c770788d2d7e23109660d621939dff86b 100644 (file)
@@ -593,6 +593,8 @@ struct dwc2_hsotg {
        struct dwc2_core_params *core_params;
        enum usb_otg_state op_state;
        enum usb_dr_mode dr_mode;
+       unsigned int hcd_enabled:1;
+       unsigned int gadget_enabled:1;
 
        struct phy *phy;
        struct usb_phy *uphy;
index ae095f009b4f792b508ee2e713f3268359a27b42..185663e0b5f439af16065989a27ae74cc31a59b6 100644 (file)
@@ -121,8 +121,10 @@ static int dwc2_driver_remove(struct platform_device *dev)
 {
        struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);
 
-       dwc2_hcd_remove(hsotg);
-       s3c_hsotg_remove(hsotg);
+       if (hsotg->hcd_enabled)
+               dwc2_hcd_remove(hsotg);
+       if (hsotg->gadget_enabled)
+               s3c_hsotg_remove(hsotg);
 
        return 0;
 }
@@ -234,12 +236,23 @@ static int dwc2_driver_probe(struct platform_device *dev)
 
        spin_lock_init(&hsotg->lock);
        mutex_init(&hsotg->init_mutex);
-       retval = dwc2_gadget_init(hsotg, irq);
-       if (retval)
-               return retval;
-       retval = dwc2_hcd_init(hsotg, irq, params);
-       if (retval)
-               return retval;
+
+       if (hsotg->dr_mode != USB_DR_MODE_HOST) {
+               retval = dwc2_gadget_init(hsotg, irq);
+               if (retval)
+                       return retval;
+               hsotg->gadget_enabled = 1;
+       }
+
+       if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
+               retval = dwc2_hcd_init(hsotg, irq, params);
+               if (retval) {
+                       if (hsotg->gadget_enabled)
+                               s3c_hsotg_remove(hsotg);
+                       return retval;
+               }
+               hsotg->hcd_enabled = 1;
+       }
 
        platform_set_drvdata(dev, hsotg);