xref: /dflybsd-src/sys/net/netisr.c (revision 3e4a09e71e628ef90f06defa19a42cbcf75e84e5)
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.7 2003/11/23 00:28:01 dillon Exp $
7  */
8 
9 #include <sys/param.h>
10 #include <sys/systm.h>
11 #include <sys/kernel.h>
12 #include <sys/msgport.h>
13 #include <sys/msgport2.h>
14 #include <sys/proc.h>
15 #include <sys/interrupt.h>
16 #include <sys/socket.h>
17 #include <sys/sysctl.h>
18 #include <net/if.h>
19 #include <net/if_var.h>
20 #include <net/netisr.h>
21 #include <machine/cpufunc.h>
22 #include <machine/ipl.h>
23 
24 struct netmsg {
25     struct lwkt_msg	nm_lmsg;
26     struct mbuf		*nm_packet;
27     netisr_fn_t		nm_handler;
28 };
29 
30 #define CMD_NETMSG_NEWPKT	(MSG_CMD_NETMSG | 0x0001)
31 #define CMD_NETMSG_POLL		(MSG_CMD_NETMSG | 0x0002)
32 
33 static struct netisr netisrs[NETISR_MAX];
34 
35 /* Per-CPU thread to handle any protocol.  */
36 struct thread netisr_cpu[MAXCPU];
37 
38 static void
39 netisr_init(void)
40 {
41     int i;
42 
43     /* Create default per-cpu threads for generic protocol handling. */
44     for (i = 0; i < ncpus; ++i)
45 	lwkt_create(netmsg_service_loop, NULL, NULL, &netisr_cpu[i], 0, i,
46 	    "netisr_cpu %d", i);
47 }
48 
49 SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL);
50 
51 void
52 netmsg_service_loop(void *arg)
53 {
54     struct netmsg *msg;
55 
56     while ((msg = lwkt_waitport(&curthread->td_msgport, NULL))) {
57 	struct mbuf *m = msg->nm_packet;
58 	netisr_fn_t handler = msg->nm_handler;
59 
60 	if (handler) {
61 		handler(m);
62 	} else if (m) {
63 		while (m->m_type == MT_TAG)
64 			m = m->m_next;
65 		KKASSERT(m != NULL);
66 		m_freem(m);
67 	}
68 	free(msg, M_TEMP);
69     }
70 }
71 
72 /*
73  * Call the netisr directly.
74  * Queueing may be done in the msg port layer at its discretion.
75  */
76 void
77 netisr_dispatch(int num, struct mbuf *m)
78 {
79     /* just queue it for now XXX JH */
80     netisr_queue(num, m);
81 }
82 
83 /*
84  * Same as netisr_dispatch(), but always queue.
85  * This is either used in places where we are not confident that
86  * direct dispatch is possible, or where queueing is required.
87  */
88 int
89 netisr_queue(int num, struct mbuf *m)
90 {
91     struct netisr *ni;
92     struct netmsg *pmsg;
93     lwkt_port_t port;
94 
95     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
96 	("netisr_queue: bad isr %d", num));
97 
98     ni = &netisrs[num];
99     if (ni->ni_handler == NULL) {
100 	printf("netisr_queue: unregistered isr %d\n", num);
101 	return EIO;
102     }
103 
104     /* use better message allocation system with limits later XXX JH */
105     if (!(pmsg = malloc(sizeof(struct netmsg), M_TEMP, M_NOWAIT)))
106 	return ENOBUFS;
107 
108     if (!(port = ni->ni_mport(m)))
109 	return EIO;
110 
111     lwkt_initmsg(&pmsg->nm_lmsg, port, CMD_NETMSG_NEWPKT);
112     pmsg->nm_packet = m;
113     pmsg->nm_handler = ni->ni_handler;
114     lwkt_sendmsg(port, &pmsg->nm_lmsg);
115     return (0);
116 }
117 
118 void
119 netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler)
120 {
121     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
122 	("netisr_register: bad isr %d", num));
123 
124     netisrs[num].ni_mport = mportfn;
125     netisrs[num].ni_handler = handler;
126 }
127 
128 int
129 netisr_unregister(int num)
130 {
131     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
132 	("unregister_netisr: bad isr number: %d\n", num));
133 
134     /* XXX JH */
135     return (0);
136 }
137 
138 /*
139  * Return message port for default handler thread on CPU 0.
140  */
141 lwkt_port_t
142 cpu0_portfn(struct mbuf *m)
143 {
144     return (&netisr_cpu[0].td_msgport);
145 }
146 
147 /*
148  * This function is used to call the netisr handler from the appropriate
149  * netisr thread for polling and other purposes.  pmsg->nm_packet will be
150  * undefined.  At the moment operation is restricted to non-packet ISRs only.
151  */
152 void
153 schednetisr(int num)
154 {
155     struct netisr *ni = &netisrs[num];
156     struct netmsg *pmsg;
157     lwkt_port_t port = &netisr_cpu[0].td_msgport;
158 
159     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
160 	("schednetisr: bad isr %d", num));
161 
162     if (!(pmsg = malloc(sizeof(struct netmsg), M_TEMP, M_NOWAIT)))
163 	return;
164 
165     lwkt_initmsg(&pmsg->nm_lmsg, port, CMD_NETMSG_POLL);
166     pmsg->nm_handler = ni->ni_handler;
167     lwkt_sendmsg(port, &pmsg->nm_lmsg);
168 }
169