Module Name:    src
Committed By:   msaitoh
Date:           Tue Oct 16 19:49:41 UTC 2012

Modified Files:
        src/sys/dev/marvell: if_mvgbe.c mvgbereg.h

Log Message:
Add code to modify interrupt coalescing with sysctl.
 - both TX side an RX side.
 - different setting for each port
 - TX side is hw.mvgbe.mvgbe*.ipginttx
 - RX side is hw.mvgbe.mvgbe*.ipgintrx
 - The default value is 768.
 - The lowest value is 0
 - For highest value, 0x3777 is used for V1, and 0xffff is used for V2.


To generate a diff of this commit:
cvs rdiff -u -r1.24 -r1.25 src/sys/dev/marvell/if_mvgbe.c
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/marvell/mvgbereg.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/dev/marvell/if_mvgbe.c
diff -u src/sys/dev/marvell/if_mvgbe.c:1.24 src/sys/dev/marvell/if_mvgbe.c:1.25
--- src/sys/dev/marvell/if_mvgbe.c:1.24	Sun Oct 14 19:17:08 2012
+++ src/sys/dev/marvell/if_mvgbe.c	Tue Oct 16 19:49:41 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_mvgbe.c,v 1.24 2012/10/14 19:17:08 msaitoh Exp $	*/
+/*	$NetBSD: if_mvgbe.c,v 1.25 2012/10/16 19:49:41 msaitoh Exp $	*/
 /*
  * Copyright (c) 2007, 2008 KIYOHARA Takashi
  * All rights reserved.
@@ -25,7 +25,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.24 2012/10/14 19:17:08 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.25 2012/10/16 19:49:41 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -35,6 +35,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v
 #include <sys/kmem.h>
 #include <sys/mutex.h>
 #include <sys/sockio.h>
+#include <sys/sysctl.h>
 
 #include <dev/marvell/marvellreg.h>
 #include <dev/marvell/marvellvar.h>
@@ -137,6 +138,8 @@ do {									\
 	    MVGBE_CDRXOFF((x)), sizeof(struct mvgbe_rx_desc), (ops));	\
 	} while (/*CONSTCOND*/0)
 
