PERFORCE change 170406 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Mon Nov 9 16:48:38 UTC 2009
http://p4web.freebsd.org/chv.cgi?CH=170406
Change 170406 by hselasky at hselasky_laptop001 on 2009/11/09 16:47:48
USB CORE:
- Improve High Speed slot allocation mechanism.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/controller/ehci.c#42 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_hub.c#36 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_hub.h#14 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/controller/ehci.c#42 (text+ko) ====
@@ -2356,19 +2356,21 @@
/* Allocate a microframe slot first: */
- slot = usb_intr_schedule_adjust
- (xfer->xroot->udev, xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX);
+ slot = usb_intr_schedule_adjust(xfer->xroot->udev,
+ xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX, 0x01);
if (usbd_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) {
xfer->usb_uframe = slot;
- xfer->usb_smask = (1 << slot) & 0xFF;
- xfer->usb_cmask = 0;
+ xfer->usb_smask = (0x01 << slot) & 0xFF;
+ xfer->usb_cmask = 0x00;
} else {
xfer->usb_uframe = slot;
- xfer->usb_smask = (1 << slot) & 0x3F;
- xfer->usb_cmask = (-(4 << slot)) & 0xFE;
+ xfer->usb_smask = (0x01 << slot) & 0x3F;
+ xfer->usb_cmask = (-(0x04 << slot)) & 0xFE;
}
+ DPRINTFN(11, "slot=%d\n", slot);
+
/*
* Find the best QH position corresponding to the given interval:
*/
@@ -2403,8 +2405,10 @@
{
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
+ /* Free microframe slot: */
+
usb_intr_schedule_adjust(xfer->xroot->udev,
- -(xfer->max_frame_size), xfer->usb_uframe);
+ -xfer->max_frame_size, xfer->usb_uframe, 0x01);
sc->sc_intr_stat[xfer->qh_pos]--;
@@ -2731,28 +2735,34 @@
uint32_t temp;
uint8_t ds;
uint8_t slot;
-
- slot = usb_intr_schedule_adjust(xfer->xroot->udev, xfer->max_frame_size,
- USB_HS_MICRO_FRAMES_MAX);
-
- xfer->usb_uframe = slot;
- xfer->usb_cmask = 0;
+ uint8_t mask;
switch (usbd_xfer_get_fps_shift(xfer)) {
case 0:
- xfer->usb_smask = 0xFF;
+ mask = 0xFF;
break;
case 1:
- xfer->usb_smask = 0x55 << (slot & 1);
+ mask = 0x55;
break;
case 2:
- xfer->usb_smask = 0x11 << (slot & 3);
+ mask = 0x11;
break;
default:
- xfer->usb_smask = 0x01 << (slot & 7);
+ mask = 0x01;
break;
}
+ /* Allocate a microframe multi-slot first: */
+
+ slot = usb_intr_schedule_adjust(xfer->xroot->udev,
+ xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX, mask);
+
+ xfer->usb_uframe = slot;
+ xfer->usb_cmask = 0;
+ xfer->usb_smask = mask << slot;
+
+ DPRINTFN(11, "slot=%d, mask=0x%02x\n", slot, mask);
+
/* initialize all TD's */
for (ds = 0; ds != 2; ds++) {
@@ -2796,8 +2806,11 @@
ehci_device_isoc_hs_close(struct usb_xfer *xfer)
{
+ /* Free microframe multi-slot: */
+
usb_intr_schedule_adjust(xfer->xroot->udev,
- -(xfer->max_frame_size), xfer->usb_uframe);
+ -xfer->max_frame_size, xfer->usb_uframe,
+ xfer->usb_smask >> xfer->usb_uframe);
ehci_device_done(xfer, USB_ERR_CANCELLED);
}
==== //depot/projects/usb/src/sys/dev/usb/usb_hub.c#36 (text+ko) ====
@@ -1108,21 +1108,38 @@
* The best Transaction Translation slot for an interrupt endpoint.
*------------------------------------------------------------------------*/
static uint8_t
-usb_intr_find_best_slot(usb_size_t *ptr, uint8_t start, uint8_t end)
+usb_intr_find_best_slot(usb_size_t *ptr, uint8_t start,
+ uint8_t end, uint8_t mask)
{
- usb_size_t max = 0 - 1;
+ usb_size_t min = 0 - 1;
+ usb_size_t sum;
uint8_t x;
uint8_t y;
+ uint8_t z;
y = 0;
/* find the last slot with lesser used bandwidth */
for (x = start; x < end; x++) {
- if (max >= ptr[x]) {
- max = ptr[x];
+
+ sum = 0;
+
+ /* compute sum of bandwidth */
+ for (z = x; z < end; z++) {
+ if (mask & (1U << (z - x)))
+ sum += ptr[z];
+ }
+
+ /* check if the current multi-slot is more optimal */
+ if (min >= sum) {
+ min = sum;
y = x;
}
+
+ /* check if the mask is about to be shifted out */
+ if (mask & (1U << (end - 1 - x)))
+ break;
}
return (y);
}
@@ -1134,17 +1151,19 @@
* having index "slot" by "len" bytes. "len" can be negative. If the
* "slot" argument is greater or equal to "USB_HS_MICRO_FRAMES_MAX"
* the "slot" argument will be replaced by the slot having least used
- * bandwidth.
+ * bandwidth. The "mask" argument is used for multi-slot allocations.
*
* Returns:
- * The slot on which the bandwidth update was done.
+ * The slot in which the bandwidth update was done: 0..7
*------------------------------------------------------------------------*/
uint8_t
-usb_intr_schedule_adjust(struct usb_device *udev, int16_t len, uint8_t slot)
+usb_intr_schedule_adjust(struct usb_device *udev, int16_t len,
+ uint8_t slot, uint8_t mask)
{
struct usb_bus *bus = udev->bus;
struct usb_hub *hub;
enum usb_dev_speed speed;
+ uint8_t x;
USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
@@ -1166,17 +1185,25 @@
hub = udev->parent_hs_hub->hub;
if (slot >= USB_HS_MICRO_FRAMES_MAX) {
slot = usb_intr_find_best_slot(hub->uframe_usage,
- USB_FS_ISOC_UFRAME_MAX, 6);
+ USB_FS_ISOC_UFRAME_MAX, 6, mask);
+ }
+ for (x = slot; x < 8; x++) {
+ if (mask & (1U << (x - slot))) {
+ hub->uframe_usage[x] += len;
+ bus->uframe_usage[x] += len;
+ }
}
- hub->uframe_usage[slot] += len;
- bus->uframe_usage[slot] += len;
break;
default:
if (slot >= USB_HS_MICRO_FRAMES_MAX) {
slot = usb_intr_find_best_slot(bus->uframe_usage, 0,
- USB_HS_MICRO_FRAMES_MAX);
+ USB_HS_MICRO_FRAMES_MAX, mask);
+ }
+ for (x = slot; x < 8; x++) {
+ if (mask & (1U << (x - slot))) {
+ bus->uframe_usage[x] += len;
+ }
}
- bus->uframe_usage[slot] += len;
break;
}
return (slot);
==== //depot/projects/usb/src/sys/dev/usb/usb_hub.h#14 (text+ko) ====
@@ -67,7 +67,7 @@
/* function prototypes */
uint8_t usb_intr_schedule_adjust(struct usb_device *udev, int16_t len,
- uint8_t slot);
+ uint8_t slot, uint8_t mask);
void usbd_fs_isoc_schedule_init_all(struct usb_fs_isoc_schedule *fss);
void usb_bus_port_set_device(struct usb_bus *bus, struct usb_port *up,
struct usb_device *udev, uint8_t device_index);
More information about the p4-projects
mailing list