Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held in completion ta... #312

Merged
merged 1 commit into from
Jun 23, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drivers/usb/host/dwc_otg/dwc_otg_hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ static void completion_tasklet_func(void *ptr)
urb_tq_entry_t *item;
dwc_irqflags_t flags;

/* This could just be spin_lock_irq */
DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
while (!DWC_TAILQ_EMPTY(&hcd->completed_urb_list)) {
item = DWC_TAILQ_FIRST(&hcd->completed_urb_list);
Expand All @@ -713,7 +714,6 @@ static void completion_tasklet_func(void *ptr)
DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
DWC_FREE(item);

usb_hcd_unlink_urb_from_ep(hcd->priv, urb);
usb_hcd_giveback_urb(hcd->priv, urb, urb->status);

DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
Expand Down
18 changes: 14 additions & 4 deletions drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,15 @@ static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,

/**
* Sets the final status of an URB and returns it to the device driver. Any
* required cleanup of the URB is performed.
* required cleanup of the URB is performed. The HCD lock should be held on
* entry.
*/
static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
{
struct urb *urb = (struct urb *)urb_handle;
urb_tq_entry_t *new_entry;
int rc = 0;
if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
__func__, urb, usb_pipedevice(urb->pipe),
Expand Down Expand Up @@ -363,9 +365,17 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
#endif
} else {
new_entry->urb = urb;
DWC_TAILQ_INSERT_TAIL(&hcd->completed_urb_list, new_entry,
urb_tq_entries);
DWC_TASK_HI_SCHEDULE(hcd->completion_tasklet);
#if USB_URB_EP_LINKING
rc = usb_hcd_check_unlink_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
if(0 == rc) {
usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
}
#endif
if(0 == rc) {
DWC_TAILQ_INSERT_TAIL(&hcd->completed_urb_list, new_entry,
urb_tq_entries);
DWC_TASK_HI_SCHEDULE(hcd->completion_tasklet);
}
}
return 0;
}
Expand Down