jme: Change polling(4) support to ifpoll support
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 24 Sep 2012 12:01:17 +0000 (20:01 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 30 Sep 2012 14:41:18 +0000 (22:41 +0800)
While I'm here, fix the disable/enable intr handing.

sys/dev/netif/jme/Makefile
sys/dev/netif/jme/if_jme.c
sys/dev/netif/jme/if_jmevar.h

index fd14660..7d832b3 100644 (file)
@@ -3,15 +3,15 @@
 KMOD=  if_jme
 SRCS=  if_jme.c
 SRCS+= miibus_if.h device_if.h bus_if.h pci_if.h
-SRCS+= opt_polling.h opt_jme.h
+SRCS+= opt_ifpoll.h opt_jme.h
 
 .ifndef BUILDING_WITH_KERNEL
 
-opt_polling.h:
-       echo '#define DEVICE_POLLING 1' > ${.OBJDIR}/${.TARGET}
+opt_ifpoll.h:
+       touch ${.OBJDIR}/${.TARGET}
 
 opt_jme.h:
-       echo '#define JME_RSS_DEBUG 1' > ${.OBJDIR}/${.TARGET}
+       touch ${.OBJDIR}/${.TARGET}
 
 .endif
 
index 157057b..d360ccf 100644 (file)
@@ -27,7 +27,7 @@
  * $FreeBSD: src/sys/dev/jme/if_jme.c,v 1.2 2008/07/18 04:20:48 yongari Exp $
  */
 
-#include "opt_polling.h"
+#include "opt_ifpoll.h"
 #include "opt_jme.h"
 
 #include <sys/param.h>
@@ -50,6 +50,7 @@
 #include <net/if_arp.h>
 #include <net/if_dl.h>
 #include <net/if_media.h>
+#include <net/if_poll.h>
 #include <net/ifq_var.h>
 #include <net/toeplitz.h>
 #include <net/toeplitz2.h>
@@ -103,8 +104,8 @@ static void jme_start(struct ifnet *);
 static void    jme_watchdog(struct ifnet *);
 static void    jme_mediastatus(struct ifnet *, struct ifmediareq *);
 static int     jme_mediachange(struct ifnet *);
-#ifdef DEVICE_POLLING
-static void    jme_poll(struct ifnet *, enum poll_cmd, int);
+#ifdef IFPOLL_ENABLE
+static void    jme_npoll(struct ifnet *, struct ifpoll_info *);
 #endif
 static void    jme_serialize(struct ifnet *, enum ifnet_serialize);
 static void    jme_deserialize(struct ifnet *, enum ifnet_serialize);
@@ -120,6 +121,8 @@ static void jme_msix_rx(void *);
 static void    jme_txeof(struct jme_softc *);
 static void    jme_rxeof(struct jme_rxdata *, int);
 static void    jme_rx_intr(struct jme_softc *, uint32_t);
+static void    jme_enable_intr(struct jme_softc *);
+static void    jme_disable_intr(struct jme_softc *);
 
 static int     jme_msix_setup(device_t);
 static void    jme_msix_teardown(device_t, int);
@@ -169,6 +172,10 @@ static int jme_sysctl_tx_coal_to(SYSCTL_HANDLER_ARGS);
 static int     jme_sysctl_tx_coal_pkt(SYSCTL_HANDLER_ARGS);
 static int     jme_sysctl_rx_coal_to(SYSCTL_HANDLER_ARGS);
 static int     jme_sysctl_rx_coal_pkt(SYSCTL_HANDLER_ARGS);
+#ifdef IFPOLL_ENABLE
+static int     jme_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS);
+static int     jme_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS);
+#endif
 
 /*
  * Devices supported by this driver.
@@ -468,8 +475,8 @@ jme_miibus_statchg(device_t dev)
        ifp->if_flags &= ~IFF_OACTIVE;
        callout_reset(&sc->jme_tick_ch, hz, jme_tick, sc);
 
-#ifdef DEVICE_POLLING
-       if (!(ifp->if_flags & IFF_POLLING))
+#ifdef IFPOLL_ENABLE
+       if (!(ifp->if_flags & IFF_NPOLLING))
 #endif
        /* Reenable interrupts. */
        CSR_WRITE_4(sc, JME_INTR_MASK_SET, JME_INTRS);
@@ -661,6 +668,9 @@ jme_attach(device_t dev)
        uint8_t pcie_ptr, rev;
        int error = 0, i, j, rx_desc_cnt;
        uint8_t eaddr[ETHER_ADDR_LEN];
+#ifdef IFPOLL_ENABLE
+       int offset, offset_def;
+#endif
 
        lwkt_serialize_init(&sc->jme_serialize);
        lwkt_serialize_init(&sc->jme_cdata.jme_tx_serialize);
@@ -879,6 +889,38 @@ jme_attach(device_t dev)
                sc->jme_caps |= JME_CAP_PMCAP;
 #endif
 
+#ifdef IFPOLL_ENABLE
+       /*
+        * NPOLLING RX CPU offset
+        */
+       if (sc->jme_cdata.jme_rx_ring_cnt == ncpus2) {
+               offset = 0;
+       } else {
+               offset_def = (sc->jme_cdata.jme_rx_ring_cnt *
+                   device_get_unit(dev)) % ncpus2;
+               offset = device_getenv_int(dev, "npoll.rxoff", offset_def);
+               if (offset >= ncpus2 ||
+                   offset % sc->jme_cdata.jme_rx_ring_cnt != 0) {
+                       device_printf(dev, "invalid npoll.rxoff %d, use %d\n",
+                           offset, offset_def);
+                       offset = offset_def;
+               }
+       }
+       sc->jme_npoll_rxoff = offset;
+
+       /*
+        * NPOLLING TX CPU offset
+        */
+       offset_def = sc->jme_npoll_rxoff;
+       offset = device_getenv_int(dev, "npoll.txoff", offset_def);
+       if (offset >= ncpus2) {
+               device_printf(dev, "invalid npoll.txoff %d, use %d\n",
+                   offset, offset_def);
+               offset = offset_def;
+       }
+       sc->jme_npoll_txoff = offset;
+#endif
+
        /*
         * Create sysctl tree
         */
@@ -894,8 +936,8 @@ jme_attach(device_t dev)
        ifp->if_init = jme_init;
        ifp->if_ioctl = jme_ioctl;
        ifp->if_start = jme_start;
-#ifdef DEVICE_POLLING
-       ifp->if_poll = jme_poll;
+#ifdef IFPOLL_ENABLE
+       ifp->if_npoll = jme_npoll;
 #endif
        ifp->if_watchdog = jme_watchdog;
        ifp->if_serialize = jme_serialize;
@@ -1067,6 +1109,7 @@ jme_sysctl_node(struct jme_softc *sc)
                       "rx_ring_count", CTLFLAG_RD,
                       &sc->jme_cdata.jme_rx_ring_cnt,
                       0, "RX ring count");
+
 #ifdef JME_RSS_DEBUG
        SYSCTL_ADD_INT(&sc->jme_sysctl_ctx,
                       SYSCTL_CHILDREN(sc->jme_sysctl_tree), OID_AUTO,
@@ -1092,6 +1135,17 @@ jme_sysctl_node(struct jme_softc *sc)
        }
 #endif
 
+#ifdef IFPOLL_ENABLE
+       SYSCTL_ADD_PROC(&sc->jme_sysctl_ctx,
+           SYSCTL_CHILDREN(sc->jme_sysctl_tree), OID_AUTO,
+           "npoll_rxoff", CTLTYPE_INT|CTLFLAG_RW, sc, 0,
+           jme_sysctl_npoll_rxoff, "I", "NPOLLING RX cpu offset");
+       SYSCTL_ADD_PROC(&sc->jme_sysctl_ctx,
+           SYSCTL_CHILDREN(sc->jme_sysctl_tree), OID_AUTO,
+           "npoll_txoff", CTLTYPE_INT|CTLFLAG_RW, sc, 0,
+           jme_sysctl_npoll_txoff, "I", "NPOLLING TX cpu offset");
+#endif
+
        /*
         * Set default coalesce valves
         */
@@ -2389,7 +2443,7 @@ jme_rxeof(struct jme_rxdata *rdata, int count)
        int nsegs, pktlen;
 
        for (;;) {
-#ifdef DEVICE_POLLING
+#ifdef IFPOLL_ENABLE
                if (count >= 0 && count-- == 0)
                        break;
 #endif
@@ -2754,11 +2808,11 @@ jme_init(void *xsc)
            ((TXTRHD_RT_LIMIT_DEFAULT << TXTRHD_RT_LIMIT_SHIFT) &
            TXTRHD_RT_LIMIT_SHIFT));
 
-#ifdef DEVICE_POLLING
-       if (!(ifp->if_flags & IFF_POLLING))
+#ifdef IFPOLL_ENABLE
+       if (!(ifp->if_flags & IFF_NPOLLING))
 #endif
        /* Initialize the interrupt mask. */
-       CSR_WRITE_4(sc, JME_INTR_MASK_SET, JME_INTRS);
+       jme_enable_intr(sc);
        CSR_WRITE_4(sc, JME_INTR_STATUS, 0xFFFFFFFF);
 
        /*
@@ -2800,7 +2854,7 @@ jme_stop(struct jme_softc *sc)
        /*
         * Disable interrupts.
         */
