Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Nov 2009 16:48:38 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 170406 for review
Message-ID:  <200911091648.nA9Gmc3B017251@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=170406

Change 170406 by hselasky@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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911091648.nA9Gmc3B017251>