Please merge to Linus' latest...
This patch fixes two problems that have already been discussed
on this list:
- USB_QUEUE_BULK is rather pointless (and UHCI-specific).
If drivers really want only one bulk urb queued at a time,
they just shouldn't issue such urbs till others complete.
FIX: remove it entirely.
- USB_DISABLE_SPD is horribly named (based on a UHCI flag).
What it really does is turn non-ISO short reads into errors.
FIX: rename it. Now it's URB_SHORT_NOT_OK.
I changed all the drivers using these two flags, including
corresponding changes in the "usbfs" API.
Most of the patch by volume is doc updates:
- Documentation/usb/URB.txt hadn't been updated in two years (!)
and was pretty out of date. It also had many details that were
inappropriately specific to usb-uhci.
- Most of the URB flags weren't even commented as to intent.
- DISABLE_SPD was often documented as if it were SHORT_IS_OK.
- There was still some doc saying how iso should use urb->next.
There are also some related updates:
- Some of the submit sanity checks for transfer flags were
overly broad ... SHORT_NOT_OK is only for reads, NO_FSBR
is for non-periodic requests, ZERO_PACKET only for writes.
- The ohci-hcd code thought SHORT_NOT_OK worked for ISO.
- The uhci-hcd code thought QUEUE_BULK applied to non-bulk
Note that this patch doesn't update any of the "old" HCDs,
including usb-ohci-hcd.
In the case of usb-uhci{,-hcd} it'd have been painful to fix
the QUEUE_BULK logic. That logic was, I think, the original
reason to have that flag! So I count switching to "uhci-hcd"
as a win already ... :)
- Dave
--- ./include/linux/usb.h-dist Mon Jun 3 10:18:41 2002
+++ ./include/linux/usb.h Sat Jul 6 10:38:06 2002
@@ -465,7 +465,7 @@
* than changeable ("unstable") ones like bus numbers or device addresses.
*
* With a partial exception for devices connected to USB 2.0 root hubs, these
- * identifiers are also predictable: so long as the device tree isn't changed,
+ * identifiers are also predictable. So long as the device tree isn't changed,
* plugging any USB device into a given hub port always gives it the same path.
* Because of the use of "companion" controllers, devices connected to ports on
* USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are
@@ -739,16 +739,14 @@
/*
* urb->transfer_flags:
*
- * FIXME should be URB_* flags
+ * FIXME should _all_ be URB_* flags
*/
-#define USB_DISABLE_SPD 0x0001
-#define USB_ISO_ASAP 0x0002
-#define USB_ASYNC_UNLINK 0x0008
-#define USB_QUEUE_BULK 0x0010
-#define USB_NO_FSBR 0x0020
+#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
+#define USB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame ignored */
+#define USB_ASYNC_UNLINK 0x0008 /* usb_unlink_urb() returns asap */
+#define USB_NO_FSBR 0x0020 /* UHCI-specific */
#define USB_ZERO_PACKET 0x0040 /* Finish bulk OUTs with short packet
*/
#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */
- /* ... less overhead for QUEUE_BULK */
#define USB_TIMEOUT_KILLED 0x1000 /* only set by HCD! */
struct usb_iso_packet_descriptor {
@@ -794,9 +792,9 @@
* @actual_length: This is read in non-iso completion functions, and
* it tells how many bytes (out of transfer_buffer_length) were
* transferred. It will normally be the same as requested, unless
- * either an error was reported or a short read was performed and
- * the USB_DISABLE_SPD transfer flag was used to say that such
- * short reads are not errors.
+ * either an error was reported or a short read was performed.
+ * The URB_SHORT_NOT_OK transfer flag may be used to make such
+ * short reads be reported as errors.
* @setup_packet: Only used for control transfers, this points to eight bytes
* of setup data. Control transfers always start by sending this data
* to the device. Then transfer_buffer is read or written, if needed.
@@ -831,14 +829,10 @@
*
* All non-isochronous URBs must also initialize
* transfer_buffer and transfer_buffer_length. They may provide the
- * USB_DISABLE_SPD transfer flag, indicating that short reads are
- * not to be treated as errors.
+ * URB_SHORT_NOT_OK transfer flag, indicating that short reads are
+ * to be treated as errors.
*
- * Bulk URBs may pass the USB_QUEUE_BULK transfer flag, telling the host
- * controller driver never to report an error if several bulk requests get
- * queued to the same endpoint. Such queueing supports more efficient use
- * of bus bandwidth, minimizing delays due to interrupts and scheduling,
- * if the host controller hardware is smart enough. Bulk URBs can also
+ * Bulk URBs may
* use the USB_ZERO_PACKET transfer flag, indicating that bulk OUT transfers
* should always terminate with a short packet, even if it means adding an
* extra zero length packet.
@@ -870,7 +864,7 @@
* the quality of service is only "best effort". Callers provide specially
* allocated URBs, with number_of_packets worth of iso_frame_desc structures
* at the end. Each such packet is an individual ISO transfer. Isochronous
- * URBs are normally queued (no flag like USB_BULK_QUEUE is needed) so that
+ * URBs are normally queued, submitted by drivers to arrange that
* transfers are at least double buffered, and then explicitly resubmitted
* in completion handlers, so
* that data (such as audio or video) streams at as constant a rate as the
@@ -909,7 +903,7 @@
struct usb_device *dev; /* (in) pointer to associated device */
unsigned int pipe; /* (in) pipe information */
int status; /* (return) non-ISO status */
- unsigned int transfer_flags; /* (in) USB_DISABLE_SPD | ...*/
+ unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
void *transfer_buffer; /* (in) associated data buffer */
int transfer_buffer_length; /* (in) data buffer length */
int actual_length; /* (return) actual transfer length */
--- ./include/linux/usbdevice_fs.h-dist Sun Apr 14 12:18:47 2002
+++ ./include/linux/usbdevice_fs.h Sat Jul 6 07:18:09 2002
@@ -78,9 +78,8 @@
unsigned char slow;
};
-#define USBDEVFS_URB_DISABLE_SPD 1
+#define USBDEVFS_URB_SHORT_NOT_OK 1
#define USBDEVFS_URB_ISO_ASAP 2
-#define USBDEVFS_URB_QUEUE_BULK 0x10
#define USBDEVFS_URB_TYPE_ISO 0
#define USBDEVFS_URB_TYPE_INTERRUPT 1
--- ./drivers/usb-dist/class/bluetty.c Sun May 26 15:55:03 2002
+++ ./drivers/usb/class/bluetty.c Sat Jul 6 06:49:22 2002
@@ -537,7 +537,6 @@
/* build up our urb */
FILL_BULK_URB (urb, bluetooth->dev,
usb_sndbulkpipe(bluetooth->dev, bluetooth->bulk_out_endpointAddress),
urb->transfer_buffer, buffer_size,
bluetooth_write_bulk_callback, bluetooth);
- urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
retval = usb_submit_urb(urb, GFP_KERNEL);
--- ./drivers/usb-dist/core/devio.c Tue Jun 18 18:06:27 2002
+++ ./drivers/usb/core/devio.c Sat Jul 6 07:16:56 2002
@@ -780,7 +780,7 @@
if (copy_from_user(&uurb, arg, sizeof(uurb)))
return -EFAULT;
- if (uurb.flags &
~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_DISABLE_SPD|USBDEVFS_URB_QUEUE_BULK|
+ if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
USB_NO_FSBR|USB_ZERO_PACKET))
return -EINVAL;
if (!uurb.buffer)
--- ./drivers/usb-dist/core/urb.c Sun Jun 9 10:40:07 2002
+++ ./drivers/usb/core/urb.c Sat Jul 6 07:59:10 2002
@@ -105,7 +105,7 @@
* any transfer flags.
*
* Successful submissions return 0; otherwise this routine returns a
- * negative error number. If the submission is successful, the complete
+ * negative error number. If the submission is successful, the complete()
* fuction of the urb will be called when the USB host driver is
* finished with the urb (either a successful transmission, or some
* error case.)
@@ -117,8 +117,8 @@
* driver which issued the request. The completion handler may then
* immediately free or reuse that URB.
*
- * Bulk URBs will be queued if the USB_QUEUE_BULK transfer flag is set
- * in the URB. This can be used to maximize bandwidth utilization by
+ * Bulk URBs may be queued by submitting an URB to an endpoint before
+ * previous ones complete. This can maximize bandwidth utilization by
* letting the USB controller start work on the next URB without any
* delay to report completion (scheduling and processing an interrupt)
* and then submit that next request.
@@ -128,16 +128,19 @@
*
* Reserved Bandwidth Transfers:
*
- * Periodic URBs (interrupt or isochronous) are completed repeatedly,
+ * Periodic URBs (interrupt or isochronous) are performed repeatedly.
+ *
+ * For interrupt requests this is (currently) automagically done
* until the original request is aborted. When the completion callback
* indicates the URB has been unlinked (with a special status code),
* control of that URB returns to the device driver. Otherwise, the
* completion handler does not control the URB, and should not change
* any of its fields.
*
- * Note that isochronous URBs should be submitted in a "ring" data
- * structure (using urb->next) to ensure that they are resubmitted
- * appropriately.
+ * For isochronous requests, the completion handler is expected to
+ * submit an urb, typically resubmitting its parameter, until drivers
+ * stop wanting data transfers. (For example, audio playback might have
+ * finished, or a webcam turned off.)
*
* If the USB subsystem can't reserve sufficient bandwidth to perform
* the periodic request, and bandwidth reservation is being done for
@@ -274,17 +277,18 @@
/* enforce simple/standard policy */
allowed = USB_ASYNC_UNLINK; // affects later unlinks
- allowed |= USB_NO_FSBR; // only affects UHCI
switch (temp) {
- case PIPE_CONTROL:
- allowed |= USB_DISABLE_SPD;
- break;
case PIPE_BULK:
- allowed |= USB_DISABLE_SPD | USB_QUEUE_BULK
- | USB_ZERO_PACKET | URB_NO_INTERRUPT;
- break;
- case PIPE_INTERRUPT:
- allowed |= USB_DISABLE_SPD;
+ allowed |= URB_NO_INTERRUPT;
+ if (is_out)
+ allowed |= USB_ZERO_PACKET;
+ /* FALLTHROUGH */
+ case PIPE_CONTROL:
+ allowed |= USB_NO_FSBR; /* only affects UHCI */
+ /* FALLTHROUGH */
+ default: /* all non-iso endpoints */
+ if (!is_out)
+ allowed |= URB_SHORT_NOT_OK;
break;
case PIPE_ISOCHRONOUS:
allowed |= USB_ISO_ASAP;
--- ./drivers/usb-dist/host/ehci-q.c Mon Jun 3 10:18:29 2002
+++ ./drivers/usb/host/ehci-q.c Sat Jul 6 08:13:24 2002
@@ -170,7 +170,7 @@
/* cleanse status if we saw no error */
if (likely (urb->status == -EINPROGRESS)) {
if (urb->actual_length != urb->transfer_buffer_length
- && (urb->transfer_flags & USB_DISABLE_SPD))
+ && (urb->transfer_flags & URB_SHORT_NOT_OK))
urb->status = -EREMOTEIO;
else
urb->status = 0;
@@ -202,7 +202,7 @@
if (likely (urb->status == -EINPROGRESS)) {
if (urb->actual_length != urb->transfer_buffer_length
- && (urb->transfer_flags & USB_DISABLE_SPD))
+ && (urb->transfer_flags & URB_SHORT_NOT_OK))
urb->status = -EREMOTEIO;
else
urb->status = 0;
@@ -793,7 +793,7 @@
last_qtd->hw_next = hw_next;
/* previous urb allows short rx? maybe optimize. */
- if (!(last_qtd->urb->transfer_flags & USB_DISABLE_SPD)
+ if (!(last_qtd->urb->transfer_flags & URB_SHORT_NOT_OK)
&& (epnum & 0x10)) {
// only the last QTD for now
last_qtd->hw_alt_next = hw_next;
--- ./drivers/usb-dist/host/ohci-q.c Wed Jun 26 11:36:11 2002
+++ ./drivers/usb/host/ohci-q.c Sat Jul 6 08:06:13 2002
@@ -726,10 +726,6 @@
int dlen = 0;
cc = (tdPSW >> 12) & 0xF;
- if (! ((urb->transfer_flags & USB_DISABLE_SPD)
- && (cc == TD_DATAUNDERRUN)))
- cc = TD_CC_NOERROR;
-
if (usb_pipeout (urb->pipe))
dlen = urb->iso_frame_desc [td->index].length;
else
@@ -758,9 +754,9 @@
usb_pipeendpoint (urb->pipe),
usb_pipeout (urb->pipe));
- /* update packet status if needed (short may be ok) */
- if (((urb->transfer_flags & USB_DISABLE_SPD) != 0
- && cc == TD_DATAUNDERRUN))
+ /* update packet status if needed (short is normally ok) */
+ if (cc == TD_DATAUNDERRUN
+ && !(urb->transfer_flags & URB_SHORT_NOT_OK))
cc = TD_CC_NOERROR;
if (cc != TD_CC_NOERROR) {
spin_lock (&urb->lock);
--- ./drivers/usb-dist/host/uhci-hcd.c Tue Jun 18 18:06:27 2002
+++ ./drivers/usb/host/uhci-hcd.c Sat Jul 6 08:33:13 2002
@@ -491,7 +491,7 @@
}
/* This function will append one URB's QH to another URB's QH. This is for */
-/* USB_QUEUE_BULK support for bulk transfers and soon implicitily for */
+/* queuing bulk transfers and soon implicitily for */
/* control transfers */
static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct
urb *urb)
{
@@ -840,7 +840,7 @@
*/
destination ^= (USB_PID_SETUP ^ usb_packetid(urb->pipe));
- if (!(urb->transfer_flags & USB_DISABLE_SPD))
+ if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
status |= TD_CTRL_SPD;
/*
@@ -1006,7 +1006,7 @@
/* Check to see if we received a short packet */
if (uhci_actual_length(td_status(td)) <
uhci_expected_length(td_token(td))) {
- if (urb->transfer_flags & USB_DISABLE_SPD) {
+ if (urb->transfer_flags & URB_SHORT_NOT_OK) {
ret = -EREMOTEIO;
goto err;
}
@@ -1128,7 +1128,7 @@
goto td_error;
if (uhci_actual_length(td_status(td)) <
uhci_expected_length(td_token(td))) {
- if (urb->transfer_flags & USB_DISABLE_SPD) {
+ if (urb->transfer_flags & URB_SHORT_NOT_OK) {
ret = -EREMOTEIO;
goto err;
} else
@@ -1210,7 +1210,7 @@
/* 3 errors */
status = TD_CTRL_ACTIVE | uhci_maxerr(3);
- if (!(urb->transfer_flags & USB_DISABLE_SPD))
+ if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
status |= TD_CTRL_SPD;
/*
@@ -1276,7 +1276,7 @@
/* Always assume breadth first */
uhci_insert_tds_in_qh(qh, urb, 1);
- if (urb->transfer_flags & USB_QUEUE_BULK && eurb)
+ if (eurb)
uhci_append_queued_urb(uhci, eurb, urb);
else
uhci_insert_qh(uhci, uhci->skel_bulk_qh, urb);
@@ -1470,10 +1470,6 @@
spin_lock_irqsave(&uhci->urb_list_lock, flags);
eurb = uhci_find_urb_ep(uhci, urb);
- if (eurb && !(urb->transfer_flags & USB_QUEUE_BULK)) {
- spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
- return -ENXIO;
- }
if (!uhci_alloc_urb_priv(uhci, urb)) {
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
@@ -1482,10 +1478,15 @@
switch (usb_pipetype(urb->pipe)) {
case PIPE_CONTROL:
- ret = uhci_submit_control(uhci, urb);
+ if (eurb)
+ ret = -ENXIO; /* no control queueing yet */
+ else
+ ret = uhci_submit_control(uhci, urb);
break;
case PIPE_INTERRUPT:
- if (urb->bandwidth == 0) { /* not yet checked/allocated */
+ if (eurb)
+ ret = -ENXIO; /* no interrupt queueing yet */
+ else if (urb->bandwidth == 0) { /* not yet checked/allocated */
bustime = usb_check_bandwidth(urb->dev, urb);
if (bustime < 0)
ret = bustime;
--- ./drivers/usb-dist/media/stv680.c Tue Jun 18 18:06:27 2002
+++ ./drivers/usb/media/stv680.c Sat Jul 6 06:49:22 2002
@@ -776,7 +776,6 @@
stv680->sbuf[i].data, stv680->rawbufsize,
stv680_video_irq, stv680);
urb->timeout = PENCAM_TIMEOUT * 2;
- urb->transfer_flags |= USB_QUEUE_BULK;
stv680->urb[i] = urb;
err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);
if (err)
--- ./drivers/usb-dist/media/se401.c Tue Jun 18 18:06:27 2002
+++ ./drivers/usb/media/se401.c Sat Jul 6 06:49:22 2002
@@ -593,7 +593,6 @@
se401->sbuf[i].data, SE401_PACKETSIZE,
se401_video_irq,
se401);
- urb->transfer_flags |= USB_QUEUE_BULK;
se401->urb[i]=urb;
--- ./drivers/usb-dist/net/usbnet.c Wed Jun 26 11:36:23 2002
+++ ./drivers/usb/net/usbnet.c Sat Jul 6 06:49:22 2002
@@ -1317,9 +1317,6 @@
usb_rcvbulkpipe (dev->udev, dev->driver_info->in),
skb->data, size, rx_complete, skb);
urb->transfer_flags |= USB_ASYNC_UNLINK;
-#ifdef REALLY_QUEUE
- urb->transfer_flags |= USB_QUEUE_BULK;
-#endif
#if 0
// Idle-but-posted reads with UHCI really chew up
// PCI bandwidth unless FSBR is disabled
@@ -1802,9 +1799,6 @@
usb_sndbulkpipe (dev->udev, info->out),
skb->data, skb->len, tx_complete, skb);
urb->transfer_flags |= USB_ASYNC_UNLINK;
-#ifdef REALLY_QUEUE
- urb->transfer_flags |= USB_QUEUE_BULK;
-#endif
// FIXME urb->timeout = ... jiffies ... ;
spin_lock_irqsave (&dev->txq.lock, flags);
--- ./drivers/usb-dist/serial/kl5kusb105.c Tue Jun 18 18:06:27 2002
+++ ./drivers/usb/serial/kl5kusb105.c Sat Jul 6 06:49:22 2002
@@ -391,7 +391,6 @@
port->read_urb->transfer_buffer_length,
klsi_105_read_bulk_callback,
port);
- port->read_urb->transfer_flags |= USB_QUEUE_BULK;
rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (rc) {
@@ -537,8 +536,6 @@
URB_TRANSFER_BUFFER_SIZE,
klsi_105_write_bulk_callback,
port);
- urb->transfer_flags |= USB_QUEUE_BULK;
-
/* send the data out the bulk port */
result = usb_submit_urb(urb, GFP_ATOMIC);
--- ./drivers/usb-dist/serial/io_edgeport.c Sun May 26 15:55:03 2002
+++ ./drivers/usb/serial/io_edgeport.c Sat Jul 6 06:49:22 2002
@@ -1460,9 +1460,6 @@
usb_sndbulkpipe(edge_serial->serial->dev,
edge_serial->bulk_out_endpoint),
buffer, count+2, edge_bulk_out_data_callback, edge_port);
- /* set the USB_BULK_QUEUE flag so that we can shove a bunch of urbs at once
down the pipe */
- urb->transfer_flags |= USB_QUEUE_BULK;
-
urb->dev = edge_serial->serial->dev;
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
@@ -2488,9 +2485,6 @@
usb_sndbulkpipe(edge_serial->serial->dev,
edge_serial->bulk_out_endpoint),
buffer, length, edge_bulk_out_cmd_callback, edge_port);
- /* set the USB_BULK_QUEUE flag so that we can shove a bunch of urbs at once
down the pipe */
- urb->transfer_flags |= USB_QUEUE_BULK;
-
edge_port->commandPending = TRUE;
status = usb_submit_urb(urb, GFP_ATOMIC);
--- ./drivers/usb-dist/serial/visor.c Tue Jun 18 18:06:27 2002
+++ ./drivers/usb/serial/visor.c Sat Jul 6 06:49:22 2002
@@ -390,7 +390,6 @@
port->bulk_out_endpointAddress),
buffer, count,
visor_write_bulk_callback, port);
- urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
--- ./drivers/usb-dist/serial/empeg.c Tue Jun 18 18:06:27 2002
+++ ./drivers/usb/serial/empeg.c Sat Jul 6 07:04:09 2002
@@ -171,8 +171,6 @@
empeg_read_bulk_callback,
port);
- port->read_urb->transfer_flags |= USB_QUEUE_BULK;
-
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
@@ -270,8 +268,6 @@
empeg_write_bulk_callback,
port);
- urb->transfer_flags |= USB_QUEUE_BULK;
-
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
@@ -424,8 +420,6 @@
empeg_read_bulk_callback,
port);
- port->read_urb->transfer_flags |= USB_QUEUE_BULK;
-
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
--- ./drivers/usb-dist/serial/ir-usb.c Tue Jun 18 18:06:27 2002
+++ ./drivers/usb/serial/ir-usb.c Sat Jul 6 06:49:22 2002
@@ -311,7 +311,6 @@
port->read_urb->transfer_buffer_length,
ir_read_bulk_callback,
port);
- port->read_urb->transfer_flags = USB_QUEUE_BULK;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
@@ -389,9 +388,7 @@
ir_write_bulk_callback,
port);
- port->write_urb->transfer_flags
- = USB_QUEUE_BULK
- | USB_ZERO_PACKET;
+ port->write_urb->transfer_flags = USB_ZERO_PACKET;
result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
@@ -501,8 +498,6 @@
ir_read_bulk_callback,
port);
- port->read_urb->transfer_flags = USB_QUEUE_BULK;
-
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
@@ -598,9 +593,7 @@
ir_write_bulk_callback,
port);
- port->write_urb->transfer_flags
- = USB_QUEUE_BULK
- | USB_ZERO_PACKET;
+ port->write_urb->transfer_flags = USB_ZERO_PACKET;
result = usb_submit_urb (port->write_urb, GFP_KERNEL);
if (result)
--- ./drivers/net/irda-dist/irda-usb.c Wed Jun 26 11:36:22 2002
+++ ./drivers/net/irda/irda-usb.c Sat Jul 6 08:21:16 2002
@@ -273,7 +273,7 @@
frame, IRDA_USB_SPEED_MTU,
speed_bulk_callback, self);
urb->transfer_buffer_length = USB_IRDA_HEADER;
- urb->transfer_flags = USB_QUEUE_BULK | USB_ASYNC_UNLINK;
+ urb->transfer_flags = USB_ASYNC_UNLINK;
urb->timeout = MSECS_TO_JIFFIES(100);
/* Irq disabled -> GFP_ATOMIC */
@@ -410,7 +410,7 @@
urb->transfer_buffer_length = skb->len;
/* Note : unlink *must* be Asynchronous because of the code in
* irda_usb_net_timeout() -> call in irq - Jean II */
- urb->transfer_flags = USB_QUEUE_BULK | USB_ASYNC_UNLINK;
+ urb->transfer_flags = USB_ASYNC_UNLINK;
/* This flag (USB_ZERO_PACKET) indicates that what we send is not
* a continuous stream of data but separate packets.
* In this case, the USB layer will insert an empty USB frame (TD)
@@ -736,7 +736,6 @@
usb_rcvbulkpipe(self->usbdev, self->bulk_in_ep),
skb->data, skb->truesize,
irda_usb_receive, skb);
- urb->transfer_flags = USB_QUEUE_BULK;
/* Note : unlink *must* be synchronous because of the code in
* irda_usb_net_close() -> free the skb - Jean II */
urb->status = 0;
--- ./drivers/bluetooth-dist/hci_usb.c Tue May 7 06:06:05 2002
+++ ./drivers/bluetooth/hci_usb.c Sat Jul 6 07:05:31 2002
@@ -176,7 +176,6 @@
pipe = usb_rcvbulkpipe(husb->udev, husb->bulk_in_ep);
FILL_BULK_URB(urb, husb->udev, pipe, skb->data, size, hci_usb_rx_complete,
skb);
- urb->transfer_flags = USB_QUEUE_BULK;
skb_queue_tail(&husb->pending_q, skb);
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -318,7 +317,7 @@
FILL_BULK_URB(urb, husb->udev, pipe, skb->data, skb->len,
hci_usb_tx_complete, skb);
- urb->transfer_flags = USB_QUEUE_BULK | USB_ZERO_PACKET;
+ urb->transfer_flags = USB_ZERO_PACKET;
BT_DBG("%s urb %p len %d", husb->hdev.name, urb, skb->len);
--- ./Documentation/usb-dist/error-codes.txt Sun Apr 14 12:18:43 2002
+++ ./Documentation/usb/error-codes.txt Sat Jul 6 09:25:09 2002
@@ -22,9 +22,8 @@
-ENODEV specified USB-device or bus doesn't exist
--ENXIO a control or interrupt URB is already queued to this endpoint;
- or (UHCI only) a bulk URB is already queued to this endpoint
- and USB_QUEUE_BULK wasn't used
+-ENXIO host controller driver does not support queuing of this type
+ of urb. (treat as a host controller bug.)
-EINVAL a) Invalid transfer type specified (or not supported)
b) Invalid interrupt interval (0<=n<256)
@@ -90,9 +89,9 @@
greater than either the max packet size of the
endpoint or the remaining buffer size. "Babble".
--EREMOTEIO The endpoint returned less than max packet size
- and that amount did not fill the specified buffer
- (and USB_DISBLE_SPD was not set in transfer_flags)
+-EREMOTEIO The data read from the endpoint did not fill the
+ specified buffer, and URB_SHORT_NOT_OK was set in
+ urb->transfer_flags.
-ETIMEDOUT transfer timed out, NAK
--- ./Documentation/usb-dist/URB.txt Sun Apr 14 12:18:49 2002
+++ ./Documentation/usb/URB.txt Sat Jul 6 11:23:05 2002
@@ -1,6 +1,13 @@
Revised: 2000-Dec-05.
+Again: 2002-Jul-06
+
+ NOTE:
+
+ The USB subsystem now has a substantial section in "The Linux Kernel API"
+ guide (in linux/Documentation/DocBook), generated from the current source
+ code. This particular documentation file isn't particularly current or
+ complete; don't rely on it except for a quick overview.
-1. Specification of the API
1.1. Basic concept or 'What is an URB?'
@@ -8,124 +15,119 @@
called USB Request Block, or URB for short.
- An URB consists of all relevant information to execute any USB transaction
-and deliver the data and status back.
+ and deliver the data and status back.
- Execution of an URB is inherently an asynchronous operation, i.e. the
-usb_submit_urb(urb) call returns immediately after it has successfully queued
-the requested action.
+ usb_submit_urb(urb) call returns immediately after it has successfully queued
+ the requested action.
-- Ongoing transfers for one URB (e.g. ISO) can simply be canceled with
-usb_unlink_urb(urb) at any time.
+- Transfers for one URB can be canceled with usb_unlink_urb(urb) at any time.
- Each URB has a completion handler, which is called after the action
-has been successfully completed or canceled (INT transfers behave a bit
-differently, see below). The URB also contains a context-pointer for free
-usage and information passing to the completion handler.
-
-- URBs can be linked. After completing one URB, the next one can be
-automatically submitted. This is especially useful for ISO transfers:
-You only have read/write the data from/to the buffers in the completion
-handler, the continuous streaming itself is transparently done by the
-URB-machinery.
+ has been successfully completed or canceled. The URB also contains a
+ context-pointer for passing information to the completion handler.
+- Each endpoint for a device logically supports a queue of requests.
+ You can fill that queue, so that the USB hardware can still transfer
+ data to an endpoint while your driver handles completion of another.
+ This maximizes use of USB bandwidth, and supports seamless streaming
+ of data to (or from) devices when using periodic transfer modes.
-1.2. The URB structure
-typedef struct urb
-{
- spinlock_t lock; // lock for the URB
+1.2. The URB structure
-// ignore, for host controller/URB machine internal use
- void *hcpriv; // private data for host controller
- struct list_head urb_list; // list pointer to all active urbs
+Some of the fields in an URB are:
-// This is used for urb linking
- struct urb* next; // pointer to next URB
+struct urb
+{
+// (IN) device and pipe specify the endpoint queue
struct usb_device *dev; // pointer to associated USB device
+ unsigned int pipe; // endpoint information
+
+ unsigned int transfer_flags; // ISO_ASAP, SHORT_NOT_OK, etc.
-// pipe is assembled by the various well-known pipe macros in usb.h
- unsigned int pipe; // pipe information
+// (IN) all urbs need completion routines
+ void *context; // context for completion routine
+ void (*complete)(struct urb *); // pointer to completion routine
-// status after each completion
+// (OUT) status after each completion
int status; // returned status
- unsigned int transfer_flags; // ASAP, DISABLE_SPD, etc.
-// for data stage (CTRL), BULK, INT and ISO
+// (IN) buffer used for data transfers
void *transfer_buffer; // associated data buffer
-
-// expected length
int transfer_buffer_length; // data buffer length
- int actual_length; // actual data buffer length
+ int number_of_packets; // size of iso_frame_desc
+
+// (OUT) sometimes only part of CTRL/BULK/INTR transfer_buffer is used
+ int actual_length; // actual data buffer length
-// setup stage for CTRL (always 8 bytes!)
+// (IN) setup stage for CTRL (pass a struct usb_ctrlrequest)
unsigned char* setup_packet; // setup packet (control only)
-// with ASAP, start_frame is set to the determined frame
- int start_frame; // start frame (iso/irq)
- int number_of_packets; // # of packets (iso/int)
- int interval; // polling interval (irq only)
- int error_count; // number of errors (iso only)
- //
- void *context; // context for completion routine
- usb_complete_t complete; // pointer to completion routine
- //
-// specification of the requested data offsets and length for ISO
- iso_packet_descriptor_t iso_frame_desc[0];
-} urb_t, *purb_t;
+// Only for PERIODIC transfers (ISO, INTERRUPT)
+ // (IN/OUT) start_frame is set unless ISO_ASAP isn't set
+ int start_frame; // start frame
+ int interval; // polling interval
+
+ // ISO only: packets are only "best effort"; each can have errors
+ int error_count; // number of errors
+ struct usb_iso_packet_descriptor iso_frame_desc[0];
+};
+
+Your driver must create the "pipe" value using values from the appropriate
+endpoint descriptor in an interface that it's claimed.
1.3. How to get an URB?
URBs are allocated with the following call
- purb_t usb_alloc_urb(int isoframes)
+ struct urb *usb_alloc_urb(int isoframes, int mem_flags)
Return value is a pointer to the allocated URB, 0 if allocation failed.
The parameter isoframes specifies the number of isochronous transfer frames
-you want to schedule. For CTRL/BULK/INT, use 0.
+you want to schedule. For CTRL/BULK/INT, use 0. The mem_flags paramter
+holds standard memory allocation flags, letting you control (among other
+things) whether the underlying code may block or not.
To free an URB, use
- void usb_free_urb(purb_t purb)
+ void usb_free_urb(struct urb *urb)
-This call also may free internal (host controller specific) memory in the
-future.
+You may not free an urb that you've submitted, but which hasn't yet been
+returned to you in a completion callback.
1.4. What has to be filled in?
-Depending on the type of transaction, there are some macros
-(FILL_CONTROL_URB, FILL_CONTROL_URB_TO, FILL_BULK_URB,
-FILL_BULK_URB_TO, and FILL_INT_URB, defined in usb.h)
-that simplify the URB creation. In general, all macros need the usb
+Depending on the type of transaction, there are some inline functions
+defined in <linux/usb.h> to simplify the initialization, such as
+fill_control_urb() and fill_bulk_urb(). In general, they need the usb
device pointer, the pipe (usual format from usb.h), the transfer buffer,
the desired transfer length, the completion handler, and its context.
-Take a look at the usb_control_msg function that converts the old API
-into the URB API.
+Take a look at the some existing drivers to see how they're used.
Flags:
For ISO there are two startup behaviors: Specified start_frame or ASAP.
For ASAP set USB_ISO_ASAP in transfer_flags.
-If short packets should NOT be tolerated, set USB_DISABLE_SPD in
+If short packets should NOT be tolerated, set URB_SHORT_NOT_OK in
transfer_flags.
-Usually, to reduce restart time, the completion handler is called
-AFTER the URB re-submission. However, it is called BEFORE URB
-re-submission for INT transfers that are being continued.
-
1.5. How to submit an URB?
Just call
- int usb_submit_urb(purb_t purb)
+ int usb_submit_urb(struct urb *urb, int mem_flags)
+
+The mem_flags parameter, such as SLAB_ATOMIC, controls memory allocation,
+such as whether the lower levels may block when memory is tight.
It immediately returns, either with status 0 (request queued) or some
error code, usually caused by the following:
- Out of memory (-ENOMEM)
-- Wrong pipe handle (-ENXIO)
- Unplugged device (-ENODEV)
- Stalled endpoint (-EPIPE)
- Too many queued ISO transfers (-EAGAIN)
@@ -133,13 +135,12 @@
- Invalid INT interval (-EINVAL)
- More than one packet for INT (-EINVAL)
-After submission, urb->status is USB_ST_URB_PENDING (-EINPROGRESS).
+After submission, urb->status is -EINPROGRESS; however, you should never
+look at that value except in your completion callback.
-For isochronous endpoints, subsequent submitting of URBs to the same endpoint
-with the ASAP flag result in a seamless ISO streaming. Exception: The
-execution cannot be scheduled later than 900 frames from the 'now'-time.
-The same applies to INT transfers, but here the seamless continuation is
-independent of the transfer flags (implicitly ASAP).
+For isochronous endpoints, your completion handlers should (re)submit
+URBs to the same endpoint with the ISO_ASAP flag, using multi-buffering,
+to get seamless ISO streaming.
1.6. How to cancel an already running URB?
@@ -147,12 +148,12 @@
For an URB which you've submitted, but which hasn't been returned to
your driver by the host controller, call
- int usb_unlink_urb(purb_t purb)
+ int usb_unlink_urb(struct urb *urb)
It removes the urb from the internal list and frees all allocated
-HW descriptors. The status is changed to USB_ST_URB_KILLED. After
-usb_unlink_urb() returns, you can safely free the URB with usb_free_urb(urb)
-and all other possibly associated data (urb->context etc.)
+HW descriptors. The status is changed to reflect unlinking. After
+usb_unlink_urb() returns with that status code, you can free the URB
+with usb_free_urb().
There is also an asynchronous unlink mode. To use this, set the
the USB_ASYNC_UNLINK flag in urb->transfer flags before calling
@@ -163,10 +164,6 @@
1.7. What about the completion handler?
-The completion handler is optional, but useful for fast data processing
-or wakeup of a sleeping process (as shown in the compatibility wrapper's
-completion handler).
-
The handler is of the following type:
typedef void (*usb_complete_t)(struct urb *);
@@ -176,10 +173,17 @@
detect any USB errors. Since the context parameter is included in the URB,
you can pass information to the completion handler.
+Note that even when an error (or unlink) is reported, data may have been
+transferred. That's because USB transfers are packetized; it might take
+sixteen packets to transfer your 1KByte buffer, and ten of them might
+have transferred succesfully before the completion is called.
+
+
NOTE: ***** WARNING *****
-AVOID using the urb->dev field in your completion handler; it's cleared
-as part of URB unlinking. Instead, use urb->context to hold all the
-data your driver needs.
+Don't use urb->dev field in your completion handler; it's cleared
+as part of giving urbs back to drivers. (Addressing an issue with
+ownership of periodic URBs, which was otherwise ambiguous.) Instead,
+use urb->context to hold all the data your driver needs.
NOTE: ***** WARNING *****
Also, NEVER SLEEP IN A COMPLETION HANDLER. These are normally called
@@ -191,38 +195,58 @@
1.8. How to do isochronous (ISO) transfers?
-For ISO transfers you have to append the iso_packet_descriptor_t structure
-to the URB for each frame you want to schedule. When using usb_alloc_urb(n)
-(recommended), the iso_packets parameter can be used to allocate the
-structures for iso_packets frames.
+For ISO transfers you have to fill a usb_iso_packet_descriptor structure,
+allocated at the end of the URB by usb_alloc_urb(n,mem_flags), for each
+packet you want to schedule. You also have to set urb->interval to say
+how often to make transfers; it's often one per frame (which is once
+every microframe for highspeed devices). The actual interval used will
+be a power of two that's no bigger than what you specify.
+
+The usb_submit_urb() call modifies urb->interval to the implemented interval
+value that is less than or equal to the requested interval value. If
+ISO_ASAP scheduling is used, urb->start_frame is also updated.
For each entry you have to specify the data offset for this frame (base is
transfer_buffer), and the length you want to write/expect to read.
After completion, actual_length contains the actual transferred length and
-status contains the resulting USB-status for the ISO transfer for this frame.
+status contains the resulting status for the ISO transfer for this frame.
It is allowed to specify a varying length from frame to frame (e.g. for
audio synchronisation/adaptive transfer rates). You can also use the length
0 to omit one or more frames (striping).
-As can be concluded from above, the UHCI-driver does not care for continuous
-data in case of short packet ISO reads! There's no fixup_isoc() like in the
-old driver. There may be a common routine to do this in the future, but this
-has nothing to do with the UHCI-driver!
-
-For scheduling you can choose your own start frame or ASAP. As written above,
-queuing more than one ISO frame with ASAP to the same device&endpoint result
-in seamless ISO streaming. For continuous streaming you have to use URB
-linking.
+For scheduling you can choose your own start frame or ISO_ASAP. As explained
+earlier, if you always keep at least one URB queued and your completion
+keeps (re)submitting a later URB, you'll get smooth ISO streaming (if usb
+bandwidth utilization allows).
+
+If you specify your own start frame, make sure it's several frames in advance
+of the current frame. You might want this model if you're synchronizing
+ISO data with some other event stream.
1.9. How to start interrupt (INT) transfers?
-INT transfers are currently implemented with different queues for intervals
-for 1, 2, 4,... 128ms. Only one URB is allocated for each interrupt. After
-calling the completion handler, that URB is recycled by the host controller
-driver (HCD).
-With the submission of one URB, the interrupt is scheduled until it is
-canceled by usb_unlink_urb.
+Interrupt transfers, like isochronous transfers, are periodic, and happen
+in intervals that are powers of two (1, 2, 4 etc) units. Units are frames
+for full and low speed devices, and microframes for high speed ones.
+
+Currently, after you submit one interrupt URB, that urb is owned by the
+host controller driver until you cancel it with usb_unlink_urb(). You
+may unlink interrupt urbs in their completion handlers, if you need to.
+
+After a transfer completion is called, the URB is automagically resubmitted.
+THIS BEHAVIOR IS EXPECTED TO BE REMOVED!!
+
+Interrupt transfers may only send (or receive) the "maxpacket" value for
+the given interrupt endpoint; if you need more data, you will need to
+copy that data out of (or into) another buffer. Similarly, you can't
+queue interrupt transfers.
+THESE RESTRICTIONS ARE EXPECTED TO BE REMOVED!!
+
+Note that this automagic resubmission model does make it awkward to use
+interrupt OUT transfers. The portable solution involves unlinking those
+OUT urbs after the data is transferred, and perhaps submitting a final
+URB for a short packet.
The usb_submit_urb() call modifies urb->interval to the implemented interval
value that is less than or equal to the requested interval value.