Page MenuHomeFreeBSD

D7031.id18386.diff
No OneTemporary

D7031.id18386.diff

Index: head/sys/arm/allwinner/if_awg.c
===================================================================
--- head/sys/arm/allwinner/if_awg.c
+++ head/sys/arm/allwinner/if_awg.c
@@ -30,6 +30,8 @@
* Allwinner Gigabit Ethernet MAC (EMAC) controller
*/
+#include "opt_device_polling.h"
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -77,7 +79,7 @@
#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 @@
#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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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_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 @@
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_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 @@
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 @@
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,
Index: head/sys/arm/allwinner/if_awgreg.h
===================================================================
--- head/sys/arm/allwinner/if_awgreg.h
+++ head/sys/arm/allwinner/if_awgreg.h
@@ -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

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 22, 7:47 AM (18 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25935004
Default Alt Text
D7031.id18386.diff (5 KB)

Event Timeline