MLK-20343 usb: chipidea: udc: using structure ci_hdrc device for runtime PM
authorPeter Chen <peter.chen@nxp.com>
Wed, 14 Nov 2018 08:43:52 +0000 (16:43 +0800)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
At current code, it doesn't maintain ci->gadget.dev's runtime PM
status well. Eg, after system resume, call pm_runtime_put_sync for
ci->dev will cause ci->dev's runtime suspend is called if its
power.usage is 0 even the power.usage is 1 for its child ci->gadget.dev.
at that time. It causes the oops this ticket describes that visiting
clock without AHB clock.

To fix this issue, we use ci_hdrc device instead of ci->gadget.dev
for runtime PM APIs at udc driver, in the way, we handle runtime
PM APIs for single device structure.

Reviewed-by: Jun Li <jun.li@nxp.com>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
(cherry picked from commit d436b3a0a81b073b195d0ad29e7a4f39a1a532f3)
Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
drivers/usb/chipidea/udc.c

index a81eefc..6ea0c30 100644 (file)
@@ -1657,12 +1657,12 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on)
        if (ci_otg_is_fsm_mode(ci) || ci->role == CI_ROLE_HOST)
                return 0;
 
-       pm_runtime_get_sync(&ci->gadget.dev);
+       pm_runtime_get_sync(ci->dev);
        if (is_on)
                hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
        else
                hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
-       pm_runtime_put_sync(&ci->gadget.dev);
+       pm_runtime_put_sync(ci->dev);
 
        return 0;
 }
@@ -1839,7 +1839,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
                        CI_HDRC_CONTROLLER_STOPPED_EVENT);
                _gadget_stop_activity(&ci->gadget);
                spin_lock_irqsave(&ci->lock, flags);
-               pm_runtime_put(&ci->gadget.dev);
+               pm_runtime_put(ci->dev);
        }
 
        ci->driver = NULL;
@@ -1974,9 +1974,6 @@ static int udc_start(struct ci_hdrc *ci)
        if (retval)
                goto destroy_eps;
 
-       pm_runtime_no_callbacks(&ci->gadget.dev);
-       pm_runtime_enable(&ci->gadget.dev);
-
        return retval;
 
 destroy_eps:
@@ -2037,7 +2034,7 @@ void ci_hdrc_gadget_connect(struct usb_gadget *gadget, int is_active)
        struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
 
        if (is_active) {
-               pm_runtime_get_sync(&gadget->dev);
+               pm_runtime_get_sync(ci->dev);
                hw_device_reset(ci);
                hw_device_state(ci, ci->ep0out->qh.dma);
                usb_gadget_set_state(gadget, USB_STATE_POWERED);
@@ -2051,7 +2048,7 @@ void ci_hdrc_gadget_connect(struct usb_gadget *gadget, int is_active)
                        ci->platdata->notify_event(ci,
                        CI_HDRC_CONTROLLER_STOPPED_EVENT);
                _gadget_stop_activity(gadget);
-               pm_runtime_put_sync(&gadget->dev);
+               pm_runtime_put_sync(ci->dev);
                usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
        }
 }