aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/isp116x-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/isp116x-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/isp116x-hcd.c')
-rw-r--r--drivers/usb/host/isp116x-hcd.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 5c851a36de72..d5027dc75a57 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -290,6 +290,7 @@ __releases(isp116x->lock) __acquires(isp116x->lock)
290 290
291 urb_dbg(urb, "Finish"); 291 urb_dbg(urb, "Finish");
292 292
293 usb_hcd_unlink_urb_from_ep(isp116x_to_hcd(isp116x), urb);
293 spin_unlock(&isp116x->lock); 294 spin_unlock(&isp116x->lock);
294 usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb); 295 usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
295 spin_lock(&isp116x->lock); 296 spin_lock(&isp116x->lock);
@@ -673,7 +674,7 @@ static int balance(struct isp116x *isp116x, u16 period, u16 load)
673/*-----------------------------------------------------------------*/ 674/*-----------------------------------------------------------------*/
674 675
675static int isp116x_urb_enqueue(struct usb_hcd *hcd, 676static int isp116x_urb_enqueue(struct usb_hcd *hcd,
676 struct usb_host_endpoint *hep, struct urb *urb, 677 struct urb *urb,
677 gfp_t mem_flags) 678 gfp_t mem_flags)
678{ 679{
679 struct isp116x *isp116x = hcd_to_isp116x(hcd); 680 struct isp116x *isp116x = hcd_to_isp116x(hcd);
@@ -682,6 +683,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
682 int is_out = !usb_pipein(pipe); 683 int is_out = !usb_pipein(pipe);
683 int type = usb_pipetype(pipe); 684 int type = usb_pipetype(pipe);
684 int epnum = usb_pipeendpoint(pipe); 685 int epnum = usb_pipeendpoint(pipe);
686 struct usb_host_endpoint *hep = urb->ep;
685 struct isp116x_ep *ep = NULL; 687 struct isp116x_ep *ep = NULL;
686 unsigned long flags; 688 unsigned long flags;
687 int i; 689 int i;
@@ -705,7 +707,12 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
705 if (!HC_IS_RUNNING(hcd->state)) { 707 if (!HC_IS_RUNNING(hcd->state)) {
706 kfree(ep); 708 kfree(ep);
707 ret = -ENODEV; 709 ret = -ENODEV;
708 goto fail; 710 goto fail_not_linked;
711 }
712 ret = usb_hcd_link_urb_to_ep(hcd, urb);
713 if (ret) {
714 kfree(ep);
715 goto fail_not_linked;
709 } 716 }
710 717
711 if (hep->hcpriv) 718 if (hep->hcpriv)
@@ -818,6 +825,9 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
818 start_atl_transfers(isp116x); 825 start_atl_transfers(isp116x);
819 826
820 fail: 827 fail:
828 if (ret)
829 usb_hcd_unlink_urb_from_ep(hcd, urb);
830 fail_not_linked:
821 spin_unlock_irqrestore(&isp116x->lock, flags); 831 spin_unlock_irqrestore(&isp116x->lock, flags);
822 return ret; 832 return ret;
823} 833}
@@ -825,20 +835,21 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
825/* 835/*
826 Dequeue URBs. 836 Dequeue URBs.
827*/ 837*/
828static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) 838static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
839 int status)
829{ 840{
830 struct isp116x *isp116x = hcd_to_isp116x(hcd); 841 struct isp116x *isp116x = hcd_to_isp116x(hcd);
831 struct usb_host_endpoint *hep; 842 struct usb_host_endpoint *hep;
832 struct isp116x_ep *ep, *ep_act; 843 struct isp116x_ep *ep, *ep_act;
833 unsigned long flags; 844 unsigned long flags;
845 int rc;
834 846
835 spin_lock_irqsave(&isp116x->lock, flags); 847 spin_lock_irqsave(&isp116x->lock, flags);
848 rc = usb_hcd_check_unlink_urb(hcd, urb, status);
849 if (rc)
850 goto done;
851
836 hep = urb->hcpriv; 852 hep = urb->hcpriv;
837 /* URB already unlinked (or never linked)? */
838 if (!hep) {
839 spin_unlock_irqrestore(&isp116x->lock, flags);
840 return 0;
841 }
842 ep = hep->hcpriv; 853 ep = hep->hcpriv;
843 WARN_ON(hep != ep->hep); 854 WARN_ON(hep != ep->hep);
844 855
@@ -856,9 +867,9 @@ static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
856 867
857 if (urb) 868 if (urb)
858 finish_request(isp116x, ep, urb); 869 finish_request(isp116x, ep, urb);
859 870 done:
860 spin_unlock_irqrestore(&isp116x->lock, flags); 871 spin_unlock_irqrestore(&isp116x->lock, flags);
861 return 0; 872 return rc;
862} 873}
863 874
864static void isp116x_endpoint_disable(struct usb_hcd *hcd, 875static void isp116x_endpoint_disable(struct usb_hcd *hcd,