From owner-svn-src-stable@FreeBSD.ORG Fri May 4 15:10:49 2012 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id C689A1065676; Fri, 4 May 2012 15:10:49 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id ADFD58FC16; Fri, 4 May 2012 15:10:49 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q44FAnHM008952; Fri, 4 May 2012 15:10:49 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q44FAnLF008945; Fri, 4 May 2012 15:10:49 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201205041510.q44FAnLF008945@svn.freebsd.org> From: Hans Petter Selasky Date: Fri, 4 May 2012 15:10:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r235001 - in stable/9/sys/dev/usb: . controller X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 May 2012 15:10:49 -0000 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);