Module Name: src
Committed By: nonaka
Date: Tue Feb 17 01:53:21 UTC 2015
Modified Files:
src/sys/arch/powerpc/booke/dev: pq3etsec.c
src/sys/arch/powerpc/include/booke: etsecreg.h
Log Message:
Added Interrupt coalescing support.
To generate a diff of this commit:
cvs rdiff -u -r1.24 -r1.25 src/sys/arch/powerpc/booke/dev/pq3etsec.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/powerpc/include/booke/etsecreg.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/powerpc/booke/dev/pq3etsec.c
diff -u src/sys/arch/powerpc/booke/dev/pq3etsec.c:1.24 src/sys/arch/powerpc/booke/dev/pq3etsec.c:1.25
--- src/sys/arch/powerpc/booke/dev/pq3etsec.c:1.24 Fri Jan 23 06:58:32 2015
+++ src/sys/arch/powerpc/booke/dev/pq3etsec.c Tue Feb 17 01:53:21 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: pq3etsec.c,v 1.24 2015/01/23 06:58:32 nonaka Exp $ */
+/* $NetBSD: pq3etsec.c,v 1.25 2015/02/17 01:53:21 nonaka Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -41,7 +41,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pq3etsec.c,v 1.24 2015/01/23 06:58:32 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pq3etsec.c,v 1.25 2015/02/17 01:53:21 nonaka Exp $");
#include <sys/param.h>
#include <sys/cpu.h>
@@ -55,6 +55,7 @@ __KERNEL_RCSID(0, "$NetBSD: pq3etsec.c,v
#include <sys/proc.h>
#include <sys/atomic.h>
#include <sys/callout.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -77,7 +78,6 @@ __KERNEL_RCSID(0, "$NetBSD: pq3etsec.c,v
#endif
#include <netinet6/in6_offload.h>
-
#include <powerpc/spr.h>
#include <powerpc/booke/spr.h>
@@ -232,8 +232,19 @@ struct pq3etsec_softc {
struct ifqueue sc_rx_bufcache;
struct pq3etsec_mapcache *sc_rx_mapcache;
struct pq3etsec_mapcache *sc_tx_mapcache;
+
+ /* Interrupt Coalescing parameters */
+ int sc_ic_rx_time;
+ int sc_ic_rx_count;
+ int sc_ic_tx_time;
+ int sc_ic_tx_count;
};
+#define ETSEC_IC_RX_ENABLED(sc) \
+ ((sc)->sc_ic_rx_time != 0 && (sc)->sc_ic_rx_count != 0)
+#define ETSEC_IC_TX_ENABLED(sc) \
+ ((sc)->sc_ic_tx_time != 0 && (sc)->sc_ic_tx_count != 0)
+
struct pq3mdio_softc {
device_t mdio_dev;
@@ -294,6 +305,11 @@ static int pq3etsec_tx_intr(void *);
static int pq3etsec_error_intr(void *);
static void pq3etsec_soft_intr(void *);
+static void pq3etsec_set_ic_rx(struct pq3etsec_softc *);
+static void pq3etsec_set_ic_tx(struct pq3etsec_softc *);
+
+static void pq3etsec_sysctl_setup(struct sysctllog **, struct pq3etsec_softc *);
+
CFATTACH_DECL_NEW(pq3etsec, sizeof(struct pq3etsec_softc),
pq3etsec_match, pq3etsec_attach, NULL, NULL);
@@ -711,6 +727,15 @@ pq3etsec_attach(device_t parent, device_
etsec_write(sc, ATTR, ATTR_DEFAULT);
etsec_write(sc, ATTRELI, ATTRELI_DEFAULT);
+ /* Enable interrupt coalesing */
+ sc->sc_ic_rx_time = 768;
+ sc->sc_ic_rx_count = 16;
+ sc->sc_ic_tx_time = 768;
+ sc->sc_ic_tx_count = 16;
+ pq3etsec_set_ic_rx(sc);
+ pq3etsec_set_ic_tx(sc);
+ pq3etsec_sysctl_setup(NULL, sc);
+
char enaddr[ETHER_ADDR_LEN] = {
[0] = sc->sc_macstnaddr2 >> 16,
[1] = sc->sc_macstnaddr2 >> 24,
@@ -1874,7 +1899,8 @@ pq3etsec_txq_produce(
* we need to ask for an interrupt to reclaim some.
*/
txq->txq_lastintr += map->dm_nsegs;
- if (txq->txq_lastintr >= txq->txq_threshold
+ if (ETSEC_IC_TX_ENABLED(sc)
+ || txq->txq_lastintr >= txq->txq_threshold
|| txq->txq_mbufs.ifq_len + 1 == txq->txq_mbufs.ifq_maxlen) {
txq->txq_lastintr = 0;
last_flags |= TXBD_I;
@@ -2529,3 +2555,189 @@ pq3etsec_mii_tick(void *arg)
#endif
mutex_exit(sc->sc_lock);
}
+
+static void
+pq3etsec_set_ic_rx(struct pq3etsec_softc *sc)
+{
+ uint32_t reg;
+
+ if (ETSEC_IC_RX_ENABLED(sc)) {
+ reg = RXIC_ICEN;
+ reg |= RXIC_ICFT_SET(sc->sc_ic_rx_count);
+ reg |= RXIC_ICTT_SET(sc->sc_ic_rx_time);
+ } else {
+ /* Disable RX interrupt coalescing */
+ reg = 0;
+ }
+
+ etsec_write(sc, RXIC, reg);
+}
+
+static void
+pq3etsec_set_ic_tx(struct pq3etsec_softc *sc)
+{
+ uint32_t reg;
+
+ if (ETSEC_IC_TX_ENABLED(sc)) {
+ reg = TXIC_ICEN;
+ reg |= TXIC_ICFT_SET(sc->sc_ic_tx_count);
+ reg |= TXIC_ICTT_SET(sc->sc_ic_tx_time);
+ } else {
+ /* Disable TX interrupt coalescing */
+ reg = 0;
+ }
+
+ etsec_write(sc, TXIC, reg);
+}
+
+/*
+ * sysctl
+ */
+static int
+pq3etsec_sysctl_ic_time_helper(SYSCTLFN_ARGS, int *valuep)
+{
+ struct sysctlnode node = *rnode;
+ struct pq3etsec_softc *sc = rnode->sysctl_data;
+ int value = *valuep;
+ int error;
+
+ node.sysctl_data = &value;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error != 0 || newp == NULL)
+ return error;
+
+ if (value < 0 || value > 65535)
+ return EINVAL;
+
+ mutex_enter(sc->sc_lock);
+ *valuep = value;
+ if (valuep == &sc->sc_ic_rx_time)
+ pq3etsec_set_ic_rx(sc);
+ else
+ pq3etsec_set_ic_tx(sc);
+ mutex_exit(sc->sc_lock);
+
+ return 0;
+}
+
+static int
+pq3etsec_sysctl_ic_count_helper(SYSCTLFN_ARGS, int *valuep)
+{
+ struct sysctlnode node = *rnode;
+ struct pq3etsec_softc *sc = rnode->sysctl_data;
+ int value = *valuep;
+ int error;
+
+ node.sysctl_data = &value;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error != 0 || newp == NULL)
+ return error;
+
+ if (value < 0 || value > 255)
+ return EINVAL;
+
+ mutex_enter(sc->sc_lock);
+ *valuep = value;
+ if (valuep == &sc->sc_ic_rx_count)
+ pq3etsec_set_ic_rx(sc);
+ else
+ pq3etsec_set_ic_tx(sc);
+ mutex_exit(sc->sc_lock);
+
+ return 0;
+}
+
+static int
+pq3etsec_sysctl_ic_rx_time_helper(SYSCTLFN_ARGS)
+{
+ struct pq3etsec_softc *sc = rnode->sysctl_data;
+
+ return pq3etsec_sysctl_ic_time_helper(SYSCTLFN_CALL(rnode),
+ &sc->sc_ic_rx_time);
+}
+
+static int
+pq3etsec_sysctl_ic_rx_count_helper(SYSCTLFN_ARGS)
+{
+ struct pq3etsec_softc *sc = rnode->sysctl_data;
+
+ return pq3etsec_sysctl_ic_count_helper(SYSCTLFN_CALL(rnode),
+ &sc->sc_ic_rx_count);
+}
+
+static int
+pq3etsec_sysctl_ic_tx_time_helper(SYSCTLFN_ARGS)
+{
+ struct pq3etsec_softc *sc = rnode->sysctl_data;
+
+ return pq3etsec_sysctl_ic_time_helper(SYSCTLFN_CALL(rnode),
+ &sc->sc_ic_tx_time);
+}
+
+static int
+pq3etsec_sysctl_ic_tx_count_helper(SYSCTLFN_ARGS)
+{
+ struct pq3etsec_softc *sc = rnode->sysctl_data;
+
+ return pq3etsec_sysctl_ic_count_helper(SYSCTLFN_CALL(rnode),
+ &sc->sc_ic_tx_count);
+}
+
+static void pq3etsec_sysctl_setup(struct sysctllog **clog,
+ struct pq3etsec_softc *sc)
+{
+ const struct sysctlnode *cnode, *rnode;
+
+ if (sysctl_createv(clog, 0, NULL, &rnode,
+ CTLFLAG_PERMANENT,
+ CTLTYPE_NODE, device_xname(sc->sc_dev),
+ SYSCTL_DESCR("TSEC interface"),
+ NULL, 0, NULL, 0,
+ CTL_HW, CTL_CREATE, CTL_EOL) != 0)
+ goto bad;
+
+ if (sysctl_createv(clog, 0, &rnode, &rnode,
+ CTLFLAG_PERMANENT,
+ CTLTYPE_NODE, "int_coal",
+ SYSCTL_DESCR("Interrupts coalescing"),
+ NULL, 0, NULL, 0,
+ CTL_CREATE, CTL_EOL) != 0)
+ goto bad;
+
+ if (sysctl_createv(clog, 0, &rnode, &cnode,
+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+ CTLTYPE_INT, "rx_time",
+ SYSCTL_DESCR("RX time threshold (0-65535)"),
+ pq3etsec_sysctl_ic_rx_time_helper, 0, (void *)sc, 0,
+ CTL_CREATE, CTL_EOL) != 0)
+ goto bad;
+
+ if (sysctl_createv(clog, 0, &rnode, &cnode,
+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+ CTLTYPE_INT, "rx_count",
+ SYSCTL_DESCR("RX frame count threshold (0-255)"),
+ pq3etsec_sysctl_ic_rx_count_helper, 0, (void *)sc, 0,
+ CTL_CREATE, CTL_EOL) != 0)
+ goto bad;
+
+ if (sysctl_createv(clog, 0, &rnode, &cnode,
+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+ CTLTYPE_INT, "tx_time",
+ SYSCTL_DESCR("TX time threshold (0-65535)"),
+ pq3etsec_sysctl_ic_tx_time_helper, 0, (void *)sc, 0,
+ CTL_CREATE, CTL_EOL) != 0)
+ goto bad;
+
+ if (sysctl_createv(clog, 0, &rnode, &cnode,
+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+ CTLTYPE_INT, "tx_count",
+ SYSCTL_DESCR("TX frame count threshold (0-255)"),
+ pq3etsec_sysctl_ic_tx_count_helper, 0, (void *)sc, 0,
+ CTL_CREATE, CTL_EOL) != 0)
+ goto bad;
+
+ return;
+
+ bad:
+ aprint_error_dev(sc->sc_dev, "could not attach sysctl nodes\n");
+}
Index: src/sys/arch/powerpc/include/booke/etsecreg.h
diff -u src/sys/arch/powerpc/include/booke/etsecreg.h:1.5 src/sys/arch/powerpc/include/booke/etsecreg.h:1.6
--- src/sys/arch/powerpc/include/booke/etsecreg.h:1.5 Tue Jul 17 01:36:13 2012
+++ src/sys/arch/powerpc/include/booke/etsecreg.h Tue Feb 17 01:53:21 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: etsecreg.h,v 1.5 2012/07/17 01:36:13 matt Exp $ */
+/* $NetBSD: etsecreg.h,v 1.6 2015/02/17 01:53:21 nonaka Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -213,6 +213,14 @@ struct rxfcb {
#define TSTAT_TXFn(n) (TSTAT_TXF0 >> (n))
#define DFVLAN 0x108 /* Default VLAN control word [TSEC3] */
#define TXIC 0x110 /* Transmit interrupt coalescing register */
+#define TXIC_ICEN __PPCBIT(0) /* Interrupt coalescing enable */
+#define TXIC_ICCS __PPCBIT(1) /* Interrupt coalescing timer clock source */
+#define TXIC_ICCS_ETSEC 0 /* eTSEC Tx interface clocks */
+#define TXIC_ICCS_SYSTEM TXIC_ICCS /* system clocks */
+#define TXIC_ICFT __PPCBITS(3,10)
+#define TXIC_ICFT_SET(n) __SHIFTIN((n),TXIC_ICFT)
+#define TXIC_ICTT __PPCBITS(16,31)
+#define TXIC_ICTT_SET(n) __SHIFTIN((n),TXIC_ICTT)
#define TQUEUE 0x114 /* Transmit queue control register [TSEC3] */
#define TQUEUE_EN0 __PPCBIT(16) /* transmit ring enabled */
#define TQUEUE_EN1 __PPCBIT(17)
@@ -295,6 +303,14 @@ struct rxfcb {
#define RSTAT_RXF __PPCBITS(24,31)
#define RSTAT_RXFn(n) (RSTAT_RXF0 >> (n))
#define RXIC 0x310 /* Receive interrupt coalescing register */
+#define RXIC_ICEN __PPCBIT(0) /* Interrupt coalescing enable */
+#define RXIC_ICCS __PPCBIT(1) /* Interrupt coalescing timer clock source */
+#define RXIC_ICCS_ETSEC 0 /* eTSEC Rx interface clocks */
+#define RXIC_ICCS_SYSTEM TXIC_ICCS /* system clocks */
+#define RXIC_ICFT __PPCBITS(3,10)
+#define RXIC_ICFT_SET(n) __SHIFTIN((n),TXIC_ICFT)
+#define RXIC_ICTT __PPCBITS(16,31)
+#define RXIC_ICTT_SET(n) __SHIFTIN((n),TXIC_ICTT)
#define RQUEUE 0x314 /* Receive queue control register. [TSEC3] */
#define RQUEUE_EX0 __PPCBIT(8) /* data transferred by DMA to ring extracted according to ATTR register */
#define RQUEUE_EX1 __PPCBIT(9)