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]