Author: hselasky
Date: Fri May  4 15:10:49 2012
New Revision: 235001
URL: http://svn.freebsd.org/changeset/base/235001

Log:
  MFC r234803 and r234961:
  Add support for Multi-TT mode of modern USB HUBs.
  This will give you more bandwidth for isochronous
  FULL speed applications connected through a
  High Speed HUB.
  
  This patch has been tested with XHCI and EHCI.

Modified:
  stable/9/sys/dev/usb/controller/ehci.c
  stable/9/sys/dev/usb/controller/xhci.c
  stable/9/sys/dev/usb/usb_controller.h
  stable/9/sys/dev/usb/usb_hub.c
  stable/9/sys/dev/usb/usb_hub.h
  stable/9/sys/dev/usb/usb_transfer.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/dev/usb/controller/ehci.c
==============================================================================
--- stable/9/sys/dev/usb/controller/ehci.c      Fri May  4 15:05:30 2012        
(r235000)
+++ stable/9/sys/dev/usb/controller/ehci.c      Fri May  4 15:10:49 2012        
(r235001)
@@ -2398,9 +2398,9 @@ ehci_device_isoc_fs_open(struct usb_xfer
            EHCI_SITD_SET_HUBA(xfer->xroot->udev->hs_hub_addr) |
            EHCI_SITD_SET_PORT(xfer->xroot->udev->hs_port_no);
 
-       if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN) {
+       if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN)
                sitd_portaddr |= EHCI_SITD_SET_DIR_IN;
-       }
+
        sitd_portaddr = htohc32(sc, sitd_portaddr);
 
        /* initialize all TD's */
