diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2009-08-19 12:22:44 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-23 09:46:37 -0400 |
commit | a448c9d8c58ff7d3f8cc2a8f835065460099b22d (patch) | |
tree | 418610891b8dc271bbd798ff5c47d921be5f806d /drivers/usb/host/ehci-q.c | |
parent | 3a44494e233c0fdd818d485cfea8998500543589 (diff) |
USB: EHCI: change deschedule logic for interrupt QHs
This patch (as1281) changes the way ehci-hcd deschedules interrupt
QHs, copying the approach used for async QHs. The caller is no longer
responsible for rescheduling the QH if its queue is non-empty; instead
the reschedule is done directly by intr_deschedule(), after calling
qh_completions(). This is exactly the same as how end_unlink_async()
works.
ehci_urb_dequeue() and intr_deschedule() now correctly handle the case
where they are called while another interrupt URB for the same QH is
being given back. This was a surprisingly large blind spot. And
scan_periodic() now respects the new needs_rescan flag.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: David Brownell <david-b@pacbell.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ehci-q.c')
-rw-r--r-- | drivers/usb/host/ehci-q.c | 12 |
1 files changed, 3 insertions, 9 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 57a84795c43f..00ad9ce392ed 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -299,7 +299,6 @@ __acquires(ehci->lock) | |||
299 | static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); | 299 | static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); |
300 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); | 300 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); |
301 | 301 | ||
302 | static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh); | ||
303 | static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); | 302 | static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); |
304 | 303 | ||
305 | /* | 304 | /* |
@@ -555,14 +554,9 @@ halt: | |||
555 | * That should be rare for interrupt transfers, | 554 | * That should be rare for interrupt transfers, |
556 | * except maybe high bandwidth ... | 555 | * except maybe high bandwidth ... |
557 | */ | 556 | */ |
558 | if ((cpu_to_hc32(ehci, QH_SMASK) | 557 | |
559 | & hw->hw_info2) != 0) { | 558 | /* Tell the caller to start an unlink */ |
560 | intr_deschedule (ehci, qh); | 559 | qh->needs_rescan = 1; |
561 | (void) qh_schedule (ehci, qh); | ||
562 | } else { | ||
563 | /* Tell the caller to start an unlink */ | ||
564 | qh->needs_rescan = 1; | ||
565 | } | ||
566 | break; | 560 | break; |
567 | /* otherwise, unlink already started */ | 561 | /* otherwise, unlink already started */ |
568 | } | 562 | } |