aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/sl811-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-08-08 11:48:02 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:55:10 -0400
commite9df41c5c5899259541dc928872cad4d07b82076 (patch)
tree12bb0917eeecbe62b2b5d3dc576806c7f2728550 /drivers/usb/host/sl811-hcd.c
parentb0e396e3097ce4914c643bc3f0c2fe0098f551eb (diff)
USB: make HCDs responsible for managing endpoint queues
This patch (as954) implements a suggestion of David Brownell's. Now the host controller drivers are responsible for linking and unlinking URBs to/from their endpoint queues. This eliminates the possiblity of strange situations where usbcore thinks an URB is linked but the HCD thinks it isn't. It also means HCDs no longer have to check for URBs being dequeued before they were fully enqueued. In addition to the core changes, this requires changing every host controller driver and the root-hub URB handler. For the most part the required changes are fairly small; drivers have to call usb_hcd_link_urb_to_ep() in their urb_enqueue method, usb_hcd_check_unlink_urb() in their urb_dequeue method, and usb_hcd_unlink_urb_from_ep() before giving URBs back. A few HCDs make matters more complicated by the way they split up the flow of control. In addition some method interfaces get changed. The endpoint argument for urb_enqueue is now redundant so it is removed. The unlink status is required by usb_hcd_check_unlink_urb(), so it has been added to urb_dequeue. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: David Brownell <david-b@pacbell.net> CC: Olav Kongas <ok@artecdesign.ee> CC: Tony Olech <tony.olech@elandigitalsystems.com> CC: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/sl811-hcd.c')
-rw-r--r--drivers/usb/host/sl811-hcd.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 4cfa3ff2c993..3d3a63d002c5 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -441,6 +441,7 @@ static void finish_request(
441 urb->hcpriv = NULL; 441 urb->hcpriv = NULL;
442 spin_unlock(&urb->lock); 442 spin_unlock(&urb->lock);
443 443
444 usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
444 spin_unlock(&sl811->lock); 445 spin_unlock(&sl811->lock);
445 usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb); 446 usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb);
446 spin_lock(&sl811->lock); 447 spin_lock(&sl811->lock);
@@ -807,7 +808,6 @@ static int balance(struct sl811 *sl811, u16 period, u16 load)
807 808
808static int sl811h_urb_enqueue( 809static int sl811h_urb_enqueue(
809 struct usb_hcd *hcd, 810 struct usb_hcd *hcd,
810 struct usb_host_endpoint *hep,
811 struct urb *urb, 811 struct urb *urb,
812 gfp_t mem_flags 812 gfp_t mem_flags
813) { 813) {
@@ -820,7 +820,8 @@ static int sl811h_urb_enqueue(
820 struct sl811h_ep *ep = NULL; 820 struct sl811h_ep *ep = NULL;
821 unsigned long flags; 821 unsigned long flags;
822 int i; 822 int i;
823 int retval = 0; 823 int retval;
824 struct usb_host_endpoint *hep = urb->ep;
824 825
825#ifdef DISABLE_ISO 826#ifdef DISABLE_ISO
826 if (type == PIPE_ISOCHRONOUS) 827 if (type == PIPE_ISOCHRONOUS)
@@ -838,7 +839,12 @@ static int sl811h_urb_enqueue(
838 || !HC_IS_RUNNING(hcd->state)) { 839 || !HC_IS_RUNNING(hcd->state)) {
839 retval = -ENODEV; 840 retval = -ENODEV;
840 kfree(ep); 841 kfree(ep);
841 goto fail; 842 goto fail_not_linked;
843 }
844 retval = usb_hcd_link_urb_to_ep(hcd, urb);
845 if (retval) {
846 kfree(ep);
847 goto fail_not_linked;
842 } 848 }
843 849
844 if (hep->hcpriv) { 850 if (hep->hcpriv) {
@@ -965,23 +971,27 @@ static int sl811h_urb_enqueue(
965 start_transfer(sl811); 971 start_transfer(sl811);
966 sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); 972 sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable);
967fail: 973fail:
974 if (retval)
975 usb_hcd_unlink_urb_from_ep(hcd, urb);
976fail_not_linked:
968 spin_unlock_irqrestore(&sl811->lock, flags); 977 spin_unlock_irqrestore(&sl811->lock, flags);
969 return retval; 978 return retval;
970} 979}
971 980
972static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) 981static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
973{ 982{
974 struct sl811 *sl811 = hcd_to_sl811(hcd); 983 struct sl811 *sl811 = hcd_to_sl811(hcd);
975 struct usb_host_endpoint *hep; 984 struct usb_host_endpoint *hep;
976 unsigned long flags; 985 unsigned long flags;
977 struct sl811h_ep *ep; 986 struct sl811h_ep *ep;
978 int retval = 0; 987 int retval;
979 988
980 spin_lock_irqsave(&sl811->lock, flags); 989 spin_lock_irqsave(&sl811->lock, flags);
981 hep = urb->hcpriv; 990 retval = usb_hcd_check_unlink_urb(hcd, urb, status);
982 if (!hep) 991 if (retval)
983 goto fail; 992 goto fail;
984 993
994 hep = urb->hcpriv;
985 ep = hep->hcpriv; 995 ep = hep->hcpriv;
986 if (ep) { 996 if (ep) {
987 /* finish right away if this urb can't be active ... 997 /* finish right away if this urb can't be active ...
@@ -1029,8 +1039,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
1029 VDBG("dequeue, urb %p active %s; wait4irq\n", urb, 1039 VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
1030 (sl811->active_a == ep) ? "A" : "B"); 1040 (sl811->active_a == ep) ? "A" : "B");
1031 } else 1041 } else
1032fail:
1033 retval = -EINVAL; 1042 retval = -EINVAL;
1043 fail:
1034 spin_unlock_irqrestore(&sl811->lock, flags); 1044 spin_unlock_irqrestore(&sl811->lock, flags);
1035 return retval; 1045 return retval;
1036} 1046}