PERFORCE change 170449 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Tue Nov 10 21:44:37 UTC 2009
http://p4web.freebsd.org/chv.cgi?CH=170449
Change 170449 by hselasky at hselasky_laptop001 on 2009/11/10 21:43:38
USB CORE:
- improve and factor out USB High-Speed slot allocation mechanism.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/controller/ehci.c#43 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_core.h#30 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_device.c#57 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_hub.c#37 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_hub.h#15 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#172 edit
.. //depot/projects/usb/src/sys/dev/usb/usbdi.h#14 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/controller/ehci.c#43 (text+ko) ====
@@ -2020,8 +2020,8 @@
qh_endphub =
(EHCI_QH_SET_MULT(xfer->max_packet_count & 3) |
- EHCI_QH_SET_CMASK(xfer->usb_cmask) |
- EHCI_QH_SET_SMASK(xfer->usb_smask) |
+ EHCI_QH_SET_CMASK(xfer->endpoint->usb_cmask) |
+ EHCI_QH_SET_SMASK(xfer->endpoint->usb_smask) |
EHCI_QH_SET_HUBA(xfer->xroot->udev->hs_hub_addr) |
EHCI_QH_SET_PORT(xfer->xroot->udev->hs_port_no));
@@ -2166,7 +2166,7 @@
DPRINTFN(2, "status=0x%08x, len=%u\n", status, len);
- if (xfer->usb_smask & (1 << td_no)) {
+ if (xfer->endpoint->usb_smask & (1 << td_no)) {
if (*plen >= len) {
/*
@@ -2352,25 +2352,9 @@
uint16_t best;
uint16_t bit;
uint16_t x;
- uint8_t slot;
- /* Allocate a microframe slot first: */
-
- 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 = (0x01 << slot) & 0xFF;
- xfer->usb_cmask = 0x00;
- } else {
- xfer->usb_uframe = slot;
- xfer->usb_smask = (0x01 << slot) & 0x3F;
- xfer->usb_cmask = (-(0x04 << slot)) & 0xFE;
- }
+ usb_hs_bandwidth_alloc(xfer);
- DPRINTFN(11, "slot=%d\n", slot);
-
/*
* Find the best QH position corresponding to the given interval:
*/
@@ -2405,14 +2389,12 @@
{
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, 0x01);
-
sc->sc_intr_stat[xfer->qh_pos]--;
ehci_device_done(xfer, USB_ERR_CANCELLED);
+
+ /* bandwidth must be freed after device done */
+ usb_hs_bandwidth_free(xfer);
}
static void
@@ -2734,35 +2716,9 @@
ehci_itd_t *td;
uint32_t temp;
uint8_t ds;
- uint8_t slot;
- uint8_t mask;
- switch (usbd_xfer_get_fps_shift(xfer)) {
- case 0:
- mask = 0xFF;
- break;
- case 1:
- mask = 0x55;
- break;
- case 2:
- mask = 0x11;
- break;
- default:
- 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);
+ usb_hs_bandwidth_alloc(xfer);
- 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++) {
@@ -2805,14 +2761,10 @@
static void
ehci_device_isoc_hs_close(struct usb_xfer *xfer)
{
+ ehci_device_done(xfer, USB_ERR_CANCELLED);
- /* Free microframe multi-slot: */
-
- usb_intr_schedule_adjust(xfer->xroot->udev,
- -xfer->max_frame_size, xfer->usb_uframe,
- xfer->usb_smask >> xfer->usb_uframe);
-
- ehci_device_done(xfer, USB_ERR_CANCELLED);
+ /* bandwidth must be freed after device done */
+ usb_hs_bandwidth_free(xfer);
}
static void
@@ -2922,7 +2874,7 @@
*plen = xfer->max_frame_size;
}
- if (xfer->usb_smask & (1 << td_no)) {
+ if (xfer->endpoint->usb_smask & (1 << td_no)) {
status = (EHCI_ITD_SET_LEN(*plen) |
EHCI_ITD_ACTIVE |
EHCI_ITD_SET_PG(0));
==== //depot/projects/usb/src/sys/dev/usb/usb_core.h#30 (text+ko) ====
@@ -161,9 +161,6 @@
uint8_t address; /* physical USB address */
uint8_t endpointno; /* physical USB endpoint */
uint8_t max_packet_count;
- uint8_t usb_smask;
- uint8_t usb_cmask;
- uint8_t usb_uframe;
uint8_t usb_state;
uint8_t fps_shift; /* down shift of FPS, 0..3 */
==== //depot/projects/usb/src/sys/dev/usb/usb_device.c#57 (text+ko) ====
@@ -665,7 +665,7 @@
/* look for matching endpoints */
if ((iface_index == USB_IFACE_INDEX_ANY) ||
(iface_index == ep->iface_index)) {
- if (ep->refcount != 0) {
+ if (ep->refcount_alloc != 0) {
/*
* This typically indicates a
* more serious error.
==== //depot/projects/usb/src/sys/dev/usb/usb_hub.c#37 (text+ko) ====
@@ -1145,7 +1145,7 @@
}
/*------------------------------------------------------------------------*
- * usb_intr_schedule_adjust
+ * usb_hs_bandwidth_adjust
*
* This function will update the bandwith usage for the microframe
* having index "slot" by "len" bytes. "len" can be negative. If the
@@ -1156,8 +1156,8 @@
* Returns:
* The slot in which the bandwidth update was done: 0..7
*------------------------------------------------------------------------*/
-uint8_t
-usb_intr_schedule_adjust(struct usb_device *udev, int16_t len,
+static uint8_t
+usb_hs_bandwidth_adjust(struct usb_device *udev, int16_t len,
uint8_t slot, uint8_t mask)
{
struct usb_bus *bus = udev->bus;
@@ -1210,6 +1210,132 @@
}
/*------------------------------------------------------------------------*
+ * usb_hs_bandwidth_alloc
+ *
+ * This function is a wrapper function for "usb_hs_bandwidth_adjust()".
+ *------------------------------------------------------------------------*/
+void
+usb_hs_bandwidth_alloc(struct usb_xfer *xfer)
+{
+ struct usb_device *udev;
+ uint8_t slot;
+ uint8_t mask;
+ uint8_t speed;
+
+ udev = xfer->xroot->udev;
+
+ if (udev->flags.usb_mode != USB_MODE_HOST)
+ return; /* not supported */
+
+ xfer->endpoint->refcount_bw++;
+ if (xfer->endpoint->refcount_bw != 1)
+ return; /* already allocated */
+
+ speed = usbd_get_speed(udev);
+
+ switch (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_INTERRUPT:
+ /* allocate a microframe slot */
+
+ mask = 0x01;
+ slot = usb_hs_bandwidth_adjust(udev,
+ xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX, mask);
+
+ xfer->endpoint->usb_uframe = slot;
+ xfer->endpoint->usb_smask = mask << slot;
+
+ if ((speed != USB_SPEED_FULL) &&
+ (speed != USB_SPEED_LOW)) {
+ xfer->endpoint->usb_cmask = 0x00 ;
+ } else {
+ xfer->endpoint->usb_cmask = (-(0x04 << slot)) & 0xFE;
+ }
+ break;
+
+ case UE_ISOCHRONOUS:
+ switch (usbd_xfer_get_fps_shift(xfer)) {
+ case 0:
+ mask = 0xFF;
+ break;
+ case 1:
+ mask = 0x55;
+ break;
+ case 2:
+ mask = 0x11;
+ break;
+ default:
+ mask = 0x01;
+ break;
+ }
+
+ /* allocate a microframe multi-slot */
+
+ slot = usb_hs_bandwidth_adjust(udev,
+ xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX, mask);
+
+ xfer->endpoint->usb_uframe = slot;
+ xfer->endpoint->usb_cmask = 0;
+ xfer->endpoint->usb_smask = mask << slot;
+ break;
+
+ default:
+ xfer->endpoint->usb_uframe = 0;
+ xfer->endpoint->usb_cmask = 0;
+ xfer->endpoint->usb_smask = 0;
+ break;
+ }
+
+ DPRINTFN(11, "slot=%d, mask=0x%02x\n",
+ xfer->endpoint->usb_uframe,
+ xfer->endpoint->usb_smask >> xfer->endpoint->usb_uframe);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_hs_bandwidth_free
+ *
+ * This function is a wrapper function for "usb_hs_bandwidth_adjust()".
+ *------------------------------------------------------------------------*/
+void
+usb_hs_bandwidth_free(struct usb_xfer *xfer)
+{
+ struct usb_device *udev;
+ uint8_t slot;
+ uint8_t mask;
+
+ udev = xfer->xroot->udev;
+
+ if (udev->flags.usb_mode != USB_MODE_HOST)
+ return; /* not supported */
+
+ xfer->endpoint->refcount_bw--;
+ if (xfer->endpoint->refcount_bw != 0)
+ return; /* still allocated */
+
+ switch (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_INTERRUPT:
+ case UE_ISOCHRONOUS:
+
+ slot = xfer->endpoint->usb_uframe;
+ mask = xfer->endpoint->usb_smask;
+
+ /* free microframe slot(s): */
+ usb_hs_bandwidth_adjust(udev,
+ -xfer->max_frame_size, slot, mask >> slot);
+
+ DPRINTFN(11, "slot=%d, mask=0x%02x\n",
+ slot, mask >> slot);
+
+ xfer->endpoint->usb_uframe = 0;
+ xfer->endpoint->usb_cmask = 0;
+ xfer->endpoint->usb_smask = 0;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------*
* usbd_fs_isoc_schedule_init_sub
*
* This function initialises an USB FULL speed isochronous schedule
==== //depot/projects/usb/src/sys/dev/usb/usb_hub.h#15 (text+ko) ====
@@ -66,8 +66,8 @@
/* function prototypes */
-uint8_t usb_intr_schedule_adjust(struct usb_device *udev, int16_t len,
- uint8_t slot, uint8_t mask);
+void usb_hs_bandwidth_alloc(struct usb_xfer *xfer);
+void usb_hs_bandwidth_free(struct usb_xfer *xfer);
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);
==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#172 (text+ko) ====
@@ -942,10 +942,18 @@
* configuration and alternate setting
* when USB transfers are in use on
* the given interface. Search the USB
- * code for "endpoint->refcount" if you
+ * code for "endpoint->refcount_alloc" if you
* want more information.
*/
- xfer->endpoint->refcount++;
+ USB_BUS_LOCK(info->bus);
+ if (xfer->endpoint->refcount_alloc >= USB_EP_REF_MAX)
+ parm.err = USB_ERR_INVAL;
+
+ xfer->endpoint->refcount_alloc++;
+
+ if (xfer->endpoint->refcount_alloc == 0)
+ panic("usbd_transfer_setup(): Refcount wrapped to zero\n");
+ USB_BUS_UNLOCK(info->bus);
/*
* Whenever we set ppxfer[] then we
@@ -960,6 +968,10 @@
*/
ppxfer[n] = xfer;
}
+
+ /* check for error */
+ if (parm.err)
+ goto done;
}
if (buf || parm.err) {
@@ -1179,7 +1191,9 @@
* NOTE: default endpoint does not have an
* interface, even if endpoint->iface_index == 0
*/
- xfer->endpoint->refcount--;
+ USB_BUS_LOCK(info->bus);
+ xfer->endpoint->refcount_alloc--;
+ USB_BUS_UNLOCK(info->bus);
usb_callout_drain(&xfer->timeout_handle);
==== //depot/projects/usb/src/sys/dev/usb/usbdi.h#14 (text+ko) ====
@@ -130,13 +130,22 @@
struct usb_pipe_methods *methods; /* set by HC driver */
uint16_t isoc_next;
- uint16_t refcount;
uint8_t toggle_next:1; /* next data toggle value */
uint8_t is_stalled:1; /* set if endpoint is stalled */
uint8_t is_synced:1; /* set if we a synchronised */
uint8_t unused:5;
uint8_t iface_index; /* not used by "default endpoint" */
+
+ uint8_t refcount_alloc; /* allocation refcount */
+ uint8_t refcount_bw; /* bandwidth refcount */
+#define USB_EP_REF_MAX 0x3f
+
+ /* High-Speed resource allocation (valid if "refcount_bw" > 0) */
+
+ uint8_t usb_smask; /* USB start mask */
+ uint8_t usb_cmask; /* USB complete mask */
+ uint8_t usb_uframe; /* USB microframe */
};
/*
More information about the p4-projects
mailing list