commit bb35ab5a919cea8e39e67f85e5db0da866775b2c Author: Ryota Ozaki Date: Tue Feb 2 17:51:04 2016 +0900 Tweak API diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c index 15e5033..26667bb 100644 --- a/sys/dev/pci/if_iwm.c +++ b/sys/dev/pci/if_iwm.c @@ -6832,8 +6832,8 @@ iwm_attach(device_t parent, device_t self, void *aux) ether_ifattach(ifp, ic->ic_myaddr); /* XXX */ #endif if_register(ifp); - /* XXX should provide its own softint handler */ - ifp->if_percpuq = if_percpuq_create(if_percpuq_softint, ifp); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); callout_init(&sc->sc_calib_to, 0); callout_setfunc(&sc->sc_calib_to, iwm_calib_timeout, sc); diff --git a/sys/dev/pci/if_rtwn.c b/sys/dev/pci/if_rtwn.c index 6f61bac..5551ebca 100644 --- a/sys/dev/pci/if_rtwn.c +++ b/sys/dev/pci/if_rtwn.c @@ -358,8 +358,8 @@ rtwn_attach(device_t parent, device_t self, void *aux) if_initialize(ifp); ieee80211_ifattach(ic); if_register(ifp); - /* XXX should provide its own softint handler */ - ifp->if_percpuq = if_percpuq_create(if_percpuq_softint, ifp); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); /* override default methods */ ic->ic_newassoc = rtwn_newassoc; diff --git a/sys/dev/pci/if_wm.c b/sys/dev/pci/if_wm.c index 6a19ffe..b9f4b10 100644 --- a/sys/dev/pci/if_wm.c +++ b/sys/dev/pci/if_wm.c @@ -442,6 +442,8 @@ struct wm_softc { krndsource_t rnd_source; /* random source */ kmutex_t *sc_core_lock; /* lock for softc operations */ + + struct if_percpuq *sc_ipq; /* softint-based input queues */ }; #define WM_TX_LOCK(_txq) if ((_txq)->txq_lock) mutex_enter((_txq)->txq_lock) @@ -2444,8 +2446,10 @@ alloc_retry: #endif /* Attach the interface. */ - if_attach(ifp); + if_initialize(ifp); + sc->sc_ipq = if_percpuq_create(&sc->sc_ethercom.ec_if); ether_ifattach(ifp, enaddr); + if_register(ifp); ether_set_ifflags_cb(&sc->sc_ethercom, wm_ifflags_cb); rnd_attach_source(&sc->rnd_source, xname, RND_TYPE_NET, RND_FLAG_DEFAULT); @@ -2559,7 +2563,7 @@ wm_detach(device_t self, int flags __unused) ether_ifdetach(ifp); if_detach(ifp); - + if_percpuq_destroy(sc->sc_ipq); /* Unload RX dmamaps and free mbufs */ for (i = 0; i < sc->sc_nrxqueues; i++) { @@ -7121,7 +7125,7 @@ wm_rxeof(struct wm_rxqueue *rxq) bpf_mtap(ifp, m); /* Pass it on. */ - if_input(ifp, m); + if_percpuq_enqueue(sc->sc_ipq, m); WM_RX_LOCK(rxq); diff --git a/sys/net/if.c b/sys/net/if.c index dfd622f..506331c 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -650,6 +650,20 @@ if_register(ifnet_t *ifp) } static void +if_percpuq_softint(void *arg) +{ + struct if_percpuq *ipq = arg; + struct ifnet *ifp = ipq->ipq_ifp; + struct mbuf *m; + int s; + + s = splnet(); + while ((m = if_percpuq_dequeue(ipq)) != NULL) + ifp->_if_input(ifp, m); + splx(s); +} + +static void if_percpuq_init_ifq(void *p, void *arg __unused, struct cpu_info *ci __unused) { struct ifqueue *const ifq = p; @@ -659,7 +673,7 @@ if_percpuq_init_ifq(void *p, void *arg __unused, struct cpu_info *ci __unused) } struct if_percpuq * -if_percpuq_create(void (*sih)(void *), void *arg) +if_percpuq_create(struct ifnet *ifp) { struct if_percpuq *ipq; @@ -667,30 +681,26 @@ if_percpuq_create(void (*sih)(void *), void *arg) if (ipq == NULL) panic("kmem_zalloc failed"); + ipq->ipq_ifp = ifp; ipq->ipq_si = softint_establish(SOFTINT_NET|SOFTINT_MPSAFE, - sih, arg); + if_percpuq_softint, ipq); ipq->ipq_ifqs = percpu_alloc(sizeof(struct ifqueue)); percpu_foreach(ipq->ipq_ifqs, &if_percpuq_init_ifq, NULL); return ipq; } -void -if_percpuq_softint(void *arg) +struct mbuf * +if_percpuq_dequeue(struct if_percpuq *ipq) { - struct ifnet *ifp = arg; struct mbuf *m; struct ifqueue *ifq; - int s; - s = splnet(); - ifq = percpu_getref(ifp->if_percpuq->ipq_ifqs); - while (!IF_IS_EMPTY(ifq)) { - IF_DEQUEUE(ifq, m); - ifp->_if_input(ifp, m); - } - percpu_putref(ifp->if_percpuq->ipq_ifqs); - splx(s); + ifq = percpu_getref(ipq->ipq_ifqs); + IF_DEQUEUE(ifq, m); + percpu_putref(ipq->ipq_ifqs); + + return m; } static void @@ -705,9 +715,47 @@ void if_percpuq_destroy(struct if_percpuq *ipq) { + softint_disestablish(ipq->ipq_si); percpu_foreach(ipq->ipq_ifqs, &if_percpuq_purge_ifq, NULL); percpu_free(ipq->ipq_ifqs, sizeof(struct ifqueue)); - softint_disestablish(ipq->ipq_si); +} + +void +if_percpuq_enqueue(struct if_percpuq *ipq, struct mbuf *m) +{ + struct ifqueue *ifq = percpu_getref(ipq->ipq_ifqs); + int s; + + s = splnet(); + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + m_freem(m); + goto out; + } + IF_ENQUEUE(ifq, m); + percpu_putref(ipq->ipq_ifqs); + + softint_schedule(ipq->ipq_si); +out: + splx(s); +} + +/* + * The common interface input routine that is called by device drivers. + * We ensure that the upper layer routines, e.g., ether_input and bridge_input, + * aren't run in hardware interrupt context. + */ +void +if_input(struct ifnet *ifp, struct mbuf *m) +{ + + if (ifp->if_percpuq) { + if_percpuq_enqueue(ifp->if_percpuq, m); + } else { + KASSERT(!cpu_intr_p()); + + ifp->_if_input(ifp, m); + } } /* @@ -717,8 +765,9 @@ if_percpuq_destroy(struct if_percpuq *ipq) void if_attach(ifnet_t *ifp) { + if_initialize(ifp); - ifp->if_percpuq = if_percpuq_create(if_percpuq_softint, ifp); + ifp->if_percpuq = if_percpuq_create(ifp); if_register(ifp); } @@ -988,13 +1037,8 @@ again: xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL); xc_wait(xc); - if (ifp->if_percpuq != NULL) { - struct if_percpuq *ipq = ifp->if_percpuq; - - percpu_foreach(ipq->ipq_ifqs, &if_percpuq_purge_ifq, NULL); - percpu_free(ipq->ipq_ifqs, sizeof(struct ifqueue)); - softint_disestablish(ipq->ipq_si); - } + if (ifp->if_percpuq != NULL) + if_percpuq_destroy(ifp->if_percpuq); splx(s); } @@ -2512,42 +2556,6 @@ if_mcast_op(ifnet_t *ifp, const unsigned long cmd, const struct sockaddr *sa) return rc; } -void -if_percpuq_enqueue(struct if_percpuq *ipq, struct mbuf *m) -{ - struct ifqueue *ifq = percpu_getref(ipq->ipq_ifqs); - - if (IF_QFULL(ifq)) { - IF_DROP(ifq); - m_freem(m); - return; - } - IF_ENQUEUE(ifq, m); - percpu_putref(ipq->ipq_ifqs); - - softint_schedule(ipq->ipq_si); -} - -/* - * The common interface input routine that is called by device drivers. - * We ensure that the upper layer routines, e.g., ether_input and bridge_input, - * aren't run in hardware interrupt context. - */ -void -if_input(struct ifnet *ifp, struct mbuf *m) -{ - - if (ifp->if_percpuq) { - KASSERT(cpu_intr_p()); - - if_percpuq_enqueue(ifp->if_percpuq, m); - } else { - KASSERT(!cpu_intr_p()); - - ifp->_if_input(ifp, m); - } -} - static void sysctl_sndq_setup(struct sysctllog **clog, const char *ifname, struct ifaltq *ifq) diff --git a/sys/net/if.h b/sys/net/if.h index 5f2e185..bf619ec 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -252,11 +252,7 @@ struct bridge_softc; struct bridge_iflist; struct callout; struct krwlock; - -struct if_percpuq { - void *ipq_si; - struct percpu *ipq_ifqs; /* struct ifqueue */ -}; +struct if_percpuq; typedef struct ifnet { void *if_softc; /* lower-level data for this if */ @@ -956,11 +952,18 @@ int if_clone_list(int, char *, int *); void if_input(struct ifnet *, struct mbuf *); +struct if_percpuq { + struct ifnet *ipq_ifp; + void *ipq_si; + struct percpu *ipq_ifqs; /* struct ifqueue */ +}; + struct if_percpuq * - if_percpuq_create(void (*)(void *), void *); + if_percpuq_create(struct ifnet *); void if_percpuq_destroy(struct if_percpuq *); void if_percpuq_enqueue(struct if_percpuq *, struct mbuf *); -void if_percpuq_softint(void *); +struct mbuf * + if_percpuq_dequeue(struct if_percpuq *); void ifa_insert(struct ifnet *, struct ifaddr *); void ifa_remove(struct ifnet *, struct ifaddr *);