diff --git a/sys/dev/pci/if_wm.c b/sys/dev/pci/if_wm.c index 4124859..de23f5c 100644 --- a/sys/dev/pci/if_wm.c +++ b/sys/dev/pci/if_wm.c @@ -2445,6 +2445,7 @@ alloc_retry: /* Attach the interface. */ if_attach(ifp); + if_init_softint_input(ifp); ether_ifattach(ifp, enaddr); ether_set_ifflags_cb(&sc->sc_ethercom, wm_ifflags_cb); rnd_attach_source(&sc->rnd_source, xname, RND_TYPE_NET, @@ -7117,11 +7118,7 @@ wm_rxeof(struct wm_rxqueue *rxq) WM_RX_UNLOCK(rxq); - /* Pass this up to any BPF listeners. */ - bpf_mtap(ifp, m); - - /* Pass it on. */ - (*ifp->if_input)(ifp, m); + if_input(ifp, m); WM_RX_LOCK(rxq); diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 100c112..3da5e29 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -485,6 +485,9 @@ main(void) /* Initialize sockets thread(s) */ soinit1(); + /* This should be before configure() for softint_establish */ + ipi_sysinit(); + /* Configure the system hardware. This will enable interrupts. */ configure(); @@ -499,7 +502,7 @@ main(void) configure2(); - ipi_sysinit(); + ipi_sysinit_ncpu(ncpu); /* Now timer is working. Enable preemption. */ kpreempt_enable(); diff --git a/sys/kern/subr_ipi.c b/sys/kern/subr_ipi.c index 4d26e92..c5dbfc9 100644 --- a/sys/kern/subr_ipi.c +++ b/sys/kern/subr_ipi.c @@ -93,20 +93,10 @@ static void ipi_msg_cpu_handler(void *); void ipi_sysinit(void) { - const size_t len = ncpu * sizeof(ipi_mbox_t); - /* Initialise the per-CPU bit fields. */ - for (u_int i = 0; i < ncpu; i++) { - struct cpu_info *ci = cpu_lookup(i); - memset(&ci->ci_ipipend, 0, sizeof(ci->ci_ipipend)); - } mutex_init(&ipi_mngmt_lock, MUTEX_DEFAULT, IPL_NONE); memset(ipi_intrs, 0, sizeof(ipi_intrs)); - /* Allocate per-CPU IPI mailboxes. */ - ipi_mboxes = kmem_zalloc(len, KM_SLEEP); - KASSERT(ipi_mboxes != NULL); - /* * Register the handler for synchronous IPIs. This mechanism * is built on top of the asynchronous interface. Slot zero is @@ -120,6 +110,25 @@ ipi_sysinit(void) } /* + * Must be called after ncpu is determined. + */ +void +ipi_sysinit_ncpu(int _ncpu) +{ + const size_t len = _ncpu * sizeof(ipi_mbox_t); + + /* Initialise the per-CPU bit fields. */ + for (u_int i = 0; i < _ncpu; i++) { + struct cpu_info *ci = cpu_lookup(i); + memset(&ci->ci_ipipend, 0, sizeof(ci->ci_ipipend)); + } + + /* Allocate per-CPU IPI mailboxes. */ + ipi_mboxes = kmem_zalloc(len, KM_SLEEP); + KASSERT(ipi_mboxes != NULL); +} + +/* * ipi_register: register an asynchronous IPI handler. * * => Returns IPI ID which is greater than zero; on failure - zero. diff --git a/sys/net/if.c b/sys/net/if.c index e7721a7..65e0444 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -118,6 +118,7 @@ __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.320 2016/01/04 09:08:38 ozaki-r Exp $"); #include #include +#include #include #include #include @@ -2442,6 +2443,37 @@ if_mcast_op(ifnet_t *ifp, const unsigned long cmd, const struct sockaddr *sa) } static void +if_input_pktq(void *arg) +{ + struct ifnet *ifp = arg; + struct mbuf *m; + + while ((m = pktq_dequeue(ifp->if_input_pktq)) != NULL) { + ifp->if_input(ifp, m); + } +} + +void +if_init_softint_input(struct ifnet *ifp) +{ + + ifp->if_input_pktq = pktq_create(IFQ_MAXLEN, if_input_pktq, ifp); +} + +void +if_input(struct ifnet *ifp, struct mbuf *m) +{ + + bpf_mtap(ifp, m); + + if (ifp->if_input_pktq) { + pktq_enqueue(ifp->if_input_pktq, m, curcpu()->ci_index); + } else { + (*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 f8051e4..2fac224 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -357,6 +357,7 @@ typedef struct ifnet { #else struct krwlock *if_afdata_lock; #endif + pktqueue_t *if_input_pktq; } ifnet_t; #define if_mtu if_data.ifi_mtu @@ -946,6 +947,8 @@ int if_do_dad(struct ifnet *); int if_mcast_op(ifnet_t *, const unsigned long, const struct sockaddr *); int if_flags_set(struct ifnet *, const short); int if_clone_list(int, char *, int *); +void if_init_softint_input(struct ifnet *); +void if_input(struct ifnet *, struct mbuf *); void ifa_insert(struct ifnet *, struct ifaddr *); void ifa_remove(struct ifnet *, struct ifaddr *); diff --git a/sys/sys/ipi.h b/sys/sys/ipi.h index 84bfb39..d13d509 100644 --- a/sys/sys/ipi.h +++ b/sys/sys/ipi.h @@ -60,6 +60,7 @@ typedef struct { #define IPI_BITWORDS (IPI_MAXREG >> IPI_BITW_SHIFT) void ipi_sysinit(void); +void ipi_sysinit_ncpu(int); void ipi_cpu_handler(void); void cpu_ipi(struct cpu_info *);