# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.635   -> 1.636  
#       drivers/usb/net/usbnet.c        1.25    -> 1.26   
#       Documentation/usb/error-codes.txt       1.4     -> 1.5    
#       drivers/usb/serial/io_edgeport.c        1.28    -> 1.29   
#       drivers/usb/media/stv680.c      1.17    -> 1.18   
#       drivers/usb/class/bluetty.c     1.24    -> 1.25   
#       include/linux/usbdevice_fs.h    1.5     -> 1.6    
#       drivers/usb/host/ehci-q.c       1.17    -> 1.18   
#       drivers/usb/media/se401.c       1.21    -> 1.22   
#       drivers/usb/serial/visor.c      1.34    -> 1.35   
#       Documentation/usb/URB.txt       1.1     -> 1.2    
#        include/linux/usb.h    1.39    -> 1.40   
#       drivers/usb/serial/empeg.c      1.26    -> 1.27   
#       drivers/usb/serial/ir-usb.c     1.16    -> 1.17   
#       drivers/usb/core/devio.c        1.27    -> 1.28   
#       drivers/net/irda/irda-usb.c     1.20    -> 1.21   
#       drivers/usb/serial/kl5kusb105.c 1.9     -> 1.10   
#       drivers/usb/core/urb.c  1.3     -> 1.4    
#       drivers/usb/host/uhci-hcd.c     1.5     -> 1.6    
#       drivers/usb/host/ohci-q.c       1.11    -> 1.12   
#       drivers/bluetooth/hci_usb.c     1.7     -> 1.8    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/07/07      [EMAIL PROTECTED]     1.636
# [PATCH] urb->transfer_flags updates
# 
# 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 ... :)
# --------------------------------------------
#
diff -Nru a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt
--- a/Documentation/usb/URB.txt Sun Jul  7 12:35:13 2002
+++ b/Documentation/usb/URB.txt Sun Jul  7 12:35:13 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
 
-// setup stage for CTRL (always 8 bytes!)
+// (OUT) sometimes only part of CTRL/BULK/INTR transfer_buffer is used
+       int actual_length;              // actual data buffer length
+
+// (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.
diff -Nru a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
--- a/Documentation/usb/error-codes.txt Sun Jul  7 12:35:12 2002
+++ b/Documentation/usb/error-codes.txt Sun Jul  7 12:35:12 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
 
diff -Nru a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
--- a/drivers/bluetooth/hci_usb.c       Sun Jul  7 12:35:13 2002
+++ b/drivers/bluetooth/hci_usb.c       Sun Jul  7 12:35:13 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);
 
diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
--- a/drivers/net/irda/irda-usb.c       Sun Jul  7 12:35:13 2002
+++ b/drivers/net/irda/irda-usb.c       Sun Jul  7 12:35:13 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;
diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
--- a/drivers/usb/class/bluetty.c       Sun Jul  7 12:35:12 2002
+++ b/drivers/usb/class/bluetty.c       Sun Jul  7 12:35:13 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);
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c  Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/core/devio.c  Sun Jul  7 12:35:13 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)
diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
--- a/drivers/usb/core/urb.c    Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/core/urb.c    Sun Jul  7 12:35:13 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;
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/host/ehci-q.c Sun Jul  7 12:35:13 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;
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/host/ohci-q.c Sun Jul  7 12:35: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);
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c       Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/host/uhci-hcd.c       Sun Jul  7 12:35: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;
diff -Nru a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
--- a/drivers/usb/media/se401.c Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/media/se401.c Sun Jul  7 12:35:13 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;
 
diff -Nru a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
--- a/drivers/usb/media/stv680.c        Sun Jul  7 12:35:12 2002
+++ b/drivers/usb/media/stv680.c        Sun Jul  7 12:35:12 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)
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c  Sun Jul  7 12:35:12 2002
+++ b/drivers/usb/net/usbnet.c  Sun Jul  7 12:35:12 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);
diff -Nru a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
--- a/drivers/usb/serial/empeg.c        Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/serial/empeg.c        Sun Jul  7 12:35:13 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) {
@@ -423,8 +419,6 @@
                port->read_urb->transfer_buffer_length,
                empeg_read_bulk_callback,
                port);
-
-       port->read_urb->transfer_flags |= USB_QUEUE_BULK;
 
        result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 
diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c  Sun Jul  7 12:35:12 2002
+++ b/drivers/usb/serial/io_edgeport.c  Sun Jul  7 12:35:12 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) {
@@ -2487,9 +2484,6 @@
        FILL_BULK_URB (urb, edge_serial->serial->dev, 
                       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);
diff -Nru a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
--- a/drivers/usb/serial/ir-usb.c       Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/serial/ir-usb.c       Sun Jul  7 12:35:13 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)
diff -Nru a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
--- a/drivers/usb/serial/kl5kusb105.c   Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/serial/kl5kusb105.c   Sun Jul  7 12:35:13 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);
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c        Sun Jul  7 12:35:13 2002
+++ b/drivers/usb/serial/visor.c        Sun Jul  7 12:35:13 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);
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h       Sun Jul  7 12:35:13 2002
+++ b/include/linux/usb.h       Sun Jul  7 12:35:13 2002
@@ -466,7 +466,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
@@ -722,16 +722,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 {
@@ -777,9 +775,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.
@@ -814,14 +812,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.
@@ -853,7 +847,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
@@ -892,7 +886,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 */
diff -Nru a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
--- a/include/linux/usbdevice_fs.h      Sun Jul  7 12:35:13 2002
+++ b/include/linux/usbdevice_fs.h      Sun Jul  7 12:35:13 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


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
We have stuff for geeks like you.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to