From owner-svn-src-head@freebsd.org Sun Nov 8 09:37:28 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5C865A26E8F; Sun, 8 Nov 2015 09:37:28 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::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 1A078161E; Sun, 8 Nov 2015 09:37:28 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tA89bR4K002563; Sun, 8 Nov 2015 09:37:27 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tA89bRlZ002561; Sun, 8 Nov 2015 09:37:27 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201511080937.tA89bRlZ002561@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Sun, 8 Nov 2015 09:37:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r290542 - 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-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 08 Nov 2015 09:37:28 -0000 Author: hselasky Date: Sun Nov 8 09:37:26 2015 New Revision: 290542 URL: https://svnweb.freebsd.org/changeset/base/290542 Log: Avoid using the bounce buffer when the source or destination buffer is 32-bits aligned. Merge the two bounce buffers into a single one. Some rough tests showed that the DWC OTG throughput on RPI2 increased by 10% after this patch. MFC after: 1 week 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 Nov 8 08:31:34 2015 (r290541) +++ head/sys/dev/usb/controller/dwc_otg.c Sun Nov 8 09:37:26 2015 (r290542) @@ -181,6 +181,110 @@ dwc_otg_get_hw_ep_profile(struct usb_dev } static void +dwc_otg_write_fifo(struct dwc_otg_softc *sc, struct usb_page_cache *pc, + uint32_t offset, uint32_t fifo, uint32_t count) +{ + uint32_t temp; + + /* round down length to nearest 4-bytes */ + temp = count & ~3; + + /* check if we can write the data directly */ + if (temp != 0 && usb_pc_buffer_is_aligned(pc, offset, temp, 3)) { + struct usb_page_search buf_res; + + /* pre-subtract length */ + count -= temp; + + /* iterate buffer list */ + do { + /* get current buffer pointer */ + usbd_get_page(pc, offset, &buf_res); + + if (buf_res.length > temp) + buf_res.length = temp; + + /* transfer data into FIFO */ + bus_space_write_region_4(sc->sc_io_tag, sc->sc_io_hdl, + fifo, buf_res.buffer, buf_res.length / 4); + + offset += buf_res.length; + fifo += buf_res.length; + temp -= buf_res.length; + } while (temp != 0); + } + + /* check for remainder */ + if (count != 0) { + /* clear topmost word before copy */ + sc->sc_bounce_buffer[(count - 1) / 4] = 0; + + /* copy out data */ + usbd_copy_out(pc, offset, + sc->sc_bounce_buffer, count); + + /* transfer data into FIFO */ + bus_space_write_region_4(sc->sc_io_tag, + sc->sc_io_hdl, fifo, sc->sc_bounce_buffer, + (count + 3) / 4); + } +} + +static void +dwc_otg_read_fifo(struct dwc_otg_softc *sc, struct usb_page_cache *pc, + uint32_t offset, uint32_t count) +{ + uint32_t temp; + + /* round down length to nearest 4-bytes */ + temp = count & ~3; + + /* check if we can read the data directly */ + if (temp != 0 && usb_pc_buffer_is_aligned(pc, offset, temp, 3)) { + struct usb_page_search buf_res; + + /* pre-subtract length */ + count -= temp; + + /* iterate buffer list */ + do { + /* get current buffer pointer */ + usbd_get_page(pc, offset, &buf_res); + + if (buf_res.length > temp) + buf_res.length = temp; + + /* transfer data from FIFO */ + bus_space_read_region_4(sc->sc_io_tag, sc->sc_io_hdl, + sc->sc_current_rx_fifo, buf_res.buffer, buf_res.length / 4); + + offset += buf_res.length; + sc->sc_current_rx_fifo += buf_res.length; + sc->sc_current_rx_bytes -= buf_res.length; + temp -= buf_res.length; + } while (temp != 0); + } + + /* check for remainder */ + if (count != 0) { + /* read data into bounce buffer */ + bus_space_read_region_4(sc->sc_io_tag, sc->sc_io_hdl, + sc->sc_current_rx_fifo, + sc->sc_bounce_buffer, (count + 3) / 4); + + /* store data into proper buffer */ + usbd_copy_in(pc, offset, sc->sc_bounce_buffer, count); + + /* round length up to nearest 4 bytes */ + count = (count + 3) & ~3; + + /* update counters */ + sc->sc_current_rx_bytes -= count; + sc->sc_current_rx_fifo += count; + } +} + +static void dwc_otg_tx_fifo_reset(struct dwc_otg_softc *sc, uint32_t value) { uint32_t temp; @@ -579,6 +683,14 @@ dwc_otg_common_rx_ack(struct dwc_otg_sof sc->sc_irq_mask |= GINTMSK_RXFLVLMSK; DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask); + if (sc->sc_current_rx_bytes != 0) { + /* need to dump remaining data */ + bus_space_read_region_4(sc->sc_io_tag, sc->sc_io_hdl, + sc->sc_current_rx_fifo, sc->sc_bounce_buffer, + sc->sc_current_rx_bytes / 4); + /* clear number of active bytes to receive */ + sc->sc_current_rx_bytes = 0; + } /* clear cached status */ sc->sc_last_rx_status = 0; } @@ -761,6 +873,7 @@ dwc_otg_host_dump_rx(struct dwc_otg_soft td->channel[x] != GRXSTSRD_CHNUM_GET(sc->sc_last_rx_status)) continue; dwc_otg_common_rx_ack(sc); + break; } } @@ -898,6 +1011,7 @@ send_pkt: td->state = DWC_CHAN_ST_WAIT_ANE; } + /* copy out control request */ usbd_copy_out(td->pc, 0, &req, sizeof(req)); DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(td->channel[0]), @@ -1024,11 +1138,11 @@ dwc_otg_setup_rx(struct dwc_otg_softc *s goto not_complete; } - /* copy in control request */ - memcpy(&req, sc->sc_rx_bounce_buffer, sizeof(req)); + /* read FIFO */ + dwc_otg_read_fifo(sc, td->pc, 0, sizeof(req)); - /* copy data into real buffer */ - usbd_copy_in(td->pc, 0, &req, sizeof(req)); + /* copy out control request */ + usbd_copy_out(td->pc, 0, &req, sizeof(req)); td->offset = sizeof(req); td->remainder = 0; @@ -1212,8 +1326,8 @@ dwc_otg_host_data_rx_sub(struct dwc_otg_ goto complete; } - usbd_copy_in(td->pc, td->offset, - sc->sc_rx_bounce_buffer, count); + /* read data from FIFO */ + dwc_otg_read_fifo(sc, td->pc, td->offset, count); td->remainder -= count; td->offset += count; @@ -1583,7 +1697,9 @@ dwc_otg_data_rx(struct dwc_otg_softc *sc return (0); /* we are complete */ } - usbd_copy_in(td->pc, td->offset, sc->sc_rx_bounce_buffer, count); + /* read data from FIFO */ + dwc_otg_read_fifo(sc, td->pc, td->offset, count); + td->remainder -= count; td->offset += count; @@ -1904,17 +2020,9 @@ send_pkt: DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar); if (count != 0) { - /* clear topmost word before copy */ - sc->sc_tx_bounce_buffer[(count - 1) / 4] = 0; - - /* copy out data */ - usbd_copy_out(td->pc, td->offset + td->tx_bytes, - sc->sc_tx_bounce_buffer, count); - - /* transfer data into FIFO */ - bus_space_write_region_4(sc->sc_io_tag, sc->sc_io_hdl, - DOTG_DFIFO(channel), - sc->sc_tx_bounce_buffer, (count + 3) / 4); + /* write data into FIFO */ + dwc_otg_write_fifo(sc, td->pc, td->offset + + td->tx_bytes, DOTG_DFIFO(channel), count); } /* store number of bytes transmitted */ @@ -2054,18 +2162,9 @@ repeat: count = fifo_left; if (count != 0) { - - /* clear topmost word before copy */ - sc->sc_tx_bounce_buffer[(count - 1) / 4] = 0; - - /* copy out data */ - usbd_copy_out(td->pc, td->offset, - sc->sc_tx_bounce_buffer, count); - - /* transfer data into FIFO */ - bus_space_write_region_4(sc->sc_io_tag, sc->sc_io_hdl, - DOTG_DFIFO(td->ep_no), - sc->sc_tx_bounce_buffer, (count + 3) / 4); + /* write data into FIFO */ + dwc_otg_write_fifo(sc, td->pc, td->offset, + DOTG_DFIFO(td->ep_no), count); td->tx_bytes -= count; td->remainder -= count; @@ -2616,6 +2715,11 @@ repeat: sc->sc_chan_state[ep_no].wait_halted = 0; DPRINTFN(5, "channel halt complete ch=%u\n", ep_no); } + /* store bytes and FIFO offset */ + sc->sc_current_rx_bytes = 0; + sc->sc_current_rx_fifo = 0; + + /* acknowledge status */ dwc_otg_common_rx_ack(sc); goto repeat; } @@ -2625,13 +2729,11 @@ repeat: ep_no = GRXSTSRD_CHNUM_GET( sc->sc_last_rx_status); - /* receive data, if any */ - if (temp != 0) { - DPRINTF("Reading %d bytes from ep %d\n", temp, ep_no); - bus_space_read_region_4(sc->sc_io_tag, sc->sc_io_hdl, - DOTG_DFIFO(ep_no), - sc->sc_rx_bounce_buffer, (temp + 3) / 4); - } + /* store bytes and FIFO offset */ + sc->sc_current_rx_bytes = (temp + 3) & ~3; + sc->sc_current_rx_fifo = DOTG_DFIFO(ep_no); + + DPRINTF("Reading %d bytes from ep %d\n", temp, ep_no); /* check if we should dump the data */ if (!(sc->sc_active_rx_ep & (1U << ep_no))) { Modified: head/sys/dev/usb/controller/dwc_otg.h ============================================================================== --- head/sys/dev/usb/controller/dwc_otg.h Sun Nov 8 08:31:34 2015 (r290541) +++ head/sys/dev/usb/controller/dwc_otg.h Sun Nov 8 09:37:26 2015 (r290542) @@ -173,8 +173,7 @@ struct dwc_otg_softc { bus_space_tag_t sc_io_tag; bus_space_handle_t sc_io_hdl; - uint32_t sc_rx_bounce_buffer[1024 / 4]; - uint32_t sc_tx_bounce_buffer[MAX(512 * DWC_OTG_MAX_TXP, 1024) / 4]; + uint32_t sc_bounce_buffer[MAX(512 * DWC_OTG_MAX_TXP, 1024) / 4]; uint32_t sc_fifo_size; uint32_t sc_irq_mask; @@ -186,6 +185,9 @@ struct dwc_otg_softc { uint32_t sc_hprt_val; uint32_t sc_xfer_complete; + uint16_t sc_current_rx_bytes; + uint16_t sc_current_rx_fifo; + uint16_t sc_active_rx_ep; uint16_t sc_last_frame_num;