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.

Signed-off-by: Li Jun <jun...@nxp.com>
---
 drivers/usb/chipidea/ci.h  |  2 ++
 drivers/usb/chipidea/udc.c | 21 +++++++++++++--------
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 59e2238..6743f85 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -177,6 +177,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;
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index f88e915..be166c6 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1845,27 +1845,32 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
                if (USBi_PCI & intr) {
                        ci->gadget.speed = hw_port_is_high_speed(ci) ?
                                USB_SPEED_HIGH : USB_SPEED_FULL;
-                       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 {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to