PERFORCE change 170449 for review

View: New views
1 Messages — Rating Filter:   Alert me  

PERFORCE change 170449 for review

by Hans Petter Selasky-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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 */
 };
 
 /*
_______________________________________________
p4-projects@... mailing list
http://lists.freebsd.org/mailman/listinfo/p4-projects
To unsubscribe, send any mail to "p4-projects-unsubscribe@..."