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>
This commit is contained in:
parent
272b98c645
commit
c7ccde6eac
|
@ -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 {
|
||||||
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)
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue