From d5e07b80f1eb16bfc171e964b221d89a5c8e2fbe Mon Sep 17 00:00:00 2001 From: lyz Date: Wed, 11 Mar 2015 17:44:14 +0800 Subject: [PATCH] usb: dwc_otg: change method of checking urb dequeue status 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 | 2 +- drivers/usb/dwc_otg_310/dwc_otg_hcd_intr.c | 34 +++--------- drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c | 58 +++++++++++++-------- 3 files changed, 42 insertions(+), 52 deletions(-) diff --git a/drivers/usb/dwc_otg_310/dwc_otg_hcd.c b/drivers/usb/dwc_otg_310/dwc_otg_hcd.c index 07845a23fc26..ff123682de68 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_hcd.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_hcd.c @@ -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; diff --git a/drivers/usb/dwc_otg_310/dwc_otg_hcd_intr.c b/drivers/usb/dwc_otg_310/dwc_otg_hcd_intr.c index e1dccb1a7a22..a7bbaaeeeacd 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_hcd_intr.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_hcd_intr.c @@ -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); diff --git a/drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c b/drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c index 24464797a2a6..28d468374e37 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c @@ -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. */ -- 2.34.1