+#define MVGBE_IPGINTTX_DEFAULT	768
+#define MVGBE_IPGINTRX_DEFAULT	768
 
 struct mvgbe_jpool_entry {
 	int slot;
@@ -206,7 +209,8 @@ struct mvgbe_softc {
 	struct mvgbe_ring_data *sc_rdata;
 	bus_dmamap_t sc_ring_map;
 	int sc_if_flags;
-	int sc_ipg_rx;
+	unsigned int sc_ipginttx;
+	unsigned int sc_ipgintrx;
 	int sc_wdogsoft;
 
 	LIST_HEAD(__mvgbe_jfreehead, mvgbe_jpool_entry) sc_jfree_listhead;
@@ -214,6 +218,7 @@ struct mvgbe_softc {
 	SIMPLEQ_HEAD(__mvgbe_txmaphead, mvgbe_txmap_entry) sc_txmap_head;
 
 	krndsource_t sc_rnd_source;
+	struct sysctllog *mvgbe_clog;
 };
 
 
@@ -264,7 +269,11 @@ static void mvgbe_filter_setup(struct mv
 #ifdef MVGBE_DEBUG
 static void mvgbe_dump_txdesc(struct mvgbe_tx_desc *, int);
 #endif
-static uint32_t mvgbe_ipg_rx(struct mvgbec_softc *, struct mvgbe_softc *);
+static int mvgbe_ipginttx(struct mvgbec_softc *, struct mvgbe_softc *, unsigned int);
+static int mvgbe_ipgintrx(struct mvgbec_softc *, struct mvgbe_softc *, unsigned int);
+static void sysctl_mvgbe_init(struct mvgbe_softc *);
+static int mvgbe_sysctl_ipginttx(SYSCTLFN_PROTO);
+static int mvgbe_sysctl_ipgintrx(SYSCTLFN_PROTO);
 
 CFATTACH_DECL_NEW(mvgbec_gt, sizeof(struct mvgbec_softc),
     mvgbec_match, mvgbec_attach, NULL, NULL);
@@ -275,6 +284,7 @@ CFATTACH_DECL_NEW(mvgbe, sizeof(struct m
     mvgbe_match, mvgbe_attach, NULL, NULL);
 
 device_t mvgbec0 = NULL;
+static int mvgbe_root_num;
 
 struct mvgbe_port {
 	int model;
@@ -785,6 +795,7 @@ mvgbe_attach(device_t parent, device_t s
 	ether_ifattach(ifp, sc->sc_enaddr);
 	ether_set_ifflags_cb(&sc->sc_ethercom, mvgbe_ifflags_cb);
 
+	sysctl_mvgbe_init(sc);
 	rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev),
 	    RND_TYPE_NET, 0);
 
@@ -805,17 +816,50 @@ fail1:
 	return;
 }
 
-static uint32_t
-mvgbe_ipg_rx(struct mvgbec_softc *csc, struct mvgbe_softc *sc)
+static int
+mvgbe_ipginttx(struct mvgbec_softc *csc, struct mvgbe_softc *sc,
+    unsigned int ipginttx)
 {
+	uint32_t reg;
+	reg = MVGBE_READ(sc, MVGBE_PTFUT);
 
-	if (csc->sc_flags & FLAGS_IPG2)
-		return (((sc->sc_ipg_rx & 0x8000) << 10) |
-			((sc->sc_ipg_rx & 0x7fff) << 7));
-	else if (csc->sc_flags & FLAGS_IPG1)
-		return ((sc->sc_ipg_rx & 0x3fff) << 8);
-	else
-		return 0;
+	if (csc->sc_flags & FLAGS_IPG2) {
+		if (ipginttx > MVGBE_PTFUT_IPGINTTX_V2_MAX)
+			return -1;
+		reg &= ~MVGBE_PTFUT_IPGINTTX_V2_MASK;
+		reg |= MVGBE_PTFUT_IPGINTTX_V2(ipginttx);
+	} else if (csc->sc_flags & FLAGS_IPG1) {
+		if (ipginttx > MVGBE_PTFUT_IPGINTTX_V1_MAX)
+			return -1;
+		reg &= ~MVGBE_PTFUT_IPGINTTX_V1_MASK;
+		reg |= MVGBE_PTFUT_IPGINTTX_V1(ipginttx);
+	}
+	MVGBE_WRITE(sc, MVGBE_PTFUT, reg);
+
+	return 0;
+}
+
+static int
+mvgbe_ipgintrx(struct mvgbec_softc *csc, struct mvgbe_softc *sc,
+    unsigned int ipgintrx)
+{
+	uint32_t reg;
+	reg = MVGBE_READ(sc, MVGBE_SDC);
+
+	if (csc->sc_flags & FLAGS_IPG2) {
+		if (ipgintrx > MVGBE_SDC_IPGINTRX_V2_MAX)
+			return -1;
+		reg &= ~MVGBE_SDC_IPGINTRX_V2_MASK;
+		reg |= MVGBE_SDC_IPGINTRX_V2(ipgintrx);
+	} else if (csc->sc_flags & FLAGS_IPG1) {
+		if (ipgintrx > MVGBE_SDC_IPGINTRX_V1_MAX)
+			return -1;
+		reg &= ~MVGBE_SDC_IPGINTRX_V1_MASK;
+		reg |= MVGBE_SDC_IPGINTRX_V1(ipgintrx);
+	}
+	MVGBE_WRITE(sc, MVGBE_SDC, reg);
+
+	return 0;
 }
 
 static int
@@ -957,9 +1001,6 @@ mvgbe_ioctl(struct ifnet *ifp, u_long cm
 	return error;
 }
 
-int mvgbe_rximt = 0;
-int mvgbe_tximt = 0;
-
 static int
 mvgbe_init(struct ifnet *ifp)
 {
@@ -990,8 +1031,10 @@ mvgbe_init(struct ifnet *ifp)
 		return ENOBUFS;
 	}
 
-	if ((csc->sc_flags & FLAGS_IPG1) || (csc->sc_flags & FLAGS_IPG2))
-		sc->sc_ipg_rx = 768;
+	if ((csc->sc_flags & FLAGS_IPG1) || (csc->sc_flags & FLAGS_IPG2)) {
+		sc->sc_ipginttx = MVGBE_IPGINTTX_DEFAULT;
+		sc->sc_ipgintrx = MVGBE_IPGINTRX_DEFAULT;
+	}
 	if (csc->sc_flags & FLAGS_FIX_MTU)
 		MVGBE_WRITE(sc, MVGBE_MTU, 0);	/* hw reset value is wrong */
 	MVGBE_WRITE(sc, MVGBE_PSC,
@@ -1030,16 +1073,21 @@ mvgbe_init(struct ifnet *ifp)
 
 	MVGBE_WRITE(sc, MVGBE_PXC, MVGBE_PXC_RXCS);
 	MVGBE_WRITE(sc, MVGBE_PXCX, 0);
+
+	/* Set SDC register except IPGINT bits */
 	MVGBE_WRITE(sc, MVGBE_SDC,
-	    mvgbe_ipg_rx(csc, sc) |
 	    MVGBE_SDC_RXBSZ_16_64BITWORDS |
 #if BYTE_ORDER == LITTLE_ENDIAN
 	    MVGBE_SDC_BLMR |	/* Big/Little Endian Receive Mode: No swap */
 	    MVGBE_SDC_BLMT |	/* Big/Little Endian Transmit Mode: No swap */
 #endif
-	    MVGBE_SDC_IPGINTRX(mvgbe_rximt) |
 	    MVGBE_SDC_TXBSZ_16_64BITWORDS);
-	MVGBE_WRITE(sc, MVGBE_PTFUT, MVGBE_PTFUT_IPGINTTX(mvgbe_tximt));
+	/* And then set IPGINT bits */
+	mvgbe_ipgintrx(csc, sc, sc->sc_ipgintrx);
+
+	/* Tx side */
+	MVGBE_WRITE(sc, MVGBE_PTFUT, 0);
+	mvgbe_ipginttx(csc, sc, sc->sc_ipginttx);
 
 	mvgbe_filter_setup(sc);
 
@@ -2011,3 +2059,123 @@ mvgbe_dump_txdesc(struct mvgbe_tx_desc *
 #undef DESC_PRINT
 }
 #endif
+
+SYSCTL_SETUP(sysctl_mvgbe, "sysctl mvgbe subtree setup")
+{
+	int rc;
+	const struct sysctlnode *node;
+
+	if ((rc = sysctl_createv(clog, 0, NULL, NULL,
+	    0, CTLTYPE_NODE, "hw", NULL,
+	    NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) {
+		goto err;
+	}
+
+	if ((rc = sysctl_createv(clog, 0, NULL, &node,
+	    0, CTLTYPE_NODE, "mvgbe",
+	    SYSCTL_DESCR("mvgbe interface controls"),
+	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
+		goto err;
+	}
+
+	mvgbe_root_num = node->sysctl_num;
+	return;
+
+err:
+	aprint_error("%s: syctl_createv failed (rc = %d)\n", __func__, rc);
+}
+
+static void
+sysctl_mvgbe_init(struct mvgbe_softc *sc)
+{
+	const struct sysctlnode *node;
+	int mvgbe_nodenum;
+
+	if (sysctl_createv(&sc->mvgbe_clog, 0, NULL, &node,
+		0, CTLTYPE_NODE, device_xname(sc->sc_dev),
+		SYSCTL_DESCR("mvgbe per-controller controls"),
+		NULL, 0, NULL, 0, CTL_HW, mvgbe_root_num, CTL_CREATE,
+		CTL_EOL) != 0) {
+		aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n");
+		return;
+	}
+	mvgbe_nodenum = node->sysctl_num;
+
+	/* interrupt moderation sysctls */
+	if (sysctl_createv(&sc->mvgbe_clog, 0, NULL, &node,
+		CTLFLAG_READWRITE, CTLTYPE_INT, "ipginttx",
+		SYSCTL_DESCR("mvgbe TX interrupt moderation timer"),
+		mvgbe_sysctl_ipginttx, 0, (void *)sc,
+		0, CTL_HW, mvgbe_root_num, mvgbe_nodenum, CTL_CREATE,
+		CTL_EOL) != 0) {
+		aprint_normal_dev(sc->sc_dev,
+		    "couldn't create ipginttx sysctl node\n");
+	}
+	if (sysctl_createv(&sc->mvgbe_clog, 0, NULL, &node,
+		CTLFLAG_READWRITE, CTLTYPE_INT, "ipgintrx",
+		SYSCTL_DESCR("mvgbe RX interrupt moderation timer"),
+		mvgbe_sysctl_ipgintrx, 0, (void *)sc,
+		0, CTL_HW, mvgbe_root_num, mvgbe_nodenum, CTL_CREATE,
+		CTL_EOL) != 0) {
+		aprint_normal_dev(sc->sc_dev,
+		    "couldn't create ipginttx sysctl node\n");
+	}
+}
+
+static int
+mvgbe_sysctl_ipginttx(SYSCTLFN_ARGS)
+{
+	int error;
+	unsigned int t;
+	struct sysctlnode node;
+	struct mvgbec_softc *csc;
+	struct mvgbe_softc *sc;
+
+	node = *rnode;
+	sc = node.sysctl_data;
+	csc = device_private(device_parent(sc->sc_dev));
+	t = sc->sc_ipginttx;
+	node.sysctl_data = &t;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	if (mvgbe_ipginttx(csc, sc, t) < 0)
+		return EINVAL;
+	/*
+	 * update the softc with sysctl-changed value, and mark
+	 * for hardware update
+	 */
+	sc->sc_ipginttx = t;
+
+	return 0;
+}
+
+static int
+mvgbe_sysctl_ipgintrx(SYSCTLFN_ARGS)
+{
+	int error;
+	unsigned int t;
+	struct sysctlnode node;
+	struct mvgbec_softc *csc;
+	struct mvgbe_softc *sc;
+
+	node = *rnode;
+	sc = node.sysctl_data;
+	csc = device_private(device_parent(sc->sc_dev));
+	t = sc->sc_ipgintrx;
+	node.sysctl_data = &t;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	if (mvgbe_ipgintrx(csc, sc, t) < 0)
+		return EINVAL;
+	/*
+	 * update the softc with sysctl-changed value, and mark
+	 * for hardware update
+	 */
+	sc->sc_ipgintrx = t;
+
+	return 0;
+}

Index: src/sys/dev/marvell/mvgbereg.h
diff -u src/sys/dev/marvell/mvgbereg.h:1.5 src/sys/dev/marvell/mvgbereg.h:1.6
--- src/sys/dev/marvell/mvgbereg.h:1.5	Fri Oct 12 10:38:06 2012
+++ src/sys/dev/marvell/mvgbereg.h	Tue Oct 16 19:49:41 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mvgbereg.h,v 1.5 2012/10/12 10:38:06 msaitoh Exp $	*/
+/*	$NetBSD: mvgbereg.h,v 1.6 2012/10/16 19:49:41 msaitoh Exp $	*/
 /*
  * Copyright (c) 2007 KIYOHARA Takashi
  * All rights reserved.
@@ -34,9 +34,6 @@
 
 #define MVGBE_PHY_TIMEOUT	10000	/* msec */
 
-#define MVGBE_RX_CSUM_MIN_BYTE	72
-
-
 /*
  * Ethernet Unit Registers
  */
@@ -236,8 +233,14 @@
 #define MVGBE_SDC_BLMR			(1 << 4)
 #define MVGBE_SDC_BLMT			(1 << 5)
 #define MVGBE_SDC_SWAPMODE		(1 << 6)
-#define MVGBE_SDC_IPGINTRX_MASK		__BITS(21, 8)
-#define MVGBE_SDC_IPGINTRX(x)		__SHIFTIN(x, MVGBE_SDC_IPGINTRX_MASK)
+#define MVGBE_SDC_IPGINTRX_V1_MASK	__BITS(21, 8)
+#define MVGBE_SDC_IPGINTRX_V2_MASK	(__BIT(25) | __BITS(21, 7))
+#define MVGBE_SDC_IPGINTRX_V1(x)	(((x) << 4)			\
+						& MVGBE_SDC_IPGINTRX_V1_MASK)
+#define MVGBE_SDC_IPGINTRX_V2(x)	((((x) & 0x8000) << 10) 	\
+						| (((x) & 0x7fff) << 7))
+#define MVGBE_SDC_IPGINTRX_V1_MAX	0x3fff
+#define MVGBE_SDC_IPGINTRX_V2_MAX	0xffff
 #define MVGBE_SDC_TXBSZ(x)		((x) << 22)
 #define MVGBE_SDC_TXBSZ_MASK		MVGBE_SDC_TXBSZ(7)
 #define MVGBE_SDC_TXBSZ_1_64BITWORDS	MVGBE_SDC_TXBSZ(0)
@@ -311,8 +314,12 @@
 #define MVGBE_ICE_ETHERINTSUM		(1 << 31)
 
 /* Port Tx FIFO Urgent Threshold (MVGBE_PTFUT) */
-#define MVGBE_PTFUT_IPGINTTX_MASK	__BITS(17, 4)
-#define MVGBE_PTFUT_IPGINTTX(x)		__SHIFTIN(x, MVGBE_PTFUT_IPGINTTX_MASK)
+#define MVGBE_PTFUT_IPGINTTX_V1_MASK	__BITS(17, 4)
+#define MVGBE_PTFUT_IPGINTTX_V2_MASK	__BITS(19, 4)
+#define MVGBE_PTFUT_IPGINTTX_V1(x)   __SHIFTIN(x, MVGBE_PTFUT_IPGINTTX_V1_MASK)
+#define MVGBE_PTFUT_IPGINTTX_V2(x)   __SHIFTIN(x, MVGBE_PTFUT_IPGINTTX_V2_MASK)
+#define MVGBE_PTFUT_IPGINTTX_V1_MAX	0x3fff
+#define MVGBE_PTFUT_IPGINTTX_V2_MAX	0xffff
 
 /* Port Rx Minimal Frame Size (MVGBE_PMFS) */
 #define MVGBE_PMFS_RXMFS(rxmfs)		(((rxmfs) - 40) & 0x7c)

Reply via email to