From owner-p4-projects@FreeBSD.ORG Wed Aug 11 18:26:18 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 4EBA01066615; Wed, 11 Aug 2010 18:26:18 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8A7DE106654D for ; Wed, 11 Aug 2010 18:26:17 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id 7681A8FC24 for ; Wed, 11 Aug 2010 18:26:16 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id o7BIQGA8084399 for ; Wed, 11 Aug 2010 18:26:16 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id o7BIQGoN084396 for perforce@freebsd.org; Wed, 11 Aug 2010 18:26:16 GMT (envelope-from hselasky@FreeBSD.org) Date: Wed, 11 Aug 2010 18:26:16 GMT Message-Id: <201008111826.o7BIQGoN084396@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 182197 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 Aug 2010 18:26:18 -0000 http://p4web.freebsd.org/@@182197?ac=10 Change 182197 by hselasky@hselasky_laptop001 on 2010/08/10 16:19:57 USB controller (XHCI): - correctly compute multiplier and burst bits for isoc. transfers. - isochronous transfers should not fail on data errors and always report success to the client unless there is a complete stop in the isochronous schedule. - use timeout error code instead of I/O error code due to the way applications handle this kind of error. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#25 edit .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#21 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#25 (text+ko) ==== @@ -113,6 +113,8 @@ uint8_t last_frame; uint8_t trb_type; uint8_t direction; + uint8_t tbc; + uint8_t tlbpc; }; static void xhci_do_poll(struct usb_bus *); @@ -722,6 +724,7 @@ if (xfer->flags_int.isochronous_xfr) { if (halted) { halted = 0; + status = XHCI_TRB_ERROR_SUCCESS; remainder = td->len; } } @@ -1537,7 +1540,9 @@ 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); + XHCI_TRB_3_FRID_SET(temp->isoc_frame) | + XHCI_TRB_3_TBC_SET(temp->tbc) | + XHCI_TRB_3_TLBPC_SET(temp->tlbpc); if (temp->direction == UE_DIR_IN) { dword |= XHCI_TRB_3_DIR_IN; @@ -1637,7 +1642,10 @@ struct xhci_td *td; uint32_t x; uint32_t y; + uint8_t mult; + temp.tbc = 0; + temp.tlbpc = 0; temp.average = xfer->max_hc_frame_size; temp.max_packet_size = xfer->max_packet_size; temp.sc = XHCI_BUS2SC(xfer->xroot->bus); @@ -1663,6 +1671,20 @@ if (xfer->flags_int.isochronous_xfr) { uint8_t shift; + /* compute multiplier for ISOCHRONOUS transfers */ + mult = xfer->endpoint->ecomp ? + (xfer->endpoint->ecomp->bmAttributes & 3) : 0; + /* check for USB 2.0 multiplier */ + if (mult == 0) { + mult = (xfer->endpoint->edesc-> + wMaxPacketSize[1] >> 3) & 3; + } + /* range check */ + if (mult > 2) + mult = 3; + else + mult++; + x = XREAD4(temp.sc, runt, XHCI_MFINDEX); DPRINTF("MFINDEX=0x%08x\n", x); @@ -1737,11 +1759,13 @@ xhci_setup_generic_chain_sub(&temp); } x = 1; + mult = 1; temp.isoc_delta = 0; temp.isoc_frame = 0; temp.trb_type = XHCI_TRB_TYPE_DATA_STAGE; } else { x = 0; + mult = 1; temp.isoc_delta = 0; temp.isoc_frame = 0; temp.trb_type = XHCI_TRB_TYPE_NORMAL; @@ -1777,8 +1801,13 @@ temp.shortpkt = 0; + temp.tbc = 0; + temp.tlbpc = mult - 1; + } else if (xfer->flags_int.isochronous_xfr) { + uint8_t tdpc; + /* isochronous transfers don't have short packet termination */ temp.shortpkt = 1; @@ -1787,6 +1816,18 @@ if (temp.len > xfer->max_frame_size) temp.len = xfer->max_frame_size; + + /* compute TD packet count */ + tdpc = (temp.len + xfer->max_packet_size - 1) / + xfer->max_packet_size; + + temp.tbc = ((tdpc + mult - 1) / mult) - 1; + temp.tlbpc = (tdpc % mult); + + if (temp.tlbpc == 0) + temp.tlbpc = mult - 1; + else + temp.tlbpc--; } else { /* regular data transfer */ @@ -2000,14 +2041,14 @@ switch (edesc->bmAttributes & UE_XFERTYPE) { case UE_INTERRUPT: case UE_ISOCHRONOUS: - temp = XHCI_EPCTX_4_MAX_ESIT_PAYLOAD_SET(max_frame_size); - temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET(XHCI_TD_PAYLOAD_MAX); + temp = XHCI_EPCTX_4_MAX_ESIT_PAYLOAD_SET(max_frame_size) | + XHCI_EPCTX_4_AVG_TRB_LEN_SET(XHCI_PAGE_SIZE); break; case UE_CONTROL: temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET(8); break; default: - temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET(XHCI_TD_PAYLOAD_MAX); + temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET(XHCI_PAGE_SIZE); break; } @@ -3395,11 +3436,22 @@ /* nuke remaining buffered transfers */ for (i = 0; i != (XHCI_MAX_TRANSFERS - 1); i++) { - if (pepext->xfer[i] != NULL) - xhci_device_done(pepext->xfer[i], USB_ERR_IOERROR); + /* + * NOTE: We need to use the timeout + * error code here else existing + * isochronous clients can get + * confused: + */ + if (pepext->xfer[i] != NULL) { + xhci_device_done(pepext->xfer[i], + USB_ERR_TIMEOUT); + } } - /* NOTE: The USB transfer cannot vanish in this state! */ + /* + * NOTE: The USB transfer cannot vanish in + * this state! + */ USB_BUS_UNLOCK(&sc->sc_bus); ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#21 (text+ko) ==== @@ -205,6 +205,8 @@ #define XHCI_TRB_3_CHAIN_BIT (1U << 4) #define XHCI_TRB_3_IOC_BIT (1U << 5) #define XHCI_TRB_3_IDT_BIT (1U << 6) +#define XHCI_TRB_3_TBC_GET(x) (((x) >> 7) & 3) +#define XHCI_TRB_3_TBC_SET(x) (((x) & 3) << 7) #define XHCI_TRB_3_BEI_BIT (1U << 9) #define XHCI_TRB_3_DCEP_BIT (1U << 9) #define XHCI_TRB_3_PRSV_BIT (1U << 9)