mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
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
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user