Date: Tue, 10 Nov 2009 21:44:36 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 170449 for review Message-ID: <200911102144.nAALiaG4045048@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=170449 Change 170449 by hselasky@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 */ }; /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911102144.nAALiaG4045048>