MLK-14256 usb: chipidea: udc: update gadget state after bus resume
authorLi Jun <jun.li@nxp.com>
Fri, 3 Mar 2017 16:30:44 +0000 (00:30 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:10:54 +0000 (15:10 -0500)
Gadget state is set to be suspended when bus suspened, but not updated
after resume, this patch saves the gadget state before suspend and
restores it after resume.

Acked-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/udc.c

index 081a501..9c8d20d 100644 (file)
@@ -178,6 +178,7 @@ struct hw_bank {
  * @td_pool: allocation pool for transfer descriptors
  * @gadget: device side representation for peripheral controller
  * @driver: gadget driver
+ * @resume_state: save the state of gadget suspend from
  * @hw_ep_max: total number of endpoints supported by hardware
  * @ci_hw_ep: array of endpoints
  * @ep0_dir: ep0 direction
@@ -227,6 +228,7 @@ struct ci_hdrc {
 
        struct usb_gadget               gadget;
        struct usb_gadget_driver        *driver;
+       enum usb_device_state           resume_state;
        unsigned                        hw_ep_max;
        struct ci_hw_ep                 ci_hw_ep[ENDPT_MAX];
        u32                             ep0_dir;
index 5b4f92c..31f7ea1 100644 (file)
@@ -1892,27 +1892,32 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
                        if (ci->usb_phy)
                                usb_phy_set_event(ci->usb_phy,
                                        USB_EVENT_ENUMERATED);
-                       if (ci->suspended && ci->driver->resume) {
-                               spin_unlock(&ci->lock);
-                               ci->driver->resume(&ci->gadget);
-                               spin_lock(&ci->lock);
+                       if (ci->suspended) {
+                               if (ci->driver->resume) {
+                                       spin_unlock(&ci->lock);
+                                       ci->driver->resume(&ci->gadget);
+                                       spin_lock(&ci->lock);
+                               }
                                ci->suspended = 0;
+                               usb_gadget_set_state(&ci->gadget,
+                                               ci->resume_state);
                        }
                }
 
                if (USBi_UI  & intr)
                        isr_tr_complete_handler(ci);
 
-               if (USBi_SLI & intr) {
+               if ((USBi_SLI & intr) && !(ci->suspended)) {
+                       ci->suspended = 1;
+                       ci->resume_state = ci->gadget.state;
                        if (ci->gadget.speed != USB_SPEED_UNKNOWN &&
                            ci->driver->suspend) {
-                               ci->suspended = 1;
                                spin_unlock(&ci->lock);
                                ci->driver->suspend(&ci->gadget);
-                               usb_gadget_set_state(&ci->gadget,
-                                               USB_STATE_SUSPENDED);
                                spin_lock(&ci->lock);
                        }
+                       usb_gadget_set_state(&ci->gadget,
+                                       USB_STATE_SUSPENDED);
                }
                retval = IRQ_HANDLED;
        } else {