Deleted Added
full compact
1c1,2
< /*
---
> /*-
> * Copyright (c) 2001,2002,2003 Jonathan Lemon <jlemon@FreeBSD.org>
9,10c10
< * notice unmodified, this list of conditions, and the following
< * disclaimer.
---
> * notice, this list of conditions and the following disclaimer.
15,24c15,25
< * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
< * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
< * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
< * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
< * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
< * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
< * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
< * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
< * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
< * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
> * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> * SUCH DAMAGE.
26c27
< * $FreeBSD: head/sys/net/netisr.c 103781 2002-09-22 05:56:41Z jake $
---
> * $FreeBSD: head/sys/net/netisr.c 111888 2003-03-04 23:19:55Z jlemon $
30d30
< #include <sys/systm.h>
32c32,33
< #include <sys/proc.h>
---
> #include <sys/rtprio.h>
> #include <sys/systm.h>
34a36,46
> #include <sys/kthread.h>
> #include <sys/lock.h>
> #include <sys/malloc.h>
> #include <sys/proc.h>
> #include <sys/random.h>
> #include <sys/resourcevar.h>
> #include <sys/sysctl.h>
> #include <sys/unistd.h>
> #include <machine/atomic.h>
> #include <machine/cpu.h>
> #include <machine/stdarg.h>
35a48,53
> #include <sys/mbuf.h>
> #include <sys/socket.h>
>
> #include <net/if.h>
> #include <net/if_types.h>
> #include <net/if_var.h>
38c56
< static void swi_net(void *);
---
> volatile unsigned int netisr; /* scheduling bits for network */
40,42c58,61
< void *net_ih;
< volatile unsigned int netisr;
< void (*netisrs[32])(void);
---
> struct netisr {
> netisr_t *ni_handler;
> struct ifqueue *ni_queue;
> } netisrs[32];
43a63,65
> static struct mtx netisr_mtx;
> static void *net_ih;
>
50,51c72,73
< int
< register_netisr(int num, netisr_t *handler)
---
> void
> netisr_register(int num, netisr_t *handler, struct ifqueue *inq)
54,56c76,95
< if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) {
< printf("register_netisr: bad isr number: %d\n", num);
< return (EINVAL);
---
> KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))),
> ("bad isr %d", num));
> netisrs[num].ni_handler = handler;
> netisrs[num].ni_queue = inq;
> }
>
> void
> netisr_unregister(int num)
> {
> struct netisr *ni;
> int s;
>
> KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))),
> ("bad isr %d", num));
> ni = &netisrs[num];
> ni->ni_handler = NULL;
> if (ni->ni_queue != NULL) {
> s = splimp();
> IF_DRAIN(ni->ni_queue);
> splx(s);
58,59d96
< netisrs[num] = handler;
< return (0);
62,63c99,141
< int
< unregister_netisr(int num)
---
> struct isrstat {
> int isrs_count; /* dispatch count */
> int isrs_directed; /* ...successfully dispatched */
> int isrs_deferred; /* ...queued instead */
> int isrs_bypassed; /* bypassed queued packets */
> int isrs_queued; /* intentionally queueued */
> int isrs_swi_count; /* swi_net handlers called */
> };
> static struct isrstat isrstat;
>
> SYSCTL_NODE(_net, OID_AUTO, isr, CTLFLAG_RW, 0, "netisr counters");
>
> static int netisr_enable = 0;
> SYSCTL_INT(_net_isr, OID_AUTO, enable, CTLFLAG_RW,
> &netisr_enable, 0, "enable direct dispatch");
>
> SYSCTL_INT(_net_isr, OID_AUTO, count, CTLFLAG_RD,
> &isrstat.isrs_count, 0, "");
> SYSCTL_INT(_net_isr, OID_AUTO, directed, CTLFLAG_RD,
> &isrstat.isrs_directed, 0, "");
> SYSCTL_INT(_net_isr, OID_AUTO, deferred, CTLFLAG_RD,
> &isrstat.isrs_deferred, 0, "");
> SYSCTL_INT(_net_isr, OID_AUTO, bypassed, CTLFLAG_RD,
> &isrstat.isrs_bypassed, 0, "");
> SYSCTL_INT(_net_isr, OID_AUTO, queued, CTLFLAG_RD,
> &isrstat.isrs_queued, 0, "");
> SYSCTL_INT(_net_isr, OID_AUTO, swi_count, CTLFLAG_RD,
> &isrstat.isrs_swi_count, 0, "");
>
> /*
> * Call the netisr directly instead of queueing the packet, if possible.
> *
> * Ideally, the permissibility of calling the routine would be determined
> * by checking if splnet() was asserted at the time the device interrupt
> * occurred; if so, this indicates that someone is in the network stack.
> *
> * However, bus_setup_intr uses INTR_TYPE_NET, which sets splnet before
> * calling the interrupt handler, so the previous mask is unavailable.
> * Approximate this by checking intr_nesting_level instead; if any SWI
> * handlers are running, the packet is queued instead.
> */
> void
> netisr_dispatch(int num, struct mbuf *m)
64a143
> struct netisr *ni;
66,68c145,171
< if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) {
< printf("unregister_netisr: bad isr number: %d\n", num);
< return (EINVAL);
---
> isrstat.isrs_count++;
> KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))),
> ("bad isr %d", num));
> ni = &netisrs[num];
> KASSERT(ni->ni_queue != NULL, ("no queue for isr %d", num));
> if (netisr_enable && mtx_trylock(&netisr_mtx)) {
> isrstat.isrs_directed++;
> /*
> * One slight problem here is that packets might bypass
> * each other in the stack, if an earlier one happened
> * to get stuck in the queue.
> *
> * we can either:
> * a. drain the queue before handling this packet,
> * b. fallback to queueing the packet,
> * c. sweep the issue under the rug and ignore it.
> *
> * Currently, we do c), and keep a rough event counter.
> */
> if (_IF_QLEN(ni->ni_queue) > 0)
> isrstat.isrs_bypassed++;
> ni->ni_handler(m);
> mtx_unlock(&netisr_mtx);
> } else {
> isrstat.isrs_deferred++;
> if (IF_HANDOFF(ni->ni_queue, m, NULL))
> schednetisr(num);
70,71d172
< netisrs[num] = NULL;
< return (0);
74,76c175,194
< #ifdef DEVICE_POLLING
< void netisr_pollmore(void);
< #endif
---
> /*
> * Same as above, but always queue.
> * This is either used in places where we are not confident that
> * direct dispatch is possible, or where queueing is required.
> */
> int
> netisr_queue(int num, struct mbuf *m)
> {
> struct netisr *ni;
>
> KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))),
> ("bad isr %d", num));
> ni = &netisrs[num];
> KASSERT(ni->ni_queue != NULL, ("no queue for isr %d", num));
> isrstat.isrs_queued++;
> if (!IF_HANDOFF(ni->ni_queue, m, NULL))
> return (0);
> schednetisr(num);
> return (1);
> }
80a199,200
> struct netisr *ni;
> struct mbuf *m;
83d202
<
85,86c204,206
< for (;;) {
< int pollmore;
---
> const int polling = 1;
> #else
> const int polling = 0;
88,106c208,234
< bits = atomic_readandclear_int(&netisr);
< #ifdef DEVICE_POLLING
< if (bits == 0)
< return;
< pollmore = bits & (1 << NETISR_POLL);
< #endif
< while ((i = ffs(bits)) != 0) {
< i--;
< if (netisrs[i] != NULL)
< netisrs[i]();
< else
< printf("swi_net: unregistered isr number: %d.\n", i);
< bits &= ~(1 << i);
< }
< #ifdef DEVICE_POLLING
< if (pollmore)
< netisr_pollmore();
< }
< #endif
---
>
> mtx_lock(&netisr_mtx);
> do {
> bits = atomic_readandclear_int(&netisr);
> if (bits == 0)
> break;
> while ((i = ffs(bits)) != 0) {
> isrstat.isrs_swi_count++;
> i--;
> bits &= ~(1 << i);
> ni = &netisrs[i];
> if (ni->ni_handler == NULL) {
> printf("swi_net: unregistered isr %d.\n", i);
> continue;
> }
> if (ni->ni_queue == NULL)
> ni->ni_handler(NULL);
> else
> for (;;) {
> IF_DEQUEUE(ni->ni_queue, m);
> if (m == NULL)
> break;
> ni->ni_handler(m);
> }
> }
> } while (polling);
> mtx_unlock(&netisr_mtx);
112a241
> mtx_init(&netisr_mtx, "netisr lock", NULL, MTX_DEF);