aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/r8a66597-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/r8a66597-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/r8a66597-hcd.c')
-rw-r--r--drivers/usb/host/r8a66597-hcd.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 40a1de4c256e..94bb229df3bc 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -784,6 +784,9 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
784 if (urb) { 784 if (urb) {
785 urb->status = -ENODEV; 785 urb->status = -ENODEV;
786 urb->hcpriv = NULL; 786 urb->hcpriv = NULL;
787 usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597),
788 urb);
789
787 spin_unlock(&r8a66597->lock); 790 spin_unlock(&r8a66597->lock);
788 usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb); 791 usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb);
789 spin_lock(&r8a66597->lock); 792 spin_lock(&r8a66597->lock);
@@ -1131,6 +1134,8 @@ static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td,
1131 urb->start_frame = r8a66597_get_frame(hcd); 1134 urb->start_frame = r8a66597_get_frame(hcd);
1132 1135
1133 urb->hcpriv = NULL; 1136 urb->hcpriv = NULL;
1137 usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
1138
1134 spin_unlock(&r8a66597->lock); 1139 spin_unlock(&r8a66597->lock);
1135 usb_hcd_giveback_urb(hcd, urb); 1140 usb_hcd_giveback_urb(hcd, urb);
1136 spin_lock(&r8a66597->lock); 1141 spin_lock(&r8a66597->lock);
@@ -1722,21 +1727,25 @@ static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597,
1722} 1727}
1723 1728
1724static int r8a66597_urb_enqueue(struct usb_hcd *hcd, 1729static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
1725 struct usb_host_endpoint *hep,
1726 struct urb *urb, 1730 struct urb *urb,
1727 gfp_t mem_flags) 1731 gfp_t mem_flags)
1728{ 1732{
1733 struct usb_host_endpoint *hep = urb->ep;
1729 struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); 1734 struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
1730 struct r8a66597_td *td = NULL; 1735 struct r8a66597_td *td = NULL;
1731 int ret = 0, request = 0; 1736 int ret, request = 0;
1732 unsigned long flags; 1737 unsigned long flags;
1733 1738
1734 spin_lock_irqsave(&r8a66597->lock, flags); 1739 spin_lock_irqsave(&r8a66597->lock, flags);
1735 if (!get_urb_to_r8a66597_dev(r8a66597, urb)) { 1740 if (!get_urb_to_r8a66597_dev(r8a66597, urb)) {
1736 ret = -ENODEV; 1741 ret = -ENODEV;
1737 goto error; 1742 goto error_not_linked;
1738 } 1743 }
1739 1744
1745 ret = usb_hcd_link_urb_to_ep(hcd, urb);
1746 if (ret)
1747 goto error_not_linked;
1748
1740 if (!hep->hcpriv) { 1749 if (!hep->hcpriv) {
1741 hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), 1750 hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe),
1742 GFP_ATOMIC); 1751 GFP_ATOMIC);
@@ -1761,15 +1770,7 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
1761 if (list_empty(&r8a66597->pipe_queue[td->pipenum])) 1770 if (list_empty(&r8a66597->pipe_queue[td->pipenum]))
1762 request = 1; 1771 request = 1;
1763 list_add_tail(&td->queue, &r8a66597->pipe_queue[td->pipenum]); 1772 list_add_tail(&td->queue, &r8a66597->pipe_queue[td->pipenum]);
1764
1765 spin_lock(&urb->lock);
1766 if (urb->status != -EINPROGRESS) {
1767 spin_unlock(&urb->lock);
1768 ret = -EPIPE;
1769 goto error;
1770 }
1771 urb->hcpriv = td; 1773 urb->hcpriv = td;
1772 spin_unlock(&urb->lock);
1773 1774
1774 if (request) { 1775 if (request) {
1775 ret = start_transfer(r8a66597, td); 1776 ret = start_transfer(r8a66597, td);
@@ -1781,17 +1782,26 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
1781 set_td_timer(r8a66597, td); 1782 set_td_timer(r8a66597, td);
1782 1783
1783error: 1784error:
1785 if (ret)
1786 usb_hcd_unlink_urb_from_ep(hcd, urb);
1787error_not_linked:
1784 spin_unlock_irqrestore(&r8a66597->lock, flags); 1788 spin_unlock_irqrestore(&r8a66597->lock, flags);
1785 return ret; 1789 return ret;
1786} 1790}
1787 1791
1788static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) 1792static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
1793 int status)
1789{ 1794{
1790 struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); 1795 struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
1791 struct r8a66597_td *td; 1796 struct r8a66597_td *td;
1792 unsigned long flags; 1797 unsigned long flags;
1798 int rc;
1793 1799
1794 spin_lock_irqsave(&r8a66597->lock, flags); 1800 spin_lock_irqsave(&r8a66597->lock, flags);
1801 rc = usb_hcd_check_unlink_urb(hcd, urb, status);
1802 if (rc)
1803 goto done;
1804
1795 if (urb->hcpriv) { 1805 if (urb->hcpriv) {
1796 td = urb->hcpriv; 1806 td = urb->hcpriv;
1797 pipe_stop(r8a66597, td->pipe); 1807 pipe_stop(r8a66597, td->pipe);
@@ -1799,8 +1809,9 @@ static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
1799 disable_irq_empty(r8a66597, td->pipenum); 1809 disable_irq_empty(r8a66597, td->pipenum);
1800 done(r8a66597, td, td->pipenum, urb); 1810 done(r8a66597, td, td->pipenum, urb);
1801 } 1811 }
1812 done:
1802 spin_unlock_irqrestore(&r8a66597->lock, flags); 1813 spin_unlock_irqrestore(&r8a66597->lock, flags);
1803 return 0; 1814 return rc;
1804} 1815}
1805 1816
1806static void r8a66597_endpoint_disable(struct usb_hcd *hcd, 1817static void r8a66597_endpoint_disable(struct usb_hcd *hcd,