Commit c7ccde6e authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

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: default avatarAlan Stern <stern@rowland.harvard.edu>
CC: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 272b98c6
...@@ -1703,7 +1703,9 @@ static void usb_giveback_urb_bh(unsigned long param) ...@@ -1703,7 +1703,9 @@ static void usb_giveback_urb_bh(unsigned long param)
urb = list_entry(local_list.next, struct urb, urb_list); urb = list_entry(local_list.next, struct urb, urb_list);
list_del_init(&urb->urb_list); list_del_init(&urb->urb_list);
bh->completing_ep = urb->ep;
__usb_hcd_giveback_urb(urb); __usb_hcd_giveback_urb(urb);
bh->completing_ep = NULL;
} }
/* check if there are new URBs to giveback */ /* check if there are new URBs to giveback */
......
...@@ -73,6 +73,7 @@ struct giveback_urb_bh { ...@@ -73,6 +73,7 @@ struct giveback_urb_bh {
spinlock_t lock; spinlock_t lock;
struct list_head head; struct list_head head;
struct tasklet_struct bh; struct tasklet_struct bh;
struct usb_host_endpoint *completing_ep;
}; };
struct usb_hcd { struct usb_hcd {
...@@ -378,6 +379,12 @@ static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd) ...@@ -378,6 +379,12 @@ static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
return hcd->driver->flags & HCD_BH; return hcd->driver->flags & HCD_BH;
} }
static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd,
struct usb_host_endpoint *ep)
{
return hcd->high_prio_bh.completing_ep == ep;
}
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
int status); int status);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment