Alan,

Please apply this patch to 2.4.0-test1-ac<Latest>.

This is the beginnings of reimplementing USB bandwidth
allocation.  I made enforcement a compile-time option.

Tom Sailer: I will still address your questions/comments...
and anyone else's comments.

Thanks,
~Randy
--- linux/include/linux/usb.h.orig      Mon Jun 12 11:42:48 2000
+++ linux/include/linux/usb.h   Mon Jun 12 16:46:47 2000
@@ -335,6 +335,9 @@
  * New USB Structures                                                         *
  *----------------------------------------------------------------------------*/
 
+/*
+ * urb->transfer_flags:
+ */
 #define USB_DISABLE_SPD         0x0001
 #define USB_ISO_ASAP            0x0002
 #define USB_URB_EARLY_COMPLETE  0x0004
@@ -366,10 +369,11 @@
        void *transfer_buffer;          // associated data buffer
        int transfer_buffer_length;     // data buffer length
        int actual_length;              // actual data buffer length    
+       int bandwidth;                  // bandwidth for this transfer request (INT or 
+ISO)
        unsigned char *setup_packet;    // setup packet (control only)
        //
        int start_frame;                // start frame (iso/irq only)
-       int number_of_packets;          // number of packets in this request (iso/irq 
only)
+       int number_of_packets;          // number of packets in this request (iso)
        int interval;                   // polling interval (irq only)
        int error_count;                // number of errors in this transfer (iso only)
        int timeout;                    // timeout (in jiffies)
@@ -487,7 +491,7 @@
        struct list_head bus_list;
        void *hcpriv;                   /* Host Controller private data */
 
-       unsigned int bandwidth_allocated; /* on this Host Controller; */
+       int bandwidth_allocated;        /* on this Host Controller; */
                                          /* applies to Int. and Isoc. pipes; */
                                          /* measured in microseconds/frame; */
                                          /* range is 0..900, where 900 = */
@@ -562,7 +566,10 @@
 extern void usb_free_dev(struct usb_device *);
 extern void usb_inc_dev_use(struct usb_device *);
 #define usb_dec_dev_use usb_free_dev
-extern void usb_release_bandwidth(struct usb_device *, int);
+
+extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
+extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int 
+bustime, int isoc);
+extern void usb_release_bandwidth(struct usb_device *dev, struct urb *urb, int isoc);
 
 extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, 
__u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
 
diff -Naur -X /home/rdunlap/doc/dontdiff linux/drivers/usb-patch/Config.in 
linux/drivers/usb/Config.in
--- linux/drivers/usb-patch/Config.in   Sun Jun 11 11:03:53 2000
+++ linux/drivers/usb/Config.in Mon Jun 12 16:32:49 2000
@@ -10,6 +10,11 @@
 
 comment 'Miscellaneous USB options'
    bool '  Preliminary USB device filesystem' CONFIG_USB_DEVICEFS
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      bool '  Enforce USB bandwidth allocation (EXPERIMENTAL)' CONFIG_USB_BANDWIDTH
+   else
+      define_bool CONFIG_USB_BANDWIDTH n
+   fi
 
 comment 'USB Controllers'
    if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
diff -Naur -X /home/rdunlap/doc/dontdiff linux/drivers/usb-patch/usb.c 
linux/drivers/usb/usb.c
--- linux/drivers/usb-patch/usb.c       Sun Jun 11 13:01:41 2000
+++ linux/drivers/usb/usb.c     Mon Jun 12 16:43:09 2000
@@ -6,6 +6,7 @@
  * (C) Copyright Andreas Gal 1999
  * (C) Copyright Gregory P. Smith 1999
  * (C) Copyright Deti Fliegl 1999 (new USB architecture)
+ * (C) Copyright Randy Dunlap 2000
  *
  * NOTE! This is not actually a driver at all, rather this is
  * just a collection of helper routines that implement the
@@ -31,6 +32,13 @@
 #endif
 #include <linux/usb.h>
 
+static const int usb_bandwidth_option =
+#ifdef CONFIG_USB_BANDWIDTH
+                               1;
+#else
+                               0;
+#endif
+
 /*
  * Prototypes for the device driver probing/loading functions
  */
@@ -159,11 +167,11 @@
 }
 
 /*
- * calc_bus_time:
+ * usb_calc_bus_time:
  *
  * returns (approximate) USB bus time in nanoseconds for a USB transaction.
  */
-static long calc_bus_time (int low_speed, int input_dir, int isoc, int bytecount)
+static long usb_calc_bus_time (int low_speed, int input_dir, int isoc, int bytecount)
 {
        unsigned long   tmp;
 
@@ -193,16 +201,16 @@
 
        tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
        return (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
-} /* end calc_bus_time */
+}
 
 /*
- * check_bandwidth_alloc():
+ * usb_check_bandwidth():
  *
  * old_alloc is from host_controller->bandwidth_allocated in microseconds;
  * bustime is from calc_bus_time(), but converted to microseconds.
  *
- * returns 0 if successful,
- * -1 if bandwidth request fails.
+ * returns <bustime in us> if successful,
+ * or USB_ST_BANDWIDTH_ERROR if bandwidth request fails.
  *
  * FIXME:
  * This initial implementation does not use Endpoint.bInterval
@@ -219,21 +227,67 @@
  * However, this first cut at USB bandwidth allocation does not
  * contain any frame allocation tracking.
  */
