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)

Reply via email to