aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-10-09 11:01:41 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-11 19:33:58 -0400
commit6ec4147e7bdbde168f5bce30de5984aa4f971b22 (patch)
tree0c06a5ac384ea390883f085de37992f0dbfedf3f /drivers/usb/core
parent9ef73dbdd0fc292d183e93cd1d4b21d1a66040d7 (diff)
usb-anchor: Delay usb_wait_anchor_empty_timeout wake up till completion is done
usb_wait_anchor_empty_timeout() should wait till the completion handler has run. Both the zd1211rw driver and the uas driver (in its task mgmt) depend on the completion handler having completed when usb_wait_anchor_empty_timeout() returns, as they read state set by the completion handler after an usb_wait_anchor_empty_timeout() call. But __usb_hcd_giveback_urb() calls usb_unanchor_urb before calling the completion handler. This is necessary as the completion handler may re-submit and re-anchor the urb. But this introduces a race where the state these drivers want to read has not been set yet by the completion handler (this race is easily triggered with the uas task mgmt code). I've considered adding an anchor_count to struct urb, which would be incremented on anchor and decremented on unanchor, and then only actually do the anchor / unanchor on 0 -> 1 and 1 -> 0 transtions, combined with moving the unanchor call in hcd_giveback_urb to after calling the completion handler. But this will only work if urb's are only re-anchored to the same anchor as they were anchored to before the completion handler ran. And at least one driver re-anchors to another anchor from the completion handler (rtlwifi). So I have come up with this patch instead, which adds the ability to suspend wakeups of usb_wait_anchor_empty_timeout() waiters to the usb_anchor functionality, and uses this in __usb_hcd_giveback_urb() to delay wake-ups until the completion handler has run. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Oliver Neukum <oliver@neukum.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/hcd.c3
-rw-r--r--drivers/usb/core/urb.c44
2 files changed, 45 insertions, 2 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 460bb59cb655..149cdf129293 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1652,6 +1652,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
1652static void __usb_hcd_giveback_urb(struct urb *urb) 1652static void __usb_hcd_giveback_urb(struct urb *urb)
1653{ 1653{
1654 struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); 1654 struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
1655 struct usb_anchor *anchor = urb->anchor;
1655 int status = urb->unlinked; 1656 int status = urb->unlinked;
1656 unsigned long flags; 1657 unsigned long flags;
1657 1658
@@ -1663,6 +1664,7 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
1663 1664
1664 unmap_urb_for_dma(hcd, urb); 1665 unmap_urb_for_dma(hcd, urb);
1665 usbmon_urb_complete(&hcd->self, urb, status); 1666 usbmon_urb_complete(&hcd->self, urb, status);
1667 usb_anchor_suspend_wakeups(anchor);
1666 usb_unanchor_urb(urb); 1668 usb_unanchor_urb(urb);
1667 1669
1668 /* pass ownership to the completion handler */ 1670 /* pass ownership to the completion handler */
@@ -1682,6 +1684,7 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
1682 urb->complete(urb); 1684 urb->complete(urb);
1683 local_irq_restore(flags); 1685 local_irq_restore(flags);
1684 1686
1687 usb_anchor_resume_wakeups(anchor);
1685 atomic_dec(&urb->use_count); 1688 atomic_dec(&urb->use_count);
1686 if (unlikely(atomic_read(&urb->reject))) 1689 if (unlikely(atomic_read(&urb->reject)))
1687 wake_up(&usb_kill_urb_queue); 1690 wake_up(&usb_kill_urb_queue);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c12bc790a6a7..e62208356c89 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -138,13 +138,19 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)
138} 138}
139EXPORT_SYMBOL_GPL(usb_anchor_urb); 139EXPORT_SYMBOL_GPL(usb_anchor_urb);
140 140
141static int usb_anchor_check_wakeup(struct usb_anchor *anchor)
142{
143 return atomic_read(&anchor->suspend_wakeups) == 0 &&
144 list_empty(&anchor->urb_list);
145}
146
141/* Callers must hold anchor->lock */ 147/* Callers must hold anchor->lock */
142static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor) 148static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor)
143{ 149{
144 urb->anchor = NULL; 150 urb->anchor = NULL;
145 list_del(&urb->anchor_list); 151 list_del(&urb->anchor_list);
146 usb_put_urb(urb); 152 usb_put_urb(urb);
147 if (list_empty(&anchor->urb_list)) 153 if (usb_anchor_check_wakeup(anchor))
148 wake_up(&anchor->wait); 154 wake_up(&anchor->wait);
149} 155}
150 156
@@ -846,6 +852,39 @@ void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
846EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs); 852EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
847 853
848/** 854/**
855 * usb_anchor_suspend_wakeups
856 * @anchor: the anchor you want to suspend wakeups on
857 *
858 * Call this to stop the last urb being unanchored from waking up any
859 * usb_wait_anchor_empty_timeout waiters. This is used in the hcd urb give-
860 * back path to delay waking up until after the completion handler has run.
861 */
862void usb_anchor_suspend_wakeups(struct usb_anchor *anchor)
863{
864 if (anchor)
865 atomic_inc(&anchor->suspend_wakeups);
866}
867EXPORT_SYMBOL_GPL(usb_anchor_suspend_wakeups);
868
869/**
870 * usb_anchor_resume_wakeups
871 * @anchor: the anchor you want to resume wakeups on
872 *
873 * Allow usb_wait_anchor_empty_timeout waiters to be woken up again, and
874 * wake up any current waiters if the anchor is empty.
875 */
876void usb_anchor_resume_wakeups(struct usb_anchor *anchor)
877{
878 if (!anchor)
879 return;
880
881 atomic_dec(&anchor->suspend_wakeups);
882 if (usb_anchor_check_wakeup(anchor))
883 wake_up(&anchor->wait);
884}
885EXPORT_SYMBOL_GPL(usb_anchor_resume_wakeups);
886
887/**
849 * usb_wait_anchor_empty_timeout - wait for an anchor to be unused 888 * usb_wait_anchor_empty_timeout - wait for an anchor to be unused
850 * @anchor: the anchor you want to become unused 889 * @anchor: the anchor you want to become unused
851 * @timeout: how long you are willing to wait in milliseconds 890 * @timeout: how long you are willing to wait in milliseconds
@@ -858,7 +897,8 @@ EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
858int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, 897int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
859 unsigned int timeout) 898 unsigned int timeout)
860{ 899{
861 return wait_event_timeout(anchor->wait, list_empty(&anchor->urb_list), 900 return wait_event_timeout(anchor->wait,
901 usb_anchor_check_wakeup(anchor),
862 msecs_to_jiffies(timeout)); 902 msecs_to_jiffies(timeout));
863} 903}
864EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout); 904EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);