aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-sched.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/ehci-sched.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/ehci-sched.c')
-rw-r--r--drivers/usb/host/ehci-sched.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index e682f2342ef8..8b267b3fd2bb 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -797,7 +797,6 @@ done:
797 797
798static int intr_submit ( 798static int intr_submit (
799 struct ehci_hcd *ehci, 799 struct ehci_hcd *ehci,
800 struct usb_host_endpoint *ep,
801 struct urb *urb, 800 struct urb *urb,
802 struct list_head *qtd_list, 801 struct list_head *qtd_list,
803 gfp_t mem_flags 802 gfp_t mem_flags
@@ -805,23 +804,26 @@ static int intr_submit (
805 unsigned epnum; 804 unsigned epnum;
806 unsigned long flags; 805 unsigned long flags;
807 struct ehci_qh *qh; 806 struct ehci_qh *qh;
808 int status = 0; 807 int status;
809 struct list_head empty; 808 struct list_head empty;
810 809
811 /* get endpoint and transfer/schedule data */ 810 /* get endpoint and transfer/schedule data */
812 epnum = ep->desc.bEndpointAddress; 811 epnum = urb->ep->desc.bEndpointAddress;
813 812
814 spin_lock_irqsave (&ehci->lock, flags); 813 spin_lock_irqsave (&ehci->lock, flags);
815 814
816 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, 815 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
817 &ehci_to_hcd(ehci)->flags))) { 816 &ehci_to_hcd(ehci)->flags))) {
818 status = -ESHUTDOWN; 817 status = -ESHUTDOWN;
819 goto done; 818 goto done_not_linked;
820 } 819 }
820 status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb);
821 if (unlikely(status))
822 goto done_not_linked;
821 823
822 /* get qh and force any scheduling errors */ 824 /* get qh and force any scheduling errors */
823 INIT_LIST_HEAD (&empty); 825 INIT_LIST_HEAD (&empty);
824 qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv); 826 qh = qh_append_tds(ehci, urb, &empty, epnum, &urb->ep->hcpriv);
825 if (qh == NULL) { 827 if (qh == NULL) {
826 status = -ENOMEM; 828 status = -ENOMEM;
827 goto done; 829 goto done;
@@ -832,13 +834,16 @@ static int intr_submit (
832 } 834 }
833 835
834 /* then queue the urb's tds to the qh */ 836 /* then queue the urb's tds to the qh */
835 qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv); 837 qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);
836 BUG_ON (qh == NULL); 838 BUG_ON (qh == NULL);
837 839
838 /* ... update usbfs periodic stats */ 840 /* ... update usbfs periodic stats */
839 ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; 841 ehci_to_hcd(ehci)->self.bandwidth_int_reqs++;
840 842
841done: 843done:
844 if (unlikely(status))
845 usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
846done_not_linked:
842 spin_unlock_irqrestore (&ehci->lock, flags); 847 spin_unlock_irqrestore (&ehci->lock, flags);
843 if (status) 848 if (status)
844 qtd_list_free (ehci, urb, qtd_list); 849 qtd_list_free (ehci, urb, qtd_list);
@@ -1686,12 +1691,19 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
1686 /* schedule ... need to lock */ 1691 /* schedule ... need to lock */
1687 spin_lock_irqsave (&ehci->lock, flags); 1692 spin_lock_irqsave (&ehci->lock, flags);
1688 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, 1693 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
1689 &ehci_to_hcd(ehci)->flags))) 1694 &ehci_to_hcd(ehci)->flags))) {
1690 status = -ESHUTDOWN; 1695 status = -ESHUTDOWN;
1691 else 1696 goto done_not_linked;
1692 status = iso_stream_schedule (ehci, urb, stream); 1697 }
1698 status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb);
1699 if (unlikely(status))
1700 goto done_not_linked;
1701 status = iso_stream_schedule(ehci, urb, stream);
1693 if (likely (status == 0)) 1702 if (likely (status == 0))
1694 itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); 1703 itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
1704 else
1705 usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
1706done_not_linked:
1695 spin_unlock_irqrestore (&ehci->lock, flags); 1707 spin_unlock_irqrestore (&ehci->lock, flags);
1696 1708
1697done: 1709done:
@@ -2049,12 +2061,19 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
2049 /* schedule ... need to lock */ 2061 /* schedule ... need to lock */
2050 spin_lock_irqsave (&ehci->lock, flags); 2062 spin_lock_irqsave (&ehci->lock, flags);
2051 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, 2063 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
2052 &ehci_to_hcd(ehci)->flags))) 2064 &ehci_to_hcd(ehci)->flags))) {
2053 status = -ESHUTDOWN; 2065 status = -ESHUTDOWN;
2054 else 2066 goto done_not_linked;
2055 status = iso_stream_schedule (ehci, urb, stream); 2067 }
2068 status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb);
2069 if (unlikely(status))
2070 goto done_not_linked;
2071 status = iso_stream_schedule(ehci, urb, stream);
2056 if (status == 0) 2072 if (status == 0)
2057 sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); 2073 sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
2074 else
2075 usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
2076done_not_linked:
2058 spin_unlock_irqrestore (&ehci->lock, flags); 2077 spin_unlock_irqrestore (&ehci->lock, flags);
2059 2078
2060done: 2079done: