Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/powerpc Added Interrupt coalescing support.



details:   https://anonhg.NetBSD.org/src/rev/e5edd265ffb7
branches:  trunk
changeset: 806339:e5edd265ffb7
user:      nonaka <nonaka%NetBSD.org@localhost>
date:      Tue Feb 17 01:53:21 2015 +0000

description:
Added Interrupt coalescing support.

diffstat:

 sys/arch/powerpc/booke/dev/pq3etsec.c     |  220 +++++++++++++++++++++++++++++-
 sys/arch/powerpc/include/booke/etsecreg.h |   18 ++-
 2 files changed, 233 insertions(+), 5 deletions(-)

diffs (truncated from 321 to 300 lines):

diff -r 968e0972ad54 -r e5edd265ffb7 sys/arch/powerpc/booke/dev/pq3etsec.c
--- a/sys/arch/powerpc/booke/dev/pq3etsec.c     Mon Feb 16 22:50:02 2015 +0000
+++ b/sys/arch/powerpc/booke/dev/pq3etsec.c     Tue Feb 17 01:53:21 2015 +0000
@@ -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 @@
 #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 @@
 #endif
 #include <netinet6/in6_offload.h>
 
-
 #include <powerpc/spr.h>
 #include <powerpc/booke/spr.h>
 
@@ -232,8 +232,19 @@
        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_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 @@
        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 @@
         * 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 @@
 #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");
+}
diff -r 968e0972ad54 -r e5edd265ffb7 sys/arch/powerpc/include/booke/etsecreg.h
--- a/sys/arch/powerpc/include/booke/etsecreg.h Mon Feb 16 22:50:02 2015 +0000
+++ b/sys/arch/powerpc/include/booke/etsecreg.h Tue Feb 17 01:53:21 2015 +0000
@@ -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 @@
 #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)



Home | Main Index | Thread Index | Old Index