-static int check_bandwidth_alloc (unsigned int old_alloc, long bustime)
+int usb_check_bandwidth (struct usb_device *dev, struct urb *urb)
 {
-       unsigned int    new_alloc;
+       int             new_alloc;
+       int             old_alloc = dev->bus->bandwidth_allocated;
+       unsigned int    pipe = urb->pipe;
+       long            bustime;
+
+       bustime = usb_calc_bus_time (usb_pipeslow(pipe), usb_pipein(pipe),
+                       usb_pipeisoc(pipe), usb_maxpacket(dev, pipe, 
+usb_pipeout(pipe)));
+       if (usb_pipeisoc(pipe))
+               bustime = NS_TO_US(bustime) / urb->number_of_packets;
+       else
+               bustime = NS_TO_US(bustime);
 
-       new_alloc = old_alloc + bustime;
+       new_alloc = old_alloc + (int)bustime;
                /* what new total allocated bus time would be */
 
-       dbg("usb-bandwidth-alloc: was: %u, new: %u, "
-               "bustime = %ld us, Pipe allowed: %s",
-               old_alloc, new_alloc, bustime,
-               (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ?
-                       "yes" : "no");
+       if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC)
+               dbg("usb-check-bandwidth %sFAILED: was %u, would be %u, bustime = %ld 
+us",
+                       usb_bandwidth_option ? "" : "would have ",
+                       old_alloc, new_alloc, bustime);
+
+       if (!usb_bandwidth_option)      /* don't enforce it */
+               return (bustime);
+       return (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? bustime : 
+USB_ST_BANDWIDTH_ERROR;
+}
+
+void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int 
+isoc)
+{
+       dev->bus->bandwidth_allocated += bustime;
+       if (isoc)
+               dev->bus->bandwidth_isoc_reqs++;
+       else
+               dev->bus->bandwidth_int_reqs++;
+       urb->bandwidth = bustime;
+       
+       dbg("bw_alloc increased by %d to %d for %d requesters",
+               bustime,
+               dev->bus->bandwidth_allocated,
+               dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
+}
+
+/*
+ * usb_release_bandwidth():
+ *
+ * called to release a pipe's bandwidth (in microseconds)
+ */
+void usb_release_bandwidth(struct usb_device *dev, struct urb *urb, int isoc)
+{
+       dev->bus->bandwidth_allocated -= urb->bandwidth;
+       if (isoc)
+               dev->bus->bandwidth_isoc_reqs--;
+       else
+               dev->bus->bandwidth_int_reqs--;
 
-       return (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? 0 : -1;
-} /* end check_bandwidth_alloc */
+       dbg("bw_alloc reduced by %d to %d for %d requesters",
+               urb->bandwidth,
+               dev->bus->bandwidth_allocated,
+               dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
+       urb->bandwidth = 0;
+}
 
 /*
  * New functions for (de)registering a controller
@@ -677,21 +731,6 @@
 }
 
 /*
- * usb_release_bandwidth():
- *
- * called to release an interrupt pipe's bandwidth (in microseconds)
- */
-void usb_release_bandwidth(struct usb_device *dev, int bw_alloc)
-{
-       dev->bus->bandwidth_allocated -= bw_alloc;
-       dev->bus->bandwidth_int_reqs--;
-       dbg("bw_alloc reduced to %d for %d requesters",
-               dev->bus->bandwidth_allocated,
-               dev->bus->bandwidth_int_reqs +
-               dev->bus->bandwidth_isoc_reqs);
-}
-
-/*
  * usb_get_current_frame_number()
  *
  * returns the current frame number for the parent USB bus/controller
@@ -702,6 +741,7 @@
        return usb_dev->bus->op->get_frame_number (usb_dev);
 }
 /*-------------------------------------------------------------------*/
+
 static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor 
*endpoint, unsigned char *buffer, int size)
 {
        struct usb_descriptor_header *header;
@@ -1740,6 +1780,9 @@
 EXPORT_SYMBOL(usb_reset_device);
 EXPORT_SYMBOL(usb_connect);
 EXPORT_SYMBOL(usb_disconnect);
+
+EXPORT_SYMBOL(usb_check_bandwidth);
+EXPORT_SYMBOL(usb_claim_bandwidth);
 EXPORT_SYMBOL(usb_release_bandwidth);
 
 EXPORT_SYMBOL(usb_set_address);
--- linux/Documentation/Configure.help.org      Sun Jun 11 11:03:51 2000
+++ linux/Documentation/Configure.help  Mon Jun 12 16:12:48 2000
@@ -9969,6 +9969,17 @@
 
   Most users want to say Y here.
 
+USB Bandwidth allocation
+CONFIG_USB_BANDWIDTH
+  If you say Y here, the USB subsystem enforces USB bandwidth
+  allocation and will prevent some device opens from succeeding
+  if they would cause USB bandwidth usage to go above 90% of
+  the bus bandwidth.
+
+  If you say N here, these conditions will cause warning messages
+  about USB bandwidth usage to be logged and some devices or
+  drivers may not work correctly.
+
 DABUSB driver
 CONFIG_USB_DABUSB
   A Digital Audio Broadcasting (DAB) Receiver for USB and Linux

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to