USB: fix usb host hot-plug bug.
authorwlf <wulf@rock-chips.com>
Mon, 9 Jun 2014 01:40:06 +0000 (09:40 +0800)
committerwlf <wulf@rock-chips.com>
Mon, 9 Jun 2014 01:40:06 +0000 (09:40 +0800)
drivers/usb/dwc_otg_310/dwc_otg_hcd.c
drivers/usb/dwc_otg_310/dwc_otg_hcd_intr.c

index 06fc33531e1164fd6e6f9d9f960e6f58d7fd490e..30a8bf1fa32cb9af86d694ae181c2ada69fc6718 100755 (executable)
@@ -276,7 +276,21 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p)
 {
        gintsts_data_t intr;
        dwc_otg_hcd_t *dwc_otg_hcd = p;
+       hprt0_data_t hprt0;
+
+       dwc_otg_hcd->non_periodic_qh_ptr = &dwc_otg_hcd->non_periodic_sched_active;
+       dwc_otg_hcd->non_periodic_channels = 0;
+       dwc_otg_hcd->periodic_channels = 0;
 
+       hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
+       /* In some case, we don't disconnect a usb device, but
+        * disconnect intr was triggered, so check hprt0 here. */
+       if ((!hprt0.b.prtenchng)
+           && (hprt0.d32 != 0x1000)
+           && (hprt0.d32 != 0x1100)) {
+               DWC_PRINTF("%s: hprt0 = 0x%08x\n", __func__, hprt0.d32);
+               return 1;
+       }
        /*
         * Set status flags for the hub driver.
         */
@@ -313,6 +327,7 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p)
                /** Delete timers if become device */
                del_timers(dwc_otg_hcd);
                dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
+               goto out;
        }
 
        /* Respond with an error status to all URBs in the schedule. */
@@ -385,6 +400,7 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p)
                }
        }
 
+out:
        if (dwc_otg_hcd->fops->disconnect) {
                dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
        }
index fb6de91b5a5ddd5a183528bf8807bd9ae8594d6a..9065863c30483965b43dbfb51b3eb29c04e11efe 100755 (executable)
@@ -48,7 +48,6 @@
 int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t *dwc_otg_hcd)
 {
        int retval = 0;
-       dwc_irqflags_t flags;
 
        dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
        gintsts_data_t gintsts;
@@ -65,12 +64,12 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t *dwc_otg_hcd)
        if (core_if->hibernation_suspend == 1) {
                return retval;
        }
-       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
+       DWC_SPINLOCK(dwc_otg_hcd->lock);
        /* Check if HOST Mode */
        if (dwc_otg_is_host_mode(core_if)) {
                gintsts.d32 = dwc_otg_read_core_intr(core_if);
                if (!gintsts.d32) {
-                       DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
+                       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
                        return 0;
                }
 #ifdef DEBUG
@@ -139,7 +138,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t *dwc_otg_hcd)
 #endif
 
        }
-       DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
+       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
        return retval;
 }