# 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.549 -> 1.550
# drivers/usb/devices.c 1.7 -> 1.8
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/03/19 [EMAIL PROTECTED] 1.550
# USB usbfs periodic endpoint/bandwidth reporting
#
# This is an updated version of a patch I sent around a
# while back. It's against 2.5.7-pre1 (so presumably is
# fine on 2.5.7), and addresses feedback against that
# earlier patch.
#
# It's bugfixes, mostly for highspeed support, to what
# /proc/bus/usb/devices shows:
#
# - Shows isochronous periods correctly (logarithmic
# encoding, possibly 1/2/4 microframes if highspeed)
# - Likewise for high-speed interrupt periods (similar)
# - Makes high bandwidth endpoints look like they
# just do bigger packets (up to 3 KBytes/uframe)
# - Shows highspeed bandwidth correctlly (80% reserved,
# vs 90% reserved for full/low speed).
# --------------------------------------------
#
diff -Nru a/drivers/usb/devices.c b/drivers/usb/devices.c
--- a/drivers/usb/devices.c Wed Apr 3 16:40:00 2002
+++ b/drivers/usb/devices.c Wed Apr 3 16:40:00 2002
@@ -105,8 +105,8 @@
"I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
static char *format_endpt =
-/* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms */
- "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%3dms\n";
+/* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */
+ "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n";
/*
@@ -166,24 +166,71 @@
return (clas_info[ix].class_name);
}
-static char *usb_dump_endpoint_descriptor(char *start, char *end, const struct
usb_endpoint_descriptor *desc)
-{
- char *EndpointType [4] = {"Ctrl", "Isoc", "Bulk", "Int."};
+static char *usb_dump_endpoint_descriptor (
+ int speed,
+ char *start,
+ char *end,
+ const struct usb_endpoint_descriptor *desc
+)
+{
+ char dir, unit, *type;
+ unsigned interval, in, bandwidth = 1;
if (start > end)
return start;
- start += sprintf(start, format_endpt, desc->bEndpointAddress,
- (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_CONTROL
- ? 'B' : /* bidirectional */
- (desc->bEndpointAddress & USB_DIR_IN) ? 'I' : 'O',
- desc->bmAttributes, EndpointType[desc->bmAttributes &
USB_ENDPOINT_XFERTYPE_MASK],
- desc->wMaxPacketSize, desc->bInterval);
- return start;
-}
+ in = (desc->bEndpointAddress & USB_DIR_IN);
+ dir = in ? 'I' : 'O';
+ if (speed == USB_SPEED_HIGH) {
+ switch (desc->wMaxPacketSize & (0x03 << 11)) {
+ case 1 << 11: bandwidth = 2; break;
+ case 2 << 11: bandwidth = 3; break;
+ }
+ }
-static char *usb_dump_endpoint(char *start, char *end, const struct
usb_endpoint_descriptor *endpoint)
-{
- return usb_dump_endpoint_descriptor(start, end, endpoint);
+ /* this isn't checking for illegal values */
+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ type = "Ctrl";
+ if (speed == USB_SPEED_HIGH) /* uframes per NAK */
+ interval = desc->bInterval;
+ else
+ interval = 0;
+ dir = 'B'; /* ctrl is bidirectional */
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ type = "Isoc";
+ interval = 1 << (desc->bInterval - 1);
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ type = "Bulk";
+ if (speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
+ interval = desc->bInterval;
+ else
+ interval = 0;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ type = "Int.";
+ if (speed == USB_SPEED_HIGH) {
+ interval = 1 << (desc->bInterval - 1);
+ } else
+ interval = desc->bInterval;
+ break;
+ default: /* "can't happen" */
+ return start;
+ }
+ interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000;
+ if (interval % 1000)
+ unit = 'u';
+ else {
+ unit = 'm';
+ interval /= 1000;
+ }
+
+ start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
+ desc->bmAttributes, type,
+ (desc->wMaxPacketSize & 0x07ff) * bandwidth,
+ interval, unit);
+ return start;
}
static char *usb_dump_interface_descriptor(char *start, char *end, const struct
usb_interface *iface, int setno)
@@ -204,8 +251,13 @@
return start;
}
-static char *usb_dump_interface(char *start, char *end, const struct usb_interface
*iface, int setno)
-{
+static char *usb_dump_interface(
+ int speed,
+ char *start,
+ char *end,
+ const struct usb_interface *iface,
+ int setno
+) {
struct usb_interface_descriptor *desc = &iface->altsetting[setno];
int i;
@@ -213,7 +265,8 @@
for (i = 0; i < desc->bNumEndpoints; i++) {
if (start > end)
return start;
- start = usb_dump_endpoint(start, end, desc->endpoint + i);
+ start = usb_dump_endpoint_descriptor(speed,
+ start, end, desc->endpoint + i);
}
return start;
}
@@ -238,7 +291,13 @@
return start;
}
-static char *usb_dump_config(char *start, char *end, const struct
usb_config_descriptor *config, int active)
+static char *usb_dump_config (
+ int speed,
+ char *start,
+ char *end,
+ const struct usb_config_descriptor *config,
+ int active
+)
{
int i, j;
struct usb_interface *interface;
@@ -255,7 +314,8 @@
for (j = 0; j < interface->num_altsetting; j++) {
if (start > end)
return start;
- start = usb_dump_interface(start, end, interface, j);
+ start = usb_dump_interface(speed,
+ start, end, interface, j);
}
}
return start;
@@ -336,8 +396,10 @@
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
if (start > end)
return start;
- start = usb_dump_config(start, end, dev->config + i,
- (dev->config + i) == dev->actconfig); /*
active ? */
+ start = usb_dump_config(dev->speed,
+ start, end, dev->config + i,
+ /* active ? */
+ (dev->config + i) == dev->actconfig);
}
return start;
}
@@ -429,16 +491,27 @@
* count = device count at this level
*/
/* If this is the root hub, display the bandwidth information */
- /* FIXME high speed reserves 20% frametime for non-periodic,
- * while full/low speed reserves only 10% ... so this is wrong
- * for high speed busses. also, change how bandwidth is recorded.
- */
- if (level == 0)
- data_end += sprintf(data_end, format_bandwidth,
bus->bandwidth_allocated,
- FRAME_TIME_MAX_USECS_ALLOC,
- (100 * bus->bandwidth_allocated +
FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
- bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
+ if (level == 0) {
+ int max;
+
+ /* high speed reserves 80%, full/low reserves 90% */
+ if (usbdev->speed == USB_SPEED_HIGH)
+ max = 800;
+ else
+ max = FRAME_TIME_MAX_USECS_ALLOC;
+
+ /* report "average" periodic allocation over a microsecond.
+ * the schedules are actually bursty, HCDs need to deal with
+ * that and just compute/report this average.
+ */
+ data_end += sprintf(data_end, format_bandwidth,
+ bus->bandwidth_allocated, max,
+ (100 * bus->bandwidth_allocated + max / 2)
+ / max,
+ bus->bandwidth_int_reqs,
+ bus->bandwidth_isoc_reqs);
+ }
data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256,
usbdev);
if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel