aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2013-09-03 13:58:43 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-09-17 12:49:24 -0400
commitc7ccde6eac6d3c4bc6110cc3fd76ef3823bc0831 (patch)
treef5221b8296a245cb9f3e3f84801b1d5d8feb12f9
parent272b98c6455f00884f0350f775c5342358ebb73f (diff)
USB: see if URB comes from a completion handler
Now that URBs can be completed inside tasklets, we need a way of determining whether a completion handler for a given endpoint is currently running. Otherwise it's not possible to maintain the API guarantee about keeping isochronous streams synchronous when an underrun occurs. This patch adds a field and a routine to check whether a completion handler for a periodic endpoint is running. At the moment no analogous routine appears to be necessary for async endpoints, but one can always be added. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: Ming Lei <tom.leiming@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/hcd.c2
-rw-r--r--include/linux/usb/hcd.h7
2 files changed, 9 insertions, 0 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index d6a8d23f047b..3a2e82a9c115 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1703,7 +1703,9 @@ static void usb_giveback_urb_bh(unsigned long param)
1703 1703
1704 urb = list_entry(local_list.next, struct urb, urb_list); 1704 urb = list_entry(local_list.next, struct urb, urb_list);
1705 list_del_init(&urb->urb_list); 1705 list_del_init(&urb->urb_list);
1706 bh->completing_ep = urb->ep;
1706 __usb_hcd_giveback_urb(urb); 1707 __usb_hcd_giveback_urb(urb);
1708 bh->completing_ep = NULL;
1707 } 1709 }
1708 1710
1709 /* check if there are new URBs to giveback */ 1711 /* check if there are new URBs to giveback */
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 75efc45eaa2f..8c865134c881 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -73,6 +73,7 @@ struct giveback_urb_bh {
73 spinlock_t lock; 73 spinlock_t lock;
74 struct list_head head; 74 struct list_head head;
75 struct tasklet_struct bh; 75 struct tasklet_struct bh;
76 struct usb_host_endpoint *completing_ep;
76}; 77};
77 78
78struct usb_hcd { 79struct usb_hcd {
@@ -378,6 +379,12 @@ static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
378 return hcd->driver->flags & HCD_BH; 379 return hcd->driver->flags & HCD_BH;
379} 380}
380 381
382static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd,
383 struct usb_host_endpoint *ep)
384{
385 return hcd->high_prio_bh.completing_ep == ep;
386}
387
381extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); 388extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
382extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, 389extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
383 int status); 390 int status);