@@ -2436,9 +2436,6 @@ ehci_device_isoc_fs_enter(struct usb_xfe
 {
        struct usb_page_search buf_res;
        ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-       struct usb_fs_isoc_schedule *fss_start;
-       struct usb_fs_isoc_schedule *fss_end;
-       struct usb_fs_isoc_schedule *fss;
        ehci_sitd_t *td;
        ehci_sitd_t *td_last = NULL;
        ehci_sitd_t **pp_last;
@@ -2450,7 +2447,6 @@ ehci_device_isoc_fs_enter(struct usb_xfe
        uint16_t tlen;
        uint8_t sa;
        uint8_t sb;
-       uint8_t error;
 
 #ifdef USB_DEBUG
        uint8_t once = 1;
@@ -2495,9 +2491,8 @@ ehci_device_isoc_fs_enter(struct usb_xfe
         * pre-compute when the isochronous transfer will be finished:
         */
        xfer->isoc_time_complete =
-           usbd_fs_isoc_schedule_isoc_time_expand
-           (xfer->xroot->udev, &fss_start, &fss_end, nframes) + buf_offset +
-           xfer->nframes;
+           usb_isoc_time_expand(&sc->sc_bus, nframes) +
+           buf_offset + xfer->nframes;
 
        /* get the real number of frames */
 
@@ -2520,19 +2515,14 @@ ehci_device_isoc_fs_enter(struct usb_xfe
 
        xfer->qh_pos = xfer->endpoint->isoc_next;
 
-       fss = fss_start + (xfer->qh_pos % USB_ISOC_TIME_MAX);
-
        while (nframes--) {
                if (td == NULL) {
                        panic("%s:%d: out of TD's\n",
                            __FUNCTION__, __LINE__);
                }
-               if (pp_last >= 
&sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]) {
+               if (pp_last >= 
&sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT])
                        pp_last = &sc->sc_isoc_fs_p_last[0];
-               }
-               if (fss >= fss_end) {
-                       fss = fss_start;
-               }
+
                /* reuse sitd_portaddr and sitd_back from last transfer */
 
                if (*plen > xfer->max_frame_size) {
@@ -2547,17 +2537,19 @@ ehci_device_isoc_fs_enter(struct usb_xfe
 #endif
                        *plen = xfer->max_frame_size;
                }
-               /*
-                * We currently don't care if the ISOCHRONOUS schedule is
-                * full!
-                */
-               error = usbd_fs_isoc_schedule_alloc(fss, &sa, *plen);
-               if (error) {
+
+               /* allocate a slot */
+
+               sa = usbd_fs_isoc_schedule_alloc_slot(xfer,
+                   xfer->isoc_time_complete - nframes - 1);
+
+               if (sa == 255) {
                        /*
-                        * The FULL speed schedule is FULL! Set length
-                        * to zero.
+                        * Schedule is FULL, set length to zero:
                         */
+
                        *plen = 0;
+                       sa = USB_FS_ISOC_UFRAME_MAX - 1;
                }
                if (*plen) {
                        /*
@@ -2637,7 +2629,6 @@ ehci_device_isoc_fs_enter(struct usb_xfe
                pp_last++;
 
                plen++;
-               fss++;
                td_last = td;
                td = td->obj_next;
        }
@@ -2647,11 +2638,29 @@ ehci_device_isoc_fs_enter(struct usb_xfe
        /* update isoc_next */
        xfer->endpoint->isoc_next = (pp_last - &sc->sc_isoc_fs_p_last[0]) &
            (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
+
+       /*
+        * We don't allow cancelling of the SPLIT transaction USB FULL
+        * speed transfer, because it disturbs the bandwidth
+        * computation algorithm.
+        */
+       xfer->flags_int.can_cancel_immed = 0;
 }
 
 static void
 ehci_device_isoc_fs_start(struct usb_xfer *xfer)
 {
+       /*
+        * We don't allow cancelling of the SPLIT transaction USB FULL
+        * speed transfer, because it disturbs the bandwidth
+        * computation algorithm.
+        */
+       xfer->flags_int.can_cancel_immed = 0;
+
+       /* set a default timeout */
+       if (xfer->timeout == 0)
+               xfer->timeout = 500; /* ms */
+
        /* put transfer on interrupt queue */
        ehci_transfer_intr_enqueue(xfer);
 }

Modified: stable/9/sys/dev/usb/controller/xhci.c
==============================================================================
--- stable/9/sys/dev/usb/controller/xhci.c      Fri May  4 15:05:30 2012        
(r235000)
+++ stable/9/sys/dev/usb/controller/xhci.c      Fri May  4 15:10:49 2012        
(r235001)
@@ -115,6 +115,7 @@ struct xhci_std_temp {
        uint8_t                 tbc;
        uint8_t                 tlbpc;
        uint8_t                 step_td;
+       uint8_t                 do_isoc_sync;
 };
 
 static void    xhci_do_poll(struct usb_bus *);
@@ -1657,11 +1658,15 @@ restart:
                        td->td_trb[x].dwTrb2 = htole32(dword);
 
                        dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
-                         XHCI_TRB_3_TYPE_SET(temp->trb_type) | 
-                         XHCI_TRB_3_FRID_SET(temp->isoc_frame / 8) | 
+                         XHCI_TRB_3_TYPE_SET(temp->trb_type) |
+                         (temp->do_isoc_sync ?
+                          XHCI_TRB_3_FRID_SET(temp->isoc_frame / 8) :
+                          XHCI_TRB_3_ISO_SIA_BIT) |
                          XHCI_TRB_3_TBC_SET(temp->tbc) |
                          XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
 
+                       temp->do_isoc_sync = 0;
+
                        if (temp->direction == UE_DIR_IN) {
                                dword |= XHCI_TRB_3_DIR_IN;
 
@@ -1764,6 +1769,7 @@ xhci_setup_generic_chain(struct usb_xfer
        uint32_t y;
        uint8_t mult;
 
+       temp.do_isoc_sync = 0;
        temp.step_td = 0;
        temp.tbc = 0;
        temp.tlbpc = 0;
@@ -1841,6 +1847,8 @@ xhci_setup_generic_chain(struct usb_xfer
                         */
                        xfer->endpoint->isoc_next = XHCI_MFINDEX_GET(x + (3 * 
8));
                        xfer->endpoint->is_synced = 1;
+                       temp.do_isoc_sync = 1;
+
                        DPRINTFN(3, "start next=%d\n", 
xfer->endpoint->isoc_next);
                }
 
@@ -1931,7 +1939,10 @@ xhci_setup_generic_chain(struct usb_xfer
 
                        uint8_t tdpc;
 
-                       /* isochronous transfers don't have short packet 
termination */
+                       /*
+                        * Isochronous transfers don't have short
+                        * packet termination:
+                        */
 
                        temp.shortpkt = 1;
 
@@ -2271,12 +2282,29 @@ xhci_configure_device(struct usb_device 
        switch (udev->speed) {
        case USB_SPEED_LOW:
                temp |= XHCI_SCTX_0_SPEED_SET(2);
+               if (udev->parent_hs_hub != NULL &&
+                   udev->parent_hs_hub->ddesc.bDeviceProtocol ==
+                   UDPROTO_HSHUBMTT) {
+                       DPRINTF("Device inherits MTT\n");
+                       temp |= XHCI_SCTX_0_MTT_SET(1);
+               }
                break;
        case USB_SPEED_HIGH:
                temp |= XHCI_SCTX_0_SPEED_SET(3);
+               if (sc->sc_hw.devs[index].nports != 0 &&
+                   udev->ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT) {
+                       DPRINTF("HUB supports MTT\n");
+                       temp |= XHCI_SCTX_0_MTT_SET(1);
+               }
                break;
        case USB_SPEED_FULL:
                temp |= XHCI_SCTX_0_SPEED_SET(1);
+               if (udev->parent_hs_hub != NULL &&
+                   udev->parent_hs_hub->ddesc.bDeviceProtocol ==
+                   UDPROTO_HSHUBMTT) {
+                       DPRINTF("Device inherits MTT\n");
+                       temp |= XHCI_SCTX_0_MTT_SET(1);
+               }
                break;
        default:
                temp |= XHCI_SCTX_0_SPEED_SET(4);
@@ -2287,15 +2315,8 @@ xhci_configure_device(struct usb_device 
            (udev->speed == USB_SPEED_SUPER ||
            udev->speed == USB_SPEED_HIGH);
 
-       if (is_hub) {
+       if (is_hub)
                temp |= XHCI_SCTX_0_HUB_SET(1);
-#if 0
-               if (udev->ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT) {
-                       DPRINTF("HUB supports MTT\n");
-                       temp |= XHCI_SCTX_0_MTT_SET(1);
-               }
-#endif
-       }
 
        xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
 
@@ -2327,8 +2348,10 @@ xhci_configure_device(struct usb_device 
 
        temp = XHCI_SCTX_2_IRQ_TARGET_SET(0);
 
-       if (is_hub)
-               temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(sc->sc_hw.devs[index].tt);
+       if (is_hub) {
+               temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(
+                   sc->sc_hw.devs[index].tt);
+       }
 
        hubdev = udev->parent_hs_hub;
 

Modified: stable/9/sys/dev/usb/usb_controller.h
==============================================================================
--- stable/9/sys/dev/usb/usb_controller.h       Fri May  4 15:05:30 2012        
(r235000)
+++ stable/9/sys/dev/usb/usb_controller.h       Fri May  4 15:10:49 2012        
(r235001)
@@ -231,7 +231,8 @@ void        usb_bus_mem_flush_all(struct usb_bu
 uint8_t        usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat, 
usb_bus_mem_cb_t *cb);
 void   usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
 uint16_t usb_isoc_time_expand(struct usb_bus *bus, uint16_t isoc_time_curr);
-uint16_t usbd_fs_isoc_schedule_isoc_time_expand(struct usb_device *udev, 
struct usb_fs_isoc_schedule **pp_start, struct usb_fs_isoc_schedule **pp_end, 
uint16_t isoc_time);
-uint8_t        usbd_fs_isoc_schedule_alloc(struct usb_fs_isoc_schedule *fss, 
uint8_t *pstart, uint16_t len);
+#if USB_HAVE_TT_SUPPORT
+uint8_t        usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, 
uint16_t isoc_time);
+#endif
 
 #endif                                 /* _USB_CONTROLLER_H_ */

Modified: stable/9/sys/dev/usb/usb_hub.c
==============================================================================
--- stable/9/sys/dev/usb/usb_hub.c      Fri May  4 15:05:30 2012        
(r235000)
+++ stable/9/sys/dev/usb/usb_hub.c      Fri May  4 15:10:49 2012        
(r235001)
@@ -109,6 +109,7 @@ struct uhub_softc {
 #define        UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol)
 #define        UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB)
 #define        UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT)
+#define        UHUB_IS_MULTI_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBMTT)
 #define        UHUB_IS_SUPER_SPEED(sc) (UHUB_PROTO(sc) == UDPROTO_SSHUB)
 
 /* prototypes for type checking: */
@@ -948,6 +949,16 @@ uhub_attach(device_t dev)
                    "bus powered HUB. HUB ignored\n");
                goto error;
        }
+
+       if (UHUB_IS_MULTI_TT(sc)) {
+               err = usbd_set_alt_interface_index(udev, 0, 1);
+               if (err) {
+                       device_printf(dev, "MTT could not be enabled\n");
+                       goto error;
+               }
+               device_printf(dev, "MTT enabled\n");
+       }
+
        /* get HUB descriptor */
 
        DPRINTFN(2, "Getting HUB descriptor\n");
@@ -1057,10 +1068,6 @@ uhub_attach(device_t dev)
        }
        udev->hub = hub;
 
-#if USB_HAVE_TT_SUPPORT
-       /* init FULL-speed ISOCHRONOUS schedule */
-       usbd_fs_isoc_schedule_init_all(hub->fs_isoc_schedule);
-#endif
        /* initialize HUB structure */
        hub->hubsoftc = sc;
        hub->explore = &uhub_explore;
@@ -1656,42 +1663,6 @@ usb_hs_bandwidth_free(struct usb_xfer *x
 }
 
 /*------------------------------------------------------------------------*
- *     usbd_fs_isoc_schedule_init_sub
- *
- * This function initialises an USB FULL speed isochronous schedule
- * entry.
- *------------------------------------------------------------------------*/
-#if USB_HAVE_TT_SUPPORT
-static void
-usbd_fs_isoc_schedule_init_sub(struct usb_fs_isoc_schedule *fss)
-{
-       fss->total_bytes = (USB_FS_ISOC_UFRAME_MAX *
-           USB_FS_BYTES_PER_HS_UFRAME);
-       fss->frame_bytes = (USB_FS_BYTES_PER_HS_UFRAME);
-       fss->frame_slot = 0;
-}
-#endif
-
-/*------------------------------------------------------------------------*
- *     usbd_fs_isoc_schedule_init_all
- *
- * This function will reset the complete USB FULL speed isochronous
- * bandwidth schedule.
- *------------------------------------------------------------------------*/
-#if USB_HAVE_TT_SUPPORT
-void
-usbd_fs_isoc_schedule_init_all(struct usb_fs_isoc_schedule *fss)
-{
-       struct usb_fs_isoc_schedule *fss_end = fss + USB_ISOC_TIME_MAX;
-
-       while (fss != fss_end) {
-               usbd_fs_isoc_schedule_init_sub(fss);
-               fss++;
-       }
-}
-#endif
-
-/*------------------------------------------------------------------------*
  *     usb_isoc_time_expand
  *
  * This function will expand the time counter from 7-bit to 16-bit.
@@ -1723,114 +1694,130 @@ usb_isoc_time_expand(struct usb_bus *bus
 }
 
 /*------------------------------------------------------------------------*
- *     usbd_fs_isoc_schedule_isoc_time_expand
+ *     usbd_fs_isoc_schedule_alloc_slot
  *
- * This function does multiple things. First of all it will expand the
- * passed isochronous time, which is the return value. Then it will
- * store where the current FULL speed isochronous schedule is
- * positioned in time and where the end is. See "pp_start" and
- * "pp_end" arguments.
+ * This function will allocate bandwidth for an isochronous FULL speed
+ * transaction in the FULL speed schedule.
  *
  * Returns:
- *   Expanded version of "isoc_time".
- *
- * NOTE: This function depends on being called regularly with
- * intervals less than "USB_ISOC_TIME_MAX".
+ *    <8: Success
+ * Else: Error
  *------------------------------------------------------------------------*/
 #if USB_HAVE_TT_SUPPORT
-uint16_t
-usbd_fs_isoc_schedule_isoc_time_expand(struct usb_device *udev,
-    struct usb_fs_isoc_schedule **pp_start,
-    struct usb_fs_isoc_schedule **pp_end,
-    uint16_t isoc_time)
+uint8_t
+usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, uint16_t 
isoc_time)
 {
-       struct usb_fs_isoc_schedule *fss_end;
-       struct usb_fs_isoc_schedule *fss_a;
-       struct usb_fs_isoc_schedule *fss_b;
-       struct usb_hub *hs_hub;
+       struct usb_xfer *xfer;
+       struct usb_xfer *pipe_xfer;
+       struct usb_bus *bus;
+       usb_frlength_t len;
+       usb_frlength_t data_len;
+       uint16_t delta;
+       uint16_t slot;
+       uint8_t retval;
 
-       isoc_time = usb_isoc_time_expand(udev->bus, isoc_time);
+       data_len = 0;
+       slot = 0;
 
-       hs_hub = udev->parent_hs_hub->hub;
+       bus = isoc_xfer->xroot->bus;
 
-       if (hs_hub != NULL) {
+       TAILQ_FOREACH(xfer, &bus->intr_q.head, wait_entry) {
 
-               fss_a = hs_hub->fs_isoc_schedule +
-                   (hs_hub->isoc_last_time % USB_ISOC_TIME_MAX);
+               /* skip self, if any */
 
-               hs_hub->isoc_last_time = isoc_time;
+               if (xfer == isoc_xfer)
+                       continue;
 
-               fss_b = hs_hub->fs_isoc_schedule +
-                   (isoc_time % USB_ISOC_TIME_MAX);
+               /* check if this USB transfer is going through the same TT */
 
-               fss_end = hs_hub->fs_isoc_schedule + USB_ISOC_TIME_MAX;
+               if (xfer->xroot->udev->parent_hs_hub !=
+                   isoc_xfer->xroot->udev->parent_hs_hub) {
+                       continue;
+               }
+               if ((isoc_xfer->xroot->udev->parent_hs_hub->
+                   ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT) &&
+                   (xfer->xroot->udev->hs_port_no !=
+                   isoc_xfer->xroot->udev->hs_port_no)) {
+                       continue;
+               }
+               if (xfer->endpoint->methods != isoc_xfer->endpoint->methods)
+                       continue;
+
+               /* check if isoc_time is part of this transfer */
+
+               delta = xfer->isoc_time_complete - isoc_time;
+               if (delta > 0 && delta <= xfer->nframes) {
+                       delta = xfer->nframes - delta;
+
+                       len = xfer->frlengths[delta];
+                       len += 8;
+                       len *= 7;
+                       len /= 6;
+
+                       data_len += len;
+               }
+
+               /* check double buffered transfers */
 
-               *pp_start = hs_hub->fs_isoc_schedule;
-               *pp_end = fss_end;
+               TAILQ_FOREACH(pipe_xfer, &xfer->endpoint->endpoint_q.head,
+                   wait_entry) {
 
-               while (fss_a != fss_b) {
-                       if (fss_a == fss_end) {
-                               fss_a = hs_hub->fs_isoc_schedule;
+                       /* skip self, if any */
+
+                       if (pipe_xfer == isoc_xfer)
                                continue;
+
+                       /* check if isoc_time is part of this transfer */
+
+                       delta = pipe_xfer->isoc_time_complete - isoc_time;
+                       if (delta > 0 && delta <= pipe_xfer->nframes) {
+                               delta = pipe_xfer->nframes - delta;
+
+                               len = pipe_xfer->frlengths[delta];
+                               len += 8;
+                               len *= 7;
+                               len /= 6;
+
+                               data_len += len;
                        }
-                       usbd_fs_isoc_schedule_init_sub(fss_a);
-                       fss_a++;
                }
+       }
 
-       } else {
-
-               *pp_start = NULL;
-               *pp_end = NULL;
+       while (data_len >= USB_FS_BYTES_PER_HS_UFRAME) {
+               data_len -= USB_FS_BYTES_PER_HS_UFRAME;
+               slot++;
        }
-       return (isoc_time);
-}
-#endif
 
-/*------------------------------------------------------------------------*
- *     usbd_fs_isoc_schedule_alloc
- *
- * This function will allocate bandwidth for an isochronous FULL speed
- * transaction in the FULL speed schedule. The microframe slot where
- * the transaction should be started is stored in the byte pointed to
- * by "pstart". The "len" argument specifies the length of the
- * transaction in bytes.
- *
- * Returns:
- *    0: Success
- * Else: Error
- *------------------------------------------------------------------------*/
-#if USB_HAVE_TT_SUPPORT
-uint8_t
-usbd_fs_isoc_schedule_alloc(struct usb_fs_isoc_schedule *fss,
-    uint8_t *pstart, uint16_t len)
-{
-       uint8_t slot = fss->frame_slot;
+       /* check for overflow */
 
-       /* Compute overhead and bit-stuffing */
+       if (slot >= USB_FS_ISOC_UFRAME_MAX)
+               return (255);
 
-       len += 8;
+       retval = slot;
 
-       len *= 7;
-       len /= 6;
+       delta = isoc_xfer->isoc_time_complete - isoc_time;
+       if (delta > 0 && delta <= isoc_xfer->nframes) {
+               delta = isoc_xfer->nframes - delta;
 
-       if (len > fss->total_bytes) {
-               *pstart = 0;            /* set some dummy value */
-               return (1);             /* error */
+               len = isoc_xfer->frlengths[delta];
+               len += 8;
+               len *= 7;
+               len /= 6;
+
+               data_len += len;
        }
-       if (len > 0) {
 
-               fss->total_bytes -= len;
+       while (data_len >= USB_FS_BYTES_PER_HS_UFRAME) {
+               data_len -= USB_FS_BYTES_PER_HS_UFRAME;
+               slot++;
+       }
 
-               while (len >= fss->frame_bytes) {
-                       len -= fss->frame_bytes;
-                       fss->frame_bytes = USB_FS_BYTES_PER_HS_UFRAME;
-                       fss->frame_slot++;
-               }
+       /* check for overflow */
 
-               fss->frame_bytes -= len;
-       }
-       *pstart = slot;
-       return (0);                     /* success */
+       if (slot >= USB_FS_ISOC_UFRAME_MAX)
+               return (255);
+
+       return (retval);
 }
 #endif
 

Modified: stable/9/sys/dev/usb/usb_hub.h
==============================================================================
--- stable/9/sys/dev/usb/usb_hub.h      Fri May  4 15:05:30 2012        
(r235000)
+++ stable/9/sys/dev/usb/usb_hub.h      Fri May  4 15:10:49 2012        
(r235001)
@@ -38,22 +38,9 @@ struct usb_port {
 };
 
 /*
- * The following structure defines how many bytes are
- * left in an 1ms USB time slot.
- */
-struct usb_fs_isoc_schedule {
-       uint16_t total_bytes;
-       uint8_t frame_bytes;
-       uint8_t frame_slot;
-};
-
-/*
  * The following structure defines an USB HUB.
  */
 struct usb_hub {
-#if USB_HAVE_TT_SUPPORT
-       struct usb_fs_isoc_schedule fs_isoc_schedule[USB_ISOC_TIME_MAX];
-#endif
        struct usb_device *hubudev;     /* the HUB device */
        usb_error_t (*explore) (struct usb_device *hub);
        void   *hubsoftc;
@@ -68,7 +55,6 @@ struct usb_hub {
 
 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);
 struct usb_device *usb_bus_port_get_device(struct usb_bus *bus,

Modified: stable/9/sys/dev/usb/usb_transfer.c
==============================================================================
--- stable/9/sys/dev/usb/usb_transfer.c Fri May  4 15:05:30 2012        
(r235000)
+++ stable/9/sys/dev/usb/usb_transfer.c Fri May  4 15:10:49 2012        
(r235001)
@@ -1680,11 +1680,12 @@ usbd_pipe_enter(struct usb_xfer *xfer)
 
        DPRINTF("enter\n");
 
+       /* the transfer can now be cancelled */
+       xfer->flags_int.can_cancel_immed = 1;
+
        /* enter the transfer */
        (ep->methods->enter) (xfer);
 
-       xfer->flags_int.can_cancel_immed = 1;
-
        /* check for transfer error */
        if (xfer->error) {
                /* some error has happened */
@@ -2417,13 +2418,15 @@ usbd_transfer_start_cb(void *arg)
 #if USB_HAVE_PF
        usbpf_xfertap(xfer, USBPF_XFERTAP_SUBMIT);
 #endif
+
+       /* the transfer can now be cancelled */
+       xfer->flags_int.can_cancel_immed = 1;
+
        /* start USB transfer, if no error */
        if (xfer->error == 0)
                (ep->methods->start) (xfer);
 
-       xfer->flags_int.can_cancel_immed = 1;
-
-       /* check for error */
+       /* check for transfer error */
        if (xfer->error) {
                /* some error has happened */
                usbd_transfer_done(xfer, 0);
@@ -2598,13 +2601,14 @@ usbd_pipe_start(struct usb_xfer_queue *p
 #if USB_HAVE_PF
        usbpf_xfertap(xfer, USBPF_XFERTAP_SUBMIT);
 #endif
+       /* the transfer can now be cancelled */
+       xfer->flags_int.can_cancel_immed = 1;
+
        /* start USB transfer, if no error */
        if (xfer->error == 0)
                (ep->methods->start) (xfer);
 
-       xfer->flags_int.can_cancel_immed = 1;
-
-       /* check for error */
+       /* check for transfer error */
        if (xfer->error) {
                /* some error has happened */
                usbd_transfer_done(xfer, 0);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to