-       CSR_WRITE_4(sc, JME_INTR_MASK_CLR, JME_INTRS);
+       jme_disable_intr(sc);
        CSR_WRITE_4(sc, JME_INTR_STATUS, 0xFFFFFFFF);
 
        /* Disable updating shadow status block. */
@@ -3207,55 +3261,155 @@ jme_set_rx_coal(struct jme_softc *sc)
                CSR_WRITE_4(sc, JME_PCCRX(r), reg);
 }
 
-#ifdef DEVICE_POLLING
+#ifdef IFPOLL_ENABLE
 
 static void
-jme_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+jme_npoll_status(struct ifnet *ifp, int pollhz __unused)
 {
        struct jme_softc *sc = ifp->if_softc;
        uint32_t status;
-       int r;
 
        ASSERT_SERIALIZED(&sc->jme_serialize);
 
-       switch (cmd) {
-       case POLL_REGISTER:
-               CSR_WRITE_4(sc, JME_INTR_MASK_CLR, JME_INTRS);
-               break;
+       status = CSR_READ_4(sc, JME_INTR_STATUS);
+       if (status & INTR_RXQ_DESC_EMPTY) {
+               int i;
 
-       case POLL_DEREGISTER:
-               CSR_WRITE_4(sc, JME_INTR_MASK_SET, JME_INTRS);
-               break;
+               for (i = 0; i < sc->jme_cdata.jme_rx_ring_cnt; ++i) {
+                       struct jme_rxdata *rdata =
+                           &sc->jme_cdata.jme_rx_data[i];
 
-       case POLL_AND_CHECK_STATUS:
-       case POLL_ONLY:
-               status = CSR_READ_4(sc, JME_INTR_STATUS);
+                       if (status & rdata->jme_rx_empty) {
+                               lwkt_serialize_enter(&rdata->jme_rx_serialize);
+                               jme_rxeof(rdata, -1);
+#ifdef JME_RSS_DEBUG
+                               rdata->jme_rx_emp++;
+#endif
+                               lwkt_serialize_exit(&rdata->jme_rx_serialize);
+                       }
+               }
+               CSR_WRITE_4(sc, JME_INTR_STATUS, status);
+               CSR_WRITE_4(sc, JME_RXCSR, sc->jme_rxcsr |
+                   RXCSR_RX_ENB | RXCSR_RXQ_START);
+       }
+}
 
-               for (r = 0; r < sc->jme_cdata.jme_rx_ring_cnt; ++r) {
+static void
+jme_npoll_rx(struct ifnet *ifp __unused, void *arg, int cycle)
+{
+       struct jme_rxdata *rdata = arg;
+
+       ASSERT_SERIALIZED(&rdata->jme_rx_serialize);
+
+       jme_rxeof(rdata, cycle);
+}
+
+static void
+jme_npoll_tx(struct ifnet *ifp, void *arg __unused, int cycle __unused)
+{
+       struct jme_softc *sc = ifp->if_softc;
+
+       ASSERT_SERIALIZED(&sc->jme_cdata.jme_tx_serialize);
+
+       jme_txeof(sc);
+       if (!ifq_is_empty(&ifp->if_snd))
+               if_devstart(ifp);
+}
+
+static void
+jme_npoll(struct ifnet *ifp, struct ifpoll_info *info)
+{
+       struct jme_softc *sc = ifp->if_softc;
+
+       ASSERT_IFNET_SERIALIZED_ALL(ifp);
+
+       if (info) {
+               int i, off;
+
+               info->ifpi_status.status_func = jme_npoll_status;
+               info->ifpi_status.serializer = &sc->jme_serialize;
+
+               off = sc->jme_npoll_txoff;
+               KKASSERT(off <= ncpus2);
+               info->ifpi_tx[off].poll_func = jme_npoll_tx;
+               info->ifpi_tx[off].arg = NULL;
+               info->ifpi_tx[off].serializer = &sc->jme_cdata.jme_tx_serialize;
+
+               off = sc->jme_npoll_rxoff;
+               for (i = 0; i < sc->jme_cdata.jme_rx_ring_cnt; ++i) {
                        struct jme_rxdata *rdata =
-                           &sc->jme_cdata.jme_rx_data[r];
+                           &sc->jme_cdata.jme_rx_data[i];
+                       int idx = i + off;
 
-                       lwkt_serialize_enter(&rdata->jme_rx_serialize);
-                       jme_rxeof(rdata, count);
-                       lwkt_serialize_exit(&rdata->jme_rx_serialize);
+                       info->ifpi_rx[idx].poll_func = jme_npoll_rx;
+                       info->ifpi_rx[idx].arg = rdata;
+                       info->ifpi_rx[idx].serializer =
+                           &rdata->jme_rx_serialize;
                }
 
-               if (status & INTR_RXQ_DESC_EMPTY) {
-                       CSR_WRITE_4(sc, JME_INTR_STATUS, status);
-                       CSR_WRITE_4(sc, JME_RXCSR, sc->jme_rxcsr |
-                           RXCSR_RX_ENB | RXCSR_RXQ_START);
-               }
+               if (ifp->if_flags & IFF_RUNNING)
+                       jme_disable_intr(sc);
+               ifp->if_npoll_cpuid = sc->jme_npoll_txoff;
+       } else {
+               if (ifp->if_flags & IFF_RUNNING)
+                       jme_enable_intr(sc);
+               ifp->if_npoll_cpuid = -1;
+       }
+}
 
-               lwkt_serialize_enter(&sc->jme_cdata.jme_tx_serialize);
-               jme_txeof(sc);
-               if (!ifq_is_empty(&ifp->if_snd))
-                       if_devstart(ifp);
-               lwkt_serialize_exit(&sc->jme_cdata.jme_tx_serialize);
-               break;
+static int
+jme_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS)
+{
+       struct jme_softc *sc = (void *)arg1;
+       struct ifnet *ifp = &sc->arpcom.ac_if;
+       int error, off;
+
+       off = sc->jme_npoll_rxoff;
+       error = sysctl_handle_int(oidp, &off, 0, req);
+       if (error || req->newptr == NULL)
+               return error;
+       if (off < 0)
+               return EINVAL;
+
+       ifnet_serialize_all(ifp);
+       if (off >= ncpus2 || off % sc->jme_cdata.jme_rx_ring_cnt != 0) {
+               error = EINVAL;
+       } else {
+               error = 0;
+               sc->jme_npoll_rxoff = off;
+       }
+       ifnet_deserialize_all(ifp);
+
+       return error;
+}
+
+static int
+jme_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS)
+{
+       struct jme_softc *sc = (void *)arg1;
+       struct ifnet *ifp = &sc->arpcom.ac_if;
+       int error, off;
+
+       off = sc->jme_npoll_txoff;
+       error = sysctl_handle_int(oidp, &off, 0, req);
+       if (error || req->newptr == NULL)
+               return error;
+       if (off < 0)
+               return EINVAL;
+
+       ifnet_serialize_all(ifp);
+       if (off >= ncpus2) {
+               error = EINVAL;
+       } else {
+               error = 0;
+               sc->jme_npoll_txoff = off;
        }
+       ifnet_deserialize_all(ifp);
+
+       return error;
 }
 
-#endif /* DEVICE_POLLING */
+#endif /* IFPOLL_ENABLE */
 
 static int
 jme_rxring_dma_alloc(struct jme_rxdata *rdata)
@@ -3732,7 +3886,9 @@ jme_msix_rx(void *xrdata)
                if (status & rdata->jme_rx_empty) {
                        CSR_WRITE_4(sc, JME_RXCSR, sc->jme_rxcsr |
                            RXCSR_RX_ENB | RXCSR_RXQ_START);
+#ifdef JME_RSS_DEBUG
                        rdata->jme_rx_emp++;
+#endif
                }
        }
 
@@ -3835,3 +3991,25 @@ jme_deserialize_skipmain(struct jme_softc *sc)
        lwkt_serialize_array_exit(sc->jme_serialize_arr,
            sc->jme_serialize_cnt, 1);
 }
+
+static void
+jme_enable_intr(struct jme_softc *sc)
+{
+       int i;
+
+       for (i = 0; i < sc->jme_serialize_cnt; ++i)
+               lwkt_serialize_handler_enable(sc->jme_serialize_arr[i]);
+
+       CSR_WRITE_4(sc, JME_INTR_MASK_SET, JME_INTRS);
+}
+
+static void
+jme_disable_intr(struct jme_softc *sc)
+{
+       int i;
+
+       CSR_WRITE_4(sc, JME_INTR_MASK_CLR, JME_INTRS);
+
+       for (i = 0; i < sc->jme_serialize_cnt; ++i)
+               lwkt_serialize_handler_disable(sc->jme_serialize_arr[i]);
+}
index b023950..3bd4bc7 100644 (file)
@@ -243,6 +243,9 @@ struct jme_softc {
        uint32_t                jme_msinum[JME_MSINUM_CNT];
        int                     jme_tx_cpuid;
 
+       int                     jme_npoll_rxoff;
+       int                     jme_npoll_txoff;
+
        device_t                jme_miibus;
        int                     jme_phyaddr;
        bus_addr_t              jme_lowaddr;