From owner-svn-src-head@freebsd.org Wed Jul 13 20:46:55 2016 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 B13B6B98CE2; Wed, 13 Jul 2016 20:46:55 +0000 (UTC) (envelope-from jmcneill@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 8EB8F1546; Wed, 13 Jul 2016 20:46:55 +0000 (UTC) (envelope-from jmcneill@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u6DKks7V045709; Wed, 13 Jul 2016 20:46:54 GMT (envelope-from jmcneill@FreeBSD.org) Received: (from jmcneill@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u6DKkswZ045707; Wed, 13 Jul 2016 20:46:54 GMT (envelope-from jmcneill@FreeBSD.org) Message-Id: <201607132046.u6DKkswZ045707@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jmcneill set sender to jmcneill@FreeBSD.org using -f From: Jared McNeill Date: Wed, 13 Jul 2016 20:46:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r302786 - head/sys/arm/allwinner 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.22 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: Wed, 13 Jul 2016 20:46:55 -0000 Author: jmcneill Date: Wed Jul 13 20:46:54 2016 New Revision: 302786 URL: https://svnweb.freebsd.org/changeset/base/302786 Log: Allwinner Gigabit EMAC performance improvements. - Support DEVICE_POLLING - Increase TX descriptors to 1024 - Add support for passing a chain of mbufs to if_input, reducing the number of calls to mtx_unlock/mtx_lock under load. - Remove duplicate byteswap when setting TX_INT_CTL in TX descriptor. - Set undocumented "TX_NEXT_FRAME" bit in TX control 1 register. According to the A83T BSP, setting this bit allows the DMA engine to operate on a packet while receiving another. Tested on A83T (1000Mbps PHY) and H3 (100Mbps PHY). Reviewed by: manu Differential Revision: https://reviews.freebsd.org/D7031 Modified: head/sys/arm/allwinner/if_awg.c head/sys/arm/allwinner/if_awgreg.h Modified: head/sys/arm/allwinner/if_awg.c ============================================================================== --- head/sys/arm/allwinner/if_awg.c Wed Jul 13 20:44:02 2016 (r302785) +++ head/sys/arm/allwinner/if_awg.c Wed Jul 13 20:46:54 2016 (r302786) @@ -30,6 +30,8 @@ * Allwinner Gigabit Ethernet MAC (EMAC) controller */ +#include "opt_device_polling.h" + #include __FBSDID("$FreeBSD$"); @@ -77,7 +79,7 @@ __FBSDID("$FreeBSD$"); #define AWG_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED) #define DESC_ALIGN 4 -#define TX_DESC_COUNT 256 +#define TX_DESC_COUNT 1024 #define TX_DESC_SIZE (sizeof(struct emac_desc) * TX_DESC_COUNT) #define RX_DESC_COUNT 256 #define RX_DESC_SIZE (sizeof(struct emac_desc) * RX_DESC_COUNT) @@ -97,6 +99,7 @@ __FBSDID("$FreeBSD$"); #define RX_TX_PRI_DEFAULT 0 #define PAUSE_TIME_DEFAULT 0x400 #define TX_INTERVAL_DEFAULT 64 +#define RX_BATCH_DEFAULT 64 /* Burst length of RX and TX DMA transfers */ static int awg_burst_len = BURST_LEN_DEFAULT; @@ -114,6 +117,10 @@ TUNABLE_INT("hw.awg.pause_time", &awg_pa static int awg_tx_interval = TX_INTERVAL_DEFAULT; TUNABLE_INT("hw.awg.tx_interval", &awg_tx_interval); +/* Maximum number of mbufs to send to if_input */ +static int awg_rx_batch = RX_BATCH_DEFAULT; +TUNABLE_INT("hw.awg.rx_batch", &awg_rx_batch); + static struct ofw_compat_data compat_data[] = { { "allwinner,sun8i-a83t-emac", 1 }, { NULL, 0 } @@ -353,7 +360,7 @@ awg_setup_txdesc(struct awg_softc *sc, i status = TX_DESC_CTL; size = flags | len; if ((index & (awg_tx_interval - 1)) == 0) - size |= htole32(TX_INT_CTL); + size |= TX_INT_CTL; ++sc->tx.queued; } @@ -617,6 +624,20 @@ awg_setup_rxfilter(struct awg_softc *sc) } static void +awg_enable_intr(struct awg_softc *sc) +{ + /* Enable interrupts */ + WR4(sc, EMAC_INT_EN, RX_INT_EN | TX_INT_EN | TX_BUF_UA_INT_EN); +} + +static void +awg_disable_intr(struct awg_softc *sc) +{ + /* Disable interrupts */ + WR4(sc, EMAC_INT_EN, 0); +} + +static void awg_init_locked(struct awg_softc *sc) { struct mii_data *mii; @@ -640,11 +661,18 @@ awg_init_locked(struct awg_softc *sc) WR4(sc, EMAC_BASIC_CTL_1, val); /* Enable interrupts */ - WR4(sc, EMAC_INT_EN, RX_INT_EN | TX_INT_EN | TX_BUF_UA_INT_EN); +#ifdef DEVICE_POLLING + if ((if_getcapenable(ifp) & IFCAP_POLLING) == 0) + awg_enable_intr(sc); + else + awg_disable_intr(sc); +#else + awg_enable_intr(sc); +#endif /* Enable transmit DMA */ val = RD4(sc, EMAC_TX_CTL_1); - WR4(sc, EMAC_TX_CTL_1, val | TX_DMA_EN | TX_MD); + WR4(sc, EMAC_TX_CTL_1, val | TX_DMA_EN | TX_MD | TX_NEXT_FRAME); /* Enable receive DMA */ val = RD4(sc, EMAC_RX_CTL_1); @@ -703,7 +731,7 @@ awg_stop(struct awg_softc *sc) WR4(sc, EMAC_RX_CTL_0, val & ~RX_EN); /* Disable interrupts */ - WR4(sc, EMAC_INT_EN, 0); + awg_disable_intr(sc); /* Disable transmit DMA */ val = RD4(sc, EMAC_TX_CTL_1); @@ -718,15 +746,18 @@ awg_stop(struct awg_softc *sc) if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING | IFF_DRV_OACTIVE); } -static void +static int awg_rxintr(struct awg_softc *sc) { if_t ifp; - struct mbuf *m, *m0; - int error, index, len; + struct mbuf *m, *m0, *mh, *mt; + int error, index, len, cnt, npkt; uint32_t status; ifp = sc->ifp; + mh = mt = NULL; + cnt = 0; + npkt = 0; bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); @@ -760,9 +791,23 @@ awg_rxintr(struct awg_softc *sc) } } - AWG_UNLOCK(sc); - if_input(ifp, m); - AWG_LOCK(sc); + m->m_nextpkt = NULL; + if (mh == NULL) + mh = m; + else + mt->m_nextpkt = m; + mt = m; + ++cnt; + ++npkt; + + if (cnt == awg_rx_batch) { + AWG_UNLOCK(sc); + if_input(ifp, mh); + AWG_LOCK(sc); + mh = mt = NULL; + cnt = 0; + } + } if ((m0 = awg_alloc_mbufcl(sc)) != NULL) { @@ -779,7 +824,15 @@ awg_rxintr(struct awg_softc *sc) BUS_DMASYNC_PREWRITE); } + if (mh != NULL) { + AWG_UNLOCK(sc); + if_input(ifp, mh); + AWG_LOCK(sc); + } + sc->rx.cur = index; + + return (npkt); } static void @@ -845,6 +898,41 @@ awg_intr(void *arg) AWG_UNLOCK(sc); } +#ifdef DEVICE_POLLING +static int +awg_poll(if_t ifp, enum poll_cmd cmd, int count) +{ + struct awg_softc *sc; + uint32_t val; + int rx_npkts; + + sc = if_getsoftc(ifp); + rx_npkts = 0; + + AWG_LOCK(sc); + + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) { + AWG_UNLOCK(sc); + return (0); + } + + rx_npkts = awg_rxintr(sc); + awg_txintr(sc); + if (!if_sendq_empty(ifp)) + awg_start_locked(sc); + + if (cmd == POLL_AND_CHECK_STATUS) { + val = RD4(sc, EMAC_INT_STA); + if (val != 0) + WR4(sc, EMAC_INT_STA, val); + } + + AWG_UNLOCK(sc); + + return (rx_npkts); +} +#endif + static int awg_ioctl(if_t ifp, u_long cmd, caddr_t data) { @@ -889,6 +977,25 @@ awg_ioctl(if_t ifp, u_long cmd, caddr_t break; case SIOCSIFCAP: mask = ifr->ifr_reqcap ^ if_getcapenable(ifp); +#ifdef DEVICE_POLLING + if (mask & IFCAP_POLLING) { + if ((ifr->ifr_reqcap & IFCAP_POLLING) != 0) { + error = ether_poll_register(awg_poll, ifp); + if (error != 0) + break; + AWG_LOCK(sc); + awg_disable_intr(sc); + if_setcapenablebit(ifp, IFCAP_POLLING, 0); + AWG_UNLOCK(sc); + } else { + error = ether_poll_deregister(ifp); + AWG_LOCK(sc); + awg_enable_intr(sc); + if_setcapenablebit(ifp, 0, IFCAP_POLLING); + AWG_UNLOCK(sc); + } + } +#endif if (mask & IFCAP_VLAN_MTU) if_togglecapenable(ifp, IFCAP_VLAN_MTU); if (mask & IFCAP_RXCSUM) @@ -1374,6 +1481,9 @@ awg_attach(device_t dev) if_sethwassist(sc->ifp, CSUM_IP | CSUM_UDP | CSUM_TCP); if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM); if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp)); +#ifdef DEVICE_POLLING + if_setcapabilitiesbit(sc->ifp, IFCAP_POLLING, 0); +#endif /* Attach MII driver */ error = mii_attach(dev, &sc->miibus, sc->ifp, awg_media_change, Modified: head/sys/arm/allwinner/if_awgreg.h ============================================================================== --- head/sys/arm/allwinner/if_awgreg.h Wed Jul 13 20:44:02 2016 (r302785) +++ head/sys/arm/allwinner/if_awgreg.h Wed Jul 13 20:46:54 2016 (r302786) @@ -65,6 +65,7 @@ #define EMAC_TX_CTL_1 0x14 #define TX_DMA_START (1 << 31) #define TX_DMA_EN (1 << 30) +#define TX_NEXT_FRAME (1 << 2) #define TX_MD (1 << 1) #define FLUSH_TX_FIFO (1 << 0) #define EMAC_TX_FLOW_CTL 0x1c