From owner-p4-projects@FreeBSD.ORG Wed Aug 11 18:26:49 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 260871066E1C; Wed, 11 Aug 2010 18:26:39 +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 470291065C1A for ; Wed, 11 Aug 2010 18:26:38 +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 F0F4D8FC22 for ; Wed, 11 Aug 2010 18:26:36 +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 o7BIQae2084794 for ; Wed, 11 Aug 2010 18:26:36 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id o7BIQalk084786 for perforce@freebsd.org; Wed, 11 Aug 2010 18:26:36 GMT (envelope-from hselasky@FreeBSD.org) Date: Wed, 11 Aug 2010 18:26:36 GMT Message-Id: <201008111826.o7BIQalk084786@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 182250 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:49 -0000 http://p4web.freebsd.org/@@182250?ac=10 Change 182250 by hselasky@hselasky_laptop001 on 2010/08/11 16:14:50 USB controller (XHCI): - fix problem with single short and multi short multi frame USB transfers. - increase maximum TD data-length to 64Kbyte. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#28 edit .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#22 edit .. //depot/projects/usb/src/sys/dev/usb/usb_transfer.h#18 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#28 (text+ko) ==== @@ -115,6 +115,7 @@ uint8_t direction; uint8_t tbc; uint8_t tlbpc; + uint8_t step_td; }; static void xhci_do_poll(struct usb_bus *); @@ -127,6 +128,7 @@ static usb_error_t xhci_configure_endpoint(struct usb_device *, struct usb_endpoint_descriptor *, uint64_t, uint16_t, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t); static usb_error_t xhci_configure_mask(struct usb_device *, uint32_t, uint8_t); static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *, uint64_t, uint8_t); +static void xhci_endpoint_doorbell(struct usb_xfer *); extern struct usb_bus_methods xhci_bus_methods; @@ -632,6 +634,56 @@ xhci_device_done(xfer, err); } +static void +xhci_activate_transfer(struct usb_xfer *xfer) +{ + struct xhci_td *td; + + td = xfer->td_transfer_cache; + + usb_pc_cpu_invalidate(td->page_cache); + + if (!(td->td_trb[0].dwTrb3 & htole32(XHCI_TRB_3_CYCLE_BIT))) { + + /* activate the transfer */ + + td->td_trb[0].dwTrb3 |= htole32(XHCI_TRB_3_CYCLE_BIT); + usb_pc_cpu_flush(td->page_cache); + + xhci_endpoint_doorbell(xfer); + } +} + +static void +xhci_skip_transfer(struct usb_xfer *xfer) +{ + struct xhci_td *td; + struct xhci_td *td_last; + + td = xfer->td_transfer_cache; + td_last = xfer->td_transfer_last; + + td = td->alt_next; + + usb_pc_cpu_invalidate(td->page_cache); + + if (!(td->td_trb[0].dwTrb3 & htole32(XHCI_TRB_3_CYCLE_BIT))) { + + usb_pc_cpu_invalidate(td_last->page_cache); + + /* copy LINK TRB to current waiting location */ + + td->td_trb[0].qwTrb0 = td_last->td_trb[td_last->ntrb].qwTrb0; + td->td_trb[0].dwTrb2 = td_last->td_trb[td_last->ntrb].dwTrb2; + usb_pc_cpu_flush(td->page_cache); + + td->td_trb[0].dwTrb3 = td_last->td_trb[td_last->ntrb].dwTrb3; + usb_pc_cpu_flush(td->page_cache); + + xhci_endpoint_doorbell(xfer); + } +} + /*------------------------------------------------------------------------* * xhci_check_transfer *------------------------------------------------------------------------*/ @@ -764,12 +816,12 @@ if (xfer->flags_int.short_frames_ok || xfer->flags_int.isochronous_xfr || xfer->flags_int.control_xfr) { - /* try to follow follow alt next */ - if (td->alt_next != NULL) { - xfer->td_transfer_cache = td->alt_next; - break; - } + /* follow the alt next */ + xfer->td_transfer_cache = td->alt_next; + xhci_activate_transfer(xfer); + break; } + xhci_skip_transfer(xfer); xhci_generic_done(xfer); break; } @@ -779,6 +831,7 @@ */ DPRINTF("Following next TD\n"); xfer->td_transfer_cache = td->obj_next; + xhci_activate_transfer(xfer); break; /* there should only be one match */ } } @@ -1553,7 +1606,6 @@ * can be sent using the wrong data * toggle value. */ - if ((temp->trb_type != XHCI_TRB_TYPE_SETUP_STAGE) && (temp->trb_type != XHCI_TRB_TYPE_STATUS_STAGE)) dword |= XHCI_TRB_3_ISP_BIT; @@ -1594,8 +1646,7 @@ td->td_trb[x].dwTrb2 = htole32(dword); dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) | - XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT | - XHCI_TRB_3_IOC_BIT; + XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT; td->td_trb[x].dwTrb3 = htole32(dword); @@ -1623,14 +1674,16 @@ goto restart; } - if (temp->multishort != 0) { - /* remove chain bit and clear TD SIZE - end of frame */ - td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15)); - td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT); - td->td_trb[td->ntrb].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15)); - td->td_trb[td->ntrb].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT); - usb_pc_cpu_flush(td->page_cache); - } + /* remove cycle bit from first if we are stepping the TRBs */ + if (temp->step_td) + td->td_trb[0].dwTrb3 &= ~htole32(XHCI_TRB_3_CYCLE_BIT); + + /* remove chain bit because this is the last TRB in the chain */ + td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15)); + td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT); + + usb_pc_cpu_flush(td->page_cache); + temp->td = td; temp->td_next = td_next; } @@ -1644,6 +1697,7 @@ uint32_t y; uint8_t mult; + temp.step_td = 0; temp.tbc = 0; temp.tlbpc = 0; temp.average = xfer->max_hc_frame_size; @@ -1783,6 +1837,8 @@ /* DATA0 / DATA1 message */ temp.len = xfer->frlengths[x]; + temp.step_td = ((xfer->endpointno & UE_DIR_IN) && + (x != 0) && (temp.multishort == 0)); x++; @@ -1855,6 +1911,7 @@ * Send a DATA1 message and invert the current * endpoint direction. */ + temp.step_td = (xfer->nframes != 0); temp.direction = UE_GET_DIR(xfer->endpointno) ^ UE_DIR_IN; temp.len = 0; temp.pc = NULL; @@ -1867,14 +1924,6 @@ td = temp.td; - /* remove chain bit and clear TD SIZE - end of frame */ - td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15)); - td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT); - td->td_trb[td->ntrb].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15)); - td->td_trb[td->ntrb].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT); - - usb_pc_cpu_flush(td->page_cache); - /* must have at least one frame! */ xfer->td_transfer_last = td; ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#22 (text+ko) ==== @@ -305,7 +305,7 @@ struct xhci_trb trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS]; }; -#define XHCI_TD_PAGE_NBUF 13 /* units */ +#define XHCI_TD_PAGE_NBUF 17 /* units, room enough for 64Kbytes */ #define XHCI_TD_PAGE_SIZE 4096 /* bytes */ #define XHCI_TD_PAYLOAD_MAX (XHCI_TD_PAGE_SIZE * (XHCI_TD_PAGE_NBUF - 1)) ==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.h#18 (text+ko) ==== @@ -101,7 +101,7 @@ usb_frlength_t bufsize; usb_frlength_t bufsize_max; - uint16_t hc_max_frame_size; + uint32_t hc_max_frame_size; uint16_t hc_max_packet_size; uint8_t hc_max_packet_count; enum usb_dev_speed speed;