From owner-svn-src-all@FreeBSD.ORG Sun May 11 08:17:46 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id D9273B87; Sun, 11 May 2014 08:17:46 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B97EF2DC1; Sun, 11 May 2014 08:17:46 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s4B8HkmX039824; Sun, 11 May 2014 08:17:46 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s4B8HkiV039822; Sun, 11 May 2014 08:17:46 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201405110817.s4B8HkiV039822@svn.freebsd.org> From: Hans Petter Selasky Date: Sun, 11 May 2014 08:17:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r265872 - head/sys/dev/usb/controller X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 11 May 2014 08:17:46 -0000 Author: hselasky Date: Sun May 11 08:17:46 2014 New Revision: 265872 URL: http://svnweb.freebsd.org/changeset/base/265872 Log: Optimise host mode data roundtrip time. When BULK data is submitted to the main processing queue, clear the NAK counter for any associated BULK or CONTROL transfers and poll the endpoint(s) for 1 millisecond at 125us rate interval, before going into slow, 10ms, NAK polling mode again. This has the effect that typical ping-ping protocols respond quicker when initiated from the USB host. MFC after: 2 weeks Modified: head/sys/dev/usb/controller/dwc_otg.c head/sys/dev/usb/controller/dwc_otg.h Modified: head/sys/dev/usb/controller/dwc_otg.c ============================================================================== --- head/sys/dev/usb/controller/dwc_otg.c Sun May 11 05:49:35 2014 (r265871) +++ head/sys/dev/usb/controller/dwc_otg.c Sun May 11 08:17:46 2014 (r265872) @@ -760,7 +760,7 @@ check_state: case DWC_CHAN_ST_WAIT_ANE: if (hcint & (HCINT_RETRY | HCINT_ERRORS)) { - td->did_nak = 1; + td->did_nak++; td->tt_scheduled = 0; goto send_pkt; } else if (hcint & (HCINT_ACK | HCINT_NYET)) { @@ -774,7 +774,7 @@ check_state: case DWC_CHAN_ST_WAIT_S_ANE: if (hcint & (HCINT_RETRY | HCINT_ERRORS)) { - td->did_nak = 1; + td->did_nak++; td->tt_scheduled = 0; goto send_pkt; } else if (hcint & (HCINT_ACK | HCINT_NYET)) { @@ -786,7 +786,7 @@ check_state: if (hcint & HCINT_NYET) { goto send_cpkt; } else if (hcint & (HCINT_RETRY | HCINT_ERRORS)) { - td->did_nak = 1; + td->did_nak++; td->tt_scheduled = 0; goto send_pkt; } else if (hcint & HCINT_ACK) { @@ -1085,7 +1085,7 @@ dwc_otg_host_rate_check(struct dwc_otg_t if (!td->tt_scheduled) goto busy; td->tt_scheduled = 0; - } else if (td->did_nak != 0) { + } else if (td->did_nak >= DWC_OTG_NAK_MAX) { goto busy; } else if (td->set_toggle) { td->set_toggle = 0; @@ -1244,7 +1244,7 @@ check_state: case DWC_CHAN_ST_WAIT_ANE: if (hcint & (HCINT_RETRY | HCINT_ERRORS)) { - td->did_nak = 1; + td->did_nak++; td->tt_scheduled = 0; if (td->hcsplt != 0) goto receive_spkt; @@ -1284,6 +1284,7 @@ check_state: */ } td->tt_scheduled = 0; + td->did_nak = 0; if (td->hcsplt != 0) goto receive_spkt; else @@ -1298,14 +1299,16 @@ check_state: * case of interrupt and isochronous transfers: */ if (hcint & (HCINT_RETRY | HCINT_ERRORS)) { - td->did_nak = 1; + td->did_nak++; td->tt_scheduled = 0; goto receive_spkt; } else if (hcint & HCINT_NYET) { td->tt_scheduled = 0; goto receive_spkt; - } else if (hcint & HCINT_ACK) + } else if (hcint & HCINT_ACK) { + td->did_nak = 0; goto receive_pkt; + } break; case DWC_CHAN_ST_WAIT_C_PKT: @@ -1633,13 +1636,14 @@ check_state: case DWC_CHAN_ST_WAIT_ANE: if (hcint & (HCINT_RETRY | HCINT_ERRORS)) { - td->did_nak = 1; + td->did_nak++; td->tt_scheduled = 0; goto send_pkt; } else if (hcint & (HCINT_ACK | HCINT_NYET)) { td->offset += td->tx_bytes; td->remainder -= td->tx_bytes; td->toggle ^= 1; + td->did_nak = 0; td->tt_scheduled = 0; /* check remainder */ @@ -1658,24 +1662,27 @@ check_state: case DWC_CHAN_ST_WAIT_S_ANE: if (hcint & (HCINT_RETRY | HCINT_ERRORS)) { - td->did_nak = 1; + td->did_nak++; td->tt_scheduled = 0; goto send_pkt; - } else if (hcint & (HCINT_ACK | HCINT_NYET)) + } else if (hcint & (HCINT_ACK | HCINT_NYET)) { + td->did_nak = 0; goto send_cpkt; + } break; case DWC_CHAN_ST_WAIT_C_ANE: if (hcint & HCINT_NYET) { goto send_cpkt; } else if (hcint & (HCINT_RETRY | HCINT_ERRORS)) { - td->did_nak = 1; + td->did_nak++; td->tt_scheduled = 0; goto send_pkt; } else if (hcint & HCINT_ACK) { td->offset += td->tx_bytes; td->remainder -= td->tx_bytes; td->toggle ^= 1; + td->did_nak = 0; td->tt_scheduled = 0; /* check remainder */ @@ -2283,8 +2290,10 @@ dwc_otg_timer(void *_sc) TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { td = xfer->td_transfer_cache; - if (td != NULL) + if (td != NULL) { + /* reset NAK counter */ td->did_nak = 0; + } } /* enable SOF interrupt, which will poll jobs */ @@ -2429,8 +2438,11 @@ dwc_otg_update_host_transfer_schedule(st TAILQ_FOREACH_SAFE(xfer, &sc->sc_bus.intr_q.head, wait_entry, xfer_next) { td = xfer->td_transfer_cache; - if (td == NULL || td->did_nak != 0 || td->ep_type != UE_CONTROL) + if (td == NULL || + td->ep_type != UE_CONTROL || + td->did_nak >= DWC_OTG_NAK_MAX) { continue; + } sc->sc_needsof = 1; @@ -2448,8 +2460,11 @@ dwc_otg_update_host_transfer_schedule(st if ((temp & 7) < 6) { TAILQ_FOREACH_SAFE(xfer, &sc->sc_bus.intr_q.head, wait_entry, xfer_next) { td = xfer->td_transfer_cache; - if (td == NULL || td->did_nak != 0 || td->ep_type != UE_BULK) + if (td == NULL || + td->ep_type != UE_BULK || + td->did_nak >= DWC_OTG_NAK_MAX) { continue; + } sc->sc_needsof = 1; @@ -3206,24 +3221,53 @@ static void dwc_otg_start_standard_chain(struct usb_xfer *xfer) { struct dwc_otg_softc *sc = DWC_OTG_BUS2SC(xfer->xroot->bus); + struct usb_xfer_root *xroot; + struct dwc_otg_td *td; DPRINTFN(9, "\n"); - /* poll one time - will turn on interrupts */ - if (dwc_otg_xfer_do_fifo(xfer)) { + /* + * Poll one time in device mode, which will turn on the + * endpoint interrupts. Else wait for SOF interrupt in host + * mode. + */ + if (sc->sc_flags.status_device_mode != 0 && + dwc_otg_xfer_do_fifo(xfer) == 0) + goto done; - /* put transfer on interrupt queue */ - usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer); + /* put transfer on interrupt queue */ + usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer); - /* start timeout, if any */ - if (xfer->timeout != 0) { - usbd_transfer_timeout_ms(xfer, - &dwc_otg_timeout, xfer->timeout); - } + /* start timeout, if any */ + if (xfer->timeout != 0) { + usbd_transfer_timeout_ms(xfer, + &dwc_otg_timeout, xfer->timeout); + } + + if (sc->sc_flags.status_device_mode != 0) + goto done; - /* enable SOF interrupt, if any */ - dwc_otg_enable_sof_irq(sc); + /* enable SOF interrupt, if any */ + dwc_otg_enable_sof_irq(sc); + + td = xfer->td_transfer_cache; + if (td->ep_type != UE_BULK) + goto done; + + xroot = xfer->xroot; + + /* + * Optimise the ping-pong effect by waking up other BULK + * transfers belonging to the same device group: + */ + TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { + td = xfer->td_transfer_cache; + if (td == NULL || td->ep_type != UE_BULK || xfer->xroot != xroot) + continue; + /* reset NAK counter */ + td->did_nak = 0; } +done:; } static void Modified: head/sys/dev/usb/controller/dwc_otg.h ============================================================================== --- head/sys/dev/usb/controller/dwc_otg.h Sun May 11 05:49:35 2014 (r265871) +++ head/sys/dev/usb/controller/dwc_otg.h Sun May 11 08:17:46 2014 (r265872) @@ -37,6 +37,7 @@ #define DWC_OTG_TT_SLOT_MAX 8 #define DWC_OTG_SLOT_IDLE_MAX 4 #define DWC_OTG_SLOT_IDLE_MIN 2 +#define DWC_OTG_NAK_MAX 8 /* 1 ms */ #define DWC_OTG_READ_4(sc, reg) \ bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg) @@ -64,6 +65,7 @@ struct dwc_otg_td { uint8_t errcnt; uint8_t tmr_res; uint8_t tmr_val; + uint8_t did_nak; /* NAK counter */ uint8_t ep_no; uint8_t ep_type; uint8_t channel[2]; @@ -87,7 +89,6 @@ struct dwc_otg_td { uint8_t toggle:1; uint8_t set_toggle:1; uint8_t got_short:1; - uint8_t did_nak:1; uint8_t tt_scheduled:1; uint8_t tt_channel_tog:1; };