summaryrefslogtreecommitdiff
path: root/drivers/usb/core/urb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/urb.c')
-rw-r--r--drivers/usb/core/urb.c47
1 files changed, 15 insertions, 32 deletions
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 7576920e2d5a..ff8df16cca35 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -372,11 +372,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
struct usb_host_endpoint *ep;
int is_out;
unsigned int allowed;
+ bool is_eusb2_isoch_double;
if (!urb || !urb->complete)
return -EINVAL;
if (urb->hcpriv) {
- WARN_ONCE(1, "URB %pK submitted while active\n", urb);
+ WARN_ONCE(1, "URB %p submitted while active\n", urb);
return -EBUSY;
}
@@ -434,7 +435,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
return -ENODEV;
max = usb_endpoint_maxp(&ep->desc);
- if (max <= 0) {
+ is_eusb2_isoch_double = usb_endpoint_is_hs_isoc_double(dev, ep);
+ if (!max && !is_eusb2_isoch_double) {
dev_dbg(&dev->dev,
"bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
usb_endpoint_num(&ep->desc), is_out ? "out" : "in",
@@ -467,9 +469,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
max = le32_to_cpu(isoc_ep_comp->dwBytesPerInterval);
}
- /* "high bandwidth" mode, 1-3 packets/uframe? */
- if (dev->speed == USB_SPEED_HIGH)
- max *= usb_endpoint_maxp_mult(&ep->desc);
+ /* High speed, 1-3 packets/uframe, max 6 for eUSB2 double bw */
+ if (dev->speed == USB_SPEED_HIGH) {
+ if (is_eusb2_isoch_double)
+ max = le32_to_cpu(ep->eusb2_isoc_ep_comp.dwBytesPerInterval);
+ else
+ max *= usb_endpoint_maxp_mult(&ep->desc);
+ }
if (urb->number_of_packets <= 0)
return -EINVAL;
@@ -500,7 +506,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
/* Check that the pipe's type matches the endpoint's type */
if (usb_pipe_type_check(urb->dev, urb->pipe))
- dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
+ dev_warn_once(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
usb_pipetype(urb->pipe), pipetypes[xfertype]);
/* Check against a simple/standard policy */
@@ -597,10 +603,9 @@ EXPORT_SYMBOL_GPL(usb_submit_urb);
* code).
*
* Drivers should not call this routine or related routines, such as
- * usb_kill_urb() or usb_unlink_anchored_urbs(), after their disconnect
- * method has returned. The disconnect function should synchronize with
- * a driver's I/O routines to insure that all URB-related activity has
- * completed before it returns.
+ * usb_kill_urb(), after their disconnect method has returned. The
+ * disconnect function should synchronize with a driver's I/O routines
+ * to insure that all URB-related activity has completed before it returns.
*
* This request is asynchronous, however the HCD might call the ->complete()
* callback during unlink. Therefore when drivers call usb_unlink_urb(), they
@@ -890,28 +895,6 @@ void usb_unpoison_anchored_urbs(struct usb_anchor *anchor)
spin_unlock_irqrestore(&anchor->lock, flags);
}
EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs);
-/**
- * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
- * @anchor: anchor the requests are bound to
- *
- * this allows all outstanding URBs to be unlinked starting
- * from the back of the queue. This function is asynchronous.
- * The unlinking is just triggered. It may happen after this
- * function has returned.
- *
- * This routine should not be called by a driver after its disconnect
- * method has returned.
- */
-void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
-{
- struct urb *victim;
-
- while ((victim = usb_get_from_anchor(anchor)) != NULL) {
- usb_unlink_urb(victim);
- usb_put_urb(victim);
- }
-}
-EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
/**
* usb_anchor_suspend_wakeups