fix hcd panic when xacterr happen
authoryangkai <yk@rock-chips.com>
Sat, 2 Jun 2012 08:16:38 +0000 (16:16 +0800)
committeryangkai <yk@rock-chips.com>
Sat, 2 Jun 2012 08:16:38 +0000 (16:16 +0800)
drivers/usb/dwc_otg/dwc_otg_hcd.c
drivers/usb/dwc_otg/dwc_otg_hcd_intr.c

index ddf44bac2dab99a4f52f5140d0bdf627372d641a..378f395f35f6044ba2d474df48a551190fd04c52 100755 (executable)
@@ -1595,7 +1595,6 @@ int dwc_otg_hcd_urb_dequeue(struct usb_hcd *_hcd, struct urb *_urb, int _status)
     if (urb_qtd == qh->qtd_in_process) {
            /* The QTD is in process (it has been assigned to a channel). */
            if (dwc_otg_hcd->flags.b.port_connect_status) {
-            DWC_PRINT("%s urb %p in process\n", __func__, _urb);
 
                    /*
                     * If still connected (i.e. in host mode), halt the
@@ -2290,7 +2289,9 @@ int dwc_otg_hcd_hub_control(struct usb_hcd *_hcd,
                        hprt0.b.prtres = 1;
                        dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
                        /* Clear Resume bit */
+            spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
                        mdelay (100);
+            spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
                        hprt0.b.prtres = 0;
                        dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
                        break;
@@ -2477,7 +2478,7 @@ int dwc_otg_hcd_hub_control(struct usb_hcd *_hcd,
                         }
                         hprt0.d32 = dwc_otg_read_hprt0 (core_if);
                         hprt0.b.prtsusp = 1;
-                       dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+                                   dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
                         //DWC_PRINT( "SUSPEND: HPRT0=%0x\n", hprt0.d32);       
                         /* Suspend the Phy Clock */
                         {
@@ -2488,7 +2489,9 @@ int dwc_otg_hcd_hub_control(struct usb_hcd *_hcd,
                         
                         /* For HNP the bus must be suspended for at least 200ms.*/
                         if (_hcd->self.b_hnp_enable) {
+                                spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
                                 mdelay(200);
+                                spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
                                 //DWC_PRINT( "SUSPEND: wait complete! (%d)\n", _hcd->state);
                         }
                        break;
index 255e4172bc513fb8d76cd39fc809fc20a5338458..ea4e1581188ffd68813ef68134f7d842f0f7a90b 100755 (executable)
@@ -821,14 +821,19 @@ static void release_channel(dwc_otg_hcd_t *_hcd,
        dwc_otg_transaction_type_e tr_type;
        int free_qtd;
        int continue_trans = 1;
-
-    if(((uint32_t) _qtd & 0xf0000000)==0){
-        DWC_PRINT("%s qtd %p, status %d\n", __func__, _qtd, _halt_status);
-        goto cleanup;
-    }
-    if(((uint32_t) _qtd->urb & 0xf0000000)==0){
-        DWC_PRINT("%s urb %p, status %d\n", __func__, _qtd->urb, _halt_status);
-        goto cleanup;
+    if(_halt_status != DWC_OTG_HC_XFER_URB_DEQUEUE){
+        if(((uint32_t) _qtd & 0xf0000000)==0){
+            DWC_PRINT("%s qtd %p, status %d\n", __func__, _qtd, _halt_status);
+            goto cleanup;
+        }
+        if(((uint32_t) _qtd & 0x80000000)==0){
+            DWC_PRINT("%s qtd %p, status %d 1\n", __func__, _qtd, _halt_status);
+            goto cleanup;
+        }
+        if(((uint32_t) _qtd->urb & 0xf0000000)==0){
+            DWC_PRINT("%s qtd %p urb %p, status %d\n", __func__, _qtd, _qtd->urb, _halt_status);
+            goto cleanup;
+        }
     }
         
        DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d\n",
@@ -1566,10 +1571,21 @@ static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t *_hcd,
     dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
        DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
                    "Transaction Error--\n", _hc->hc_num);
+    if (list_empty(&_hc->qh->qh_list_entry)){
+        DWC_PRINT("%s qh empty\n", __func__);
+        goto out;
+    }
     
-    if((_qtd==NULL)||(_qtd->urb == NULL))
-    {
-               DWC_PRINT("%s qtd->urb %p NULL\n", __func__, _qtd);
+    if(((uint32_t) _qtd & 0xf0000000)==0){
+        DWC_PRINT("%s qtd %p\n", __func__, _qtd);
+        goto out;
+    }
+    if(((uint32_t) _qtd & 0x80000000)==0){
+        DWC_PRINT("%s qtd %p 1\n", __func__, _qtd);
+        goto out;
+    }
+    if(((uint32_t) _qtd->urb & 0xf0000000)==0){
+        DWC_PRINT("%s qtd %p urb %p\n", __func__,_qtd, _qtd->urb);
         goto out;
     }
        switch (usb_pipetype(_qtd->urb->pipe)) {