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 322031066E23; Wed, 11 Aug 2010 18:26:40 +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 63F3F106625C for ; Wed, 11 Aug 2010 18:26:39 +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 364288FC24 for ; Wed, 11 Aug 2010 18:26:37 +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 o7BIQba2084806 for ; Wed, 11 Aug 2010 18:26:37 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id o7BIQa1d084798 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.o7BIQa1d084798@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 182251 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/@@182251?ac=10 Change 182251 by hselasky@hselasky_laptop001 on 2010/08/11 16:20:07 USB controller (EHCI): - revert most of r197682 (EHCI Hardware BUG workaround). Implement proper solution which is to not use the TERMINATE pointer, but rather link to a halted TD. The initial fix was due to a misunderstanding about how the EHCI hardware works. Thanks to Alan Stern for clearing this up during a recent e-mail discussion. - this patch can increase mass storage read performance significantly. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/controller/ehci.c#58 edit .. //depot/projects/usb/src/sys/dev/usb/controller/ehci.h#18 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/controller/ehci.c#58 (text+ko) ==== @@ -145,7 +145,6 @@ uint8_t auto_data_toggle; uint8_t setup_alt_next; uint8_t last_frame; - uint8_t can_use_next; }; void @@ -157,6 +156,9 @@ cb(bus, &sc->sc_hw.pframes_pc, &sc->sc_hw.pframes_pg, sizeof(uint32_t) * EHCI_FRAMELIST_COUNT, EHCI_FRAMELIST_ALIGN); + cb(bus, &sc->sc_hw.terminate_pc, &sc->sc_hw.terminate_pg, + sizeof(struct ehci_qh_sub), EHCI_QH_ALIGN); + cb(bus, &sc->sc_hw.async_start_pc, &sc->sc_hw.async_start_pg, sizeof(ehci_qh_t), EHCI_QH_ALIGN); @@ -310,6 +312,24 @@ sc->sc_eintrs = EHCI_NORMAL_INTRS; + if (1) { + struct ehci_qh_sub *qh; + + usbd_get_page(&sc->sc_hw.terminate_pc, 0, &buf_res); + + qh = buf_res.buffer; + + sc->sc_terminate_self = htohc32(sc, buf_res.physaddr); + + /* init terminate TD */ + qh->qtd_next = + htohc32(sc, EHCI_LINK_TERMINATE); + qh->qtd_altnext = + htohc32(sc, EHCI_LINK_TERMINATE); + qh->qtd_status = + htohc32(sc, EHCI_QTD_HALTED); + } + for (i = 0; i < EHCI_VIRTUAL_FRAMELIST_COUNT; i++) { ehci_qh_t *qh; @@ -1416,15 +1436,7 @@ */ if (status & EHCI_QTD_ACTIVE) { /* update cache */ - if (xfer->td_transfer_cache != td) { - xfer->td_transfer_cache = td; - if (qh->qh_qtd.qtd_next & - htohc32(sc, EHCI_LINK_TERMINATE)) { - /* XXX - manually advance to next frame */ - qh->qh_qtd.qtd_next = td->qtd_self; - usb_pc_cpu_flush(td->page_cache); - } - } + xfer->td_transfer_cache = td; goto done; } /* @@ -1634,10 +1646,12 @@ uint32_t average; uint32_t len_old; uint32_t terminate; + uint32_t qtd_altnext; uint8_t shortpkt_old; uint8_t precompute; - terminate = htohc32(temp->sc, EHCI_LINK_TERMINATE); + terminate = temp->sc->sc_terminate_self; + qtd_altnext = temp->sc->sc_terminate_self; td_alt_next = NULL; buf_offset = 0; shortpkt_old = temp->shortpkt; @@ -1771,23 +1785,11 @@ td->qtd_buffer_hi[x] = 0; } - if (temp->can_use_next) { - if (td_next) { - /* link the current TD with the next one */ - td->qtd_next = td_next->qtd_self; - } - } else { - /* - * BUG WARNING: The EHCI HW can use the - * qtd_next field instead of qtd_altnext when - * a short packet is received! We work this - * around in software by not queueing more - * than one job/TD at a time! - */ - td->qtd_next = terminate; + if (td_next) { + /* link the current TD with the next one */ + td->qtd_next = td_next->qtd_self; } - - td->qtd_altnext = terminate; + td->qtd_altnext = qtd_altnext; td->alt_next = td_alt_next; usb_pc_cpu_flush(td->page_cache); @@ -1799,9 +1801,15 @@ /* setup alt next pointer, if any */ if (temp->last_frame) { td_alt_next = NULL; + qtd_altnext = terminate; } else { /* we use this field internally */ td_alt_next = td_next; + if (temp->setup_alt_next) { + qtd_altnext = td_next->qtd_self; + } else { + qtd_altnext = terminate; + } } /* restore */ @@ -1846,8 +1854,6 @@ temp.qtd_status = 0; temp.last_frame = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; - temp.can_use_next = (xfer->flags_int.control_xfr || - (UE_GET_DIR(xfer->endpointno) == UE_DIR_OUT)); if (xfer->flags_int.control_xfr) { if (xfer->endpoint->toggle_next) { ==== //depot/projects/usb/src/sys/dev/usb/controller/ehci.h#18 (text+ko) ==== @@ -285,12 +285,14 @@ struct ehci_hw_softc { struct usb_page_cache pframes_pc; + struct usb_page_cache terminate_pc; struct usb_page_cache async_start_pc; struct usb_page_cache intr_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT]; struct usb_page_cache isoc_hs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT]; struct usb_page_cache isoc_fs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT]; struct usb_page pframes_pg; + struct usb_page terminate_pg; struct usb_page async_start_pg; struct usb_page intr_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT]; struct usb_page isoc_hs_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT]; @@ -329,6 +331,7 @@ bus_space_tag_t sc_io_tag; bus_space_handle_t sc_io_hdl; + uint32_t sc_terminate_self; /* TD short packet termination pointer */ uint32_t sc_eintrs; uint32_t sc_cmd; /* shadow of cmd register during * suspend */