From 09f49d522029d6a76976f2a91fca9e9260ec0c03 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sat, 22 Sep 2012 21:45:43 +0800 Subject: [PATCH] emx: Allow user to specify RX/TX processing CPU's offset --- sys/dev/netif/emx/if_emx.c | 129 ++++++++++++++++++++++++++++++++++--- sys/dev/netif/emx/if_emx.h | 3 + 2 files changed, 123 insertions(+), 9 deletions(-) diff --git a/sys/dev/netif/emx/if_emx.c b/sys/dev/netif/emx/if_emx.c index c9c95cda32..efb709bcb1 100644 --- a/sys/dev/netif/emx/if_emx.c +++ b/sys/dev/netif/emx/if_emx.c @@ -242,6 +242,10 @@ static int emx_sysctl_stats(SYSCTL_HANDLER_ARGS); static int emx_sysctl_debug_info(SYSCTL_HANDLER_ARGS); static int emx_sysctl_int_throttle(SYSCTL_HANDLER_ARGS); static int emx_sysctl_int_tx_nsegs(SYSCTL_HANDLER_ARGS); +#ifdef IFPOLL_ENABLE +static int emx_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS); +static int emx_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS); +#endif static void emx_add_sysctl(struct emx_softc *); static void emx_serialize_skipmain(struct emx_softc *); @@ -413,6 +417,9 @@ emx_attach(device_t dev) u_int intr_flags; uint16_t eeprom_data, device_id, apme_mask; driver_intr_t *intr_func; +#ifdef IFPOLL_ENABLE + int offset, offset_def; +#endif lwkt_serialize_init(&sc->main_serialize); lwkt_serialize_init(&sc->tx_serialize); @@ -689,6 +696,37 @@ emx_attach(device_t dev) /* XXX disable wol */ sc->wol = 0; +#ifdef IFPOLL_ENABLE + /* + * NPOLLING RX CPU offset + */ + if (sc->rx_ring_cnt == ncpus2) { + offset = 0; + } else { + offset_def = (sc->rx_ring_cnt * device_get_unit(dev)) % ncpus2; + offset = device_getenv_int(dev, "npoll.rxoff", offset_def); + if (offset >= ncpus2 || + offset % sc->rx_ring_cnt != 0) { + device_printf(dev, "invalid npoll.rxoff %d, use %d\n", + offset, offset_def); + offset = offset_def; + } + } + sc->rx_npoll_off = offset; + + /* + * NPOLLING TX CPU offset + */ + offset_def = sc->rx_npoll_off; + 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->tx_npoll_off = offset; +#endif + /* Setup OS specific network interface */ emx_setup_ifp(sc); @@ -3406,6 +3444,17 @@ emx_add_sysctl(struct emx_softc *sc) OID_AUTO, "rx_ring_cnt", CTLFLAG_RD, &sc->rx_ring_cnt, 0, "RX ring count"); +#ifdef IFPOLL_ENABLE + SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), + OID_AUTO, "npoll_rxoff", CTLTYPE_INT|CTLFLAG_RW, + sc, 0, emx_sysctl_npoll_rxoff, "I", + "NPOLLING RX cpu offset"); + SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), + OID_AUTO, "npoll_txoff", CTLTYPE_INT|CTLFLAG_RW, + sc, 0, emx_sysctl_npoll_txoff, "I", + "NPOLLING TX cpu offset"); +#endif + #ifdef EMX_RSS_DEBUG SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, "rss_debug", CTLFLAG_RW, &sc->rss_debug, @@ -3502,6 +3551,62 @@ emx_sysctl_int_tx_nsegs(SYSCTL_HANDLER_ARGS) return error; } +#ifdef IFPOLL_ENABLE + +static int +emx_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS) +{ + struct emx_softc *sc = (void *)arg1; + struct ifnet *ifp = &sc->arpcom.ac_if; + int error, off; + + off = sc->rx_npoll_off; + 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->rx_ring_cnt != 0) { + error = EINVAL; + } else { + error = 0; + sc->rx_npoll_off = off; + } + ifnet_deserialize_all(ifp); + + return error; +} + +static int +emx_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS) +{ + struct emx_softc *sc = (void *)arg1; + struct ifnet *ifp = &sc->arpcom.ac_if; + int error, off; + + off = sc->tx_npoll_off; + 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->tx_npoll_off = off; + } + ifnet_deserialize_all(ifp); + + return error; +} + +#endif /* IFPOLL_ENABLE */ + static int emx_dma_alloc(struct emx_softc *sc) { @@ -3663,25 +3768,31 @@ emx_npoll(struct ifnet *ifp, struct ifpoll_info *info) ASSERT_IFNET_SERIALIZED_ALL(ifp); if (info) { - int i; + int i, off; info->ifpi_status.status_func = emx_npoll_status; info->ifpi_status.serializer = &sc->main_serialize; - info->ifpi_tx[0].poll_func = emx_npoll_tx; - info->ifpi_tx[0].arg = NULL; - info->ifpi_tx[0].serializer = &sc->tx_serialize; + off = sc->tx_npoll_off; + KKASSERT(off < ncpus2); + info->ifpi_tx[off].poll_func = emx_npoll_tx; + info->ifpi_tx[off].arg = NULL; + info->ifpi_tx[off].serializer = &sc->tx_serialize; + off = sc->rx_npoll_off; for (i = 0; i < sc->rx_ring_cnt; ++i) { - info->ifpi_rx[i].poll_func = emx_npoll_rx; - info->ifpi_rx[i].arg = &sc->rx_data[i]; - info->ifpi_rx[i].serializer = - &sc->rx_data[i].rx_serialize; + struct emx_rxdata *rdata = &sc->rx_data[i]; + int idx = i + off; + + KKASSERT(idx < ncpus2); + info->ifpi_rx[idx].poll_func = emx_npoll_rx; + info->ifpi_rx[idx].arg = rdata; + info->ifpi_rx[idx].serializer = &rdata->rx_serialize; } if (ifp->if_flags & IFF_RUNNING) emx_disable_intr(sc); - ifp->if_npoll_cpuid = 0; /* XXX */ + ifp->if_npoll_cpuid = sc->tx_npoll_off; } else { if (ifp->if_flags & IFF_RUNNING) emx_enable_intr(sc); diff --git a/sys/dev/netif/emx/if_emx.h b/sys/dev/netif/emx/if_emx.h index d57e4c928e..7f913f7517 100644 --- a/sys/dev/netif/emx/if_emx.h +++ b/sys/dev/netif/emx/if_emx.h @@ -276,6 +276,9 @@ struct emx_softc { uint32_t smartspeed; int int_throttle_ceil; + int rx_npoll_off; + int tx_npoll_off; + struct lwkt_serialize main_serialize; struct lwkt_serialize tx_serialize; struct lwkt_serialize *serializes[EMX_NSERIALIZE]; -- 2.41.0