usb: dwc_otg: change method of checking urb dequeue status
authorlyz <lyz@rock-chips.com>
Wed, 11 Mar 2015 09:44:14 +0000 (17:44 +0800)
committerlyz <lyz@rock-chips.com>
Mon, 16 Mar 2015 08:41:43 +0000 (16:41 +0800)
According to commit e9df41c5c, change dwc_otg driver to call
usb_hcd_link_urb_to_ep() and usb_hcd_unlink_urb_from_ep() routine
for checking urb dequeue status instead check for null pointer
by hcd driver to test address.

TEST:
1.rk3126 run host/device change script for 10000 times

drivers/usb/dwc_otg_310/dwc_otg_hcd.c
drivers/usb/dwc_otg_310/dwc_otg_hcd_intr.c
drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c

index 07845a23fc262a196f2da7c920cdc104fd42bff7..ff123682de68a389126ab9975d06096efca84e36 100755 (executable)
@@ -563,7 +563,7 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t *hcd,
        dwc_otg_qtd_t *urb_qtd;
 
        urb_qtd = dwc_otg_urb->qtd;
-       if (((uint32_t) urb_qtd & 0xf0000000) == 0) {
+       if (!urb_qtd) {
                DWC_PRINTF("%s error: urb_qtd is %p dwc_otg_urb %p!!!\n",
                           __func__, urb_qtd, dwc_otg_urb);
                return 0;
index e1dccb1a7a220261f75ef475f6f915b40b386cd6..a7bbaaeeeacd77c232ceb760c2283bebf39e5be4 100755 (executable)
@@ -837,26 +837,6 @@ static void release_channel(dwc_otg_hcd_t *hcd,
        DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d\n",
                    __func__, hc->hc_num, halt_status);
 
-       if (halt_status != DWC_OTG_HC_XFER_URB_DEQUEUE) {
-               if (((uint32_t) qtd & 0xf0000000) == 0) {
-                       DWC_PRINTF("%s error: qtd %p, status %d 0!!!\n",
-                                  __func__, qtd, halt_status);
-                       goto cleanup;
-               }
-
-               if (((uint32_t) qtd & 0x80000000) == 0) {
-                       DWC_PRINTF("%s error: qtd %p, status %d 1!!!\n",
-                                  __func__, qtd, halt_status);
-                       goto cleanup;
-               }
-
-               if (((uint32_t) qtd->urb & 0xf0000000) == 0) {
-                       DWC_PRINTF("%s qtd %p urb %p, status %d\n", __func__,
-                                  qtd, qtd->urb, halt_status);
-                       goto cleanup;
-               }
-       }
-
        switch (halt_status) {
        case DWC_OTG_HC_XFER_URB_COMPLETE:
                free_qtd = 1;
@@ -1129,17 +1109,15 @@ static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t *hcd,
        DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
                    "Transfer Complete--\n", hc->hc_num);
 
-       if (((uint32_t) qtd & 0xf0000000) == 0) {
-               DWC_PRINTF("%s qtd %p\n", __func__, qtd);
-               release_channel(hcd, hc, qtd, hc->halt_status);
-               return 1;
+       if (!qtd) {
+               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_DEQUEUE);
+               goto handle_xfercomp_done;
        }
 
        urb = qtd->urb;
-       if (((uint32_t) urb & 0xf0000000) == 0) {
-               DWC_PRINTF("%s qtd %p, urb %p\n", __func__, qtd, urb);
-               release_channel(hcd, hc, qtd, hc->halt_status);
-               return 1;
+       if (!urb) {
+               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_DEQUEUE);
+               goto handle_xfercomp_done;
        }
 
        pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
index 24464797a2a6f51aaf297e10636045a69f4f56b6..28d468374e37f8fc554317baf04c031513b9bca8 100755 (executable)
@@ -328,6 +328,8 @@ static int _complete(dwc_otg_hcd_t *hcd, void *urb_handle,
 
        DWC_FREE(dwc_otg_urb);
 
+       usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
+
        DWC_SPINUNLOCK(hcd->lock);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
        usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
@@ -1006,6 +1008,7 @@ static int urb_enqueue(struct usb_hcd *hcd,
        int alloc_bandwidth = 0;
        uint8_t ep_type = 0;
        uint32_t flags = 0;
+       dwc_irqflags_t irq_flags;
        void *buf;
 
 #ifdef DEBUG
@@ -1106,20 +1109,36 @@ static int urb_enqueue(struct usb_hcd *hcd,
        }
 
        urb->hcpriv = dwc_otg_urb;
+
+       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irq_flags);
+       retval = usb_hcd_link_urb_to_ep(hcd, urb);
+       DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irq_flags);
+       if (retval)
+               goto fail1;
+
        retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb, &ep->hcpriv,
                                         mem_flags == GFP_ATOMIC ? 1 : 0);
-       if (!retval) {
-               if (alloc_bandwidth) {
-                       allocate_bus_bandwidth(hcd,
-                                              dwc_otg_hcd_get_ep_bandwidth
-                                              (dwc_otg_hcd, ep->hcpriv), urb);
-               }
-       } else {
-               if (retval == -DWC_E_NO_DEVICE) {
+       if (retval) {
+               if (retval == -DWC_E_NO_DEVICE)
                        retval = -ENODEV;
-               }
+               goto fail2;
+       }
+
+       if (alloc_bandwidth) {
+               allocate_bus_bandwidth(hcd, dwc_otg_hcd_get_ep_bandwidth
+                                      (dwc_otg_hcd, ep->hcpriv), urb);
        }
 
+       return 0;
+fail2:
+       /*  */
+       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irq_flags);
+       dwc_otg_urb->priv = NULL;
+       usb_hcd_unlink_urb_from_ep(hcd, urb);
+       DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irq_flags);
+fail1:
+       urb->hcpriv = NULL;
+       DWC_FREE(dwc_otg_urb);
        return retval;
 }
 
@@ -1131,6 +1150,7 @@ static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
 static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 #endif
 {
+       int rc;
        dwc_irqflags_t flags;
        dwc_otg_hcd_t *dwc_otg_hcd;
        DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
@@ -1143,30 +1163,22 @@ static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
        }
 #endif
 
-       if (((uint32_t) urb & 0xf0000000) == 0) {
+       if (!urb) {
                DWC_PRINTF("%s error: urb is %p!!!\n", __func__, urb);
                return 0;
        }
 
        DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
-
-       if (((uint32_t) urb->hcpriv & 0xf0000000) == 0) {
-               DWC_PRINTF("%s error: urb->hcpriv %p urb %p, count %d!!!\n",
-                          __func__, urb->hcpriv, urb,
-                          atomic_read(&urb->use_count));
-               if ((atomic_read(&urb->use_count)) == 1)
-                       goto out2;
-               else {
-                       DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
-                       return 0;
-               }
+       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+       if (rc){
+               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
+               return rc;
        }
 
        dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, urb->hcpriv);
-
-out2:
        DWC_FREE(urb->hcpriv);
        urb->hcpriv = NULL;
+       usb_hcd_unlink_urb_from_ep(hcd, urb);
        DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
 
        /* Higher layer software sets URB status. */