xref: /dragonfly/sys/net/netisr.c (revision 16777b6b)
1 /*-
2  * Copyright (c) 2003 Jeffrey Hsu
3  * Copyright (c) 2003 Jonathan Lemon
4  * Copyright (c) 2003 Matthew Dillon
5  *
6  * $DragonFly: src/sys/net/netisr.c,v 1.2 2003/09/15 23:38:13 hsu Exp $
7  */
8 
9 #include <sys/param.h>
10 #include <sys/systm.h>
11 #include <sys/proc.h>
12 #include <sys/interrupt.h>
13 #include <sys/socket.h>
14 #include <sys/sysctl.h>
15 #include <net/if.h>
16 #include <net/if_var.h>
17 #include <net/netisr.h>
18 #include <machine/cpufunc.h>
19 #include <machine/ipl.h>
20 
21 int isrmask;
22 static int isrsoftint_installed;
23 static struct netisr netisrs[NETISR_MAX];
24 
25 /* SYSCTL_NODE(_net, OID_AUTO, isr, CTLFLAG_RW, 0, "netisr counters"); */
26 
27 static int netisr_directdispatch = 0;
28 /*
29 SYSCTL_INT(_net_isr, OID_AUTO, directdispatch, CTLFLAG_RW,
30     &netisr_directdispatch, 0, "enable direct dispatch");
31 */
32 
33 static void
34 swi_net(void *arg)
35 {
36     int mask;
37     int bit;
38 
39     while ((mask = isrmask) != 0) {
40 	bit = bsfl(mask);
41 	if (btrl(&isrmask, bit)) {
42 	    struct netisr *ni = &netisrs[bit];
43 	    netisr_fn_t func = ni->ni_handler;
44 
45 	    if (ni->ni_queue) {
46 		while (1) {
47 		    struct mbuf *m;
48 		    int s;
49 
50 		    s = splimp();
51 		    IF_DEQUEUE(ni->ni_queue, m);
52 		    splx(s);
53 		    if (!m)
54 			break;
55 		    func(m);
56 		}
57 	    } else
58 	        func(NULL);
59 	}
60     }
61 }
62 
63 /*
64  * Call the netisr directly instead of queueing the packet, if possible.
65  */
66 void
67 netisr_dispatch(int num, struct mbuf *m)
68 {
69     struct netisr *ni;
70 
71     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
72 	("bad isr %d", num));
73 
74     ni = &netisrs[num];
75 
76     if (!ni->ni_queue) {
77 	m_freem(m);
78 	return;
79     }
80 
81     if (netisr_directdispatch) {
82       /*
83        * missing check for concurrent execution from swi_net() XXX JH
84        * Address this after conversion to message ports.
85        */
86 	ni->ni_handler(m);
87     } else {
88 	if (IF_HANDOFF(ni->ni_queue, m, NULL))
89 	    schednetisr(num);
90     }
91 }
92 
93 /*
94  * Same as netisr_dispatch(), but always queue.
95  * This is either used in places where we are not confident that
96  * direct dispatch is possible, or where queueing is required.
97  */
98 int
99 netisr_queue(int num, struct mbuf *m)
100 {
101     struct netisr *ni;
102 
103     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
104 	("bad isr %d", num));
105 
106     ni = &netisrs[num];
107 
108     if (!ni->ni_queue) {
109 	m_freem(m);
110 	return (ENOBUFS);
111     }
112 
113     if (!IF_HANDOFF(ni->ni_queue, m, NULL))
114 	return (ENOBUFS);
115 
116     schednetisr(num);
117     return (0);
118 }
119 
120 int
121 netisr_register(int num, netisr_fn_t handler, struct ifqueue *ifq)
122 {
123     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
124 	("bad isr %d", num));
125 
126     if (isrsoftint_installed == 0) {
127 	isrsoftint_installed = 1;
128 	register_swi(SWI_NET, swi_net, NULL, "swi_net");
129     }
130     netisrs[num].ni_handler = handler;
131     netisrs[num].ni_queue = ifq;
132     return (0);
133 }
134 
135 int
136 netisr_unregister(int num)
137 {
138     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
139 	("unregister_netisr: bad isr number: %d\n", num));
140 
141     if (netisrs[num].ni_queue != NULL) {
142 	int s;
143 
144 	s = splimp();
145 	IF_DRAIN(netisrs[num].ni_queue);
146 	splx(s);
147     }
148     netisrs[num].ni_handler = NULL;
149     return (0);
150 }
151