xref: /dflybsd-src/sys/net/netisr.c (revision 7b39b21b9eddc5c8c0a213f0890ba59237298982)
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.16 2004/04/24 06:55:57 hsu Exp $
7  */
8 
9 #include <sys/param.h>
10 #include <sys/systm.h>
11 #include <sys/kernel.h>
12 #include <sys/malloc.h>
13 #include <sys/msgport.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 #include <sys/thread2.h>
25 #include <sys/msgport2.h>
26 
27 static struct netisr netisrs[NETISR_MAX];
28 
29 /* Per-CPU thread to handle any protocol.  */
30 struct thread netisr_cpu[MAXCPU];
31 lwkt_port netisr_afree_rport;
32 
33 /*
34  * netisr_afree_rport replymsg function, only used to handle async
35  * messages which the sender has abandoned to their fate.
36  */
37 static void
38 netisr_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
39 {
40     free(msg, M_LWKTMSG);
41 }
42 
43 /*
44  * We must construct a custom putport function (which runs in the context
45  * of the message originator)
46  *
47  * Our custom putport must check for self-referential messages, which can
48  * occur when the so_upcall routine is called (e.g. nfs).  Self referential
49  * messages are executed synchronously.  However, we must panic if the message
50  * is not marked DONE on completion because the self-referential case cannot
51  * block without deadlocking.
52  */
53 int
54 netmsg_put_port(lwkt_port_t port, lwkt_msg_t lmsg)
55 {
56     int error;
57 
58     if ((lmsg->ms_flags & MSGF_ASYNC) == 0 && port->mp_td == curthread) {
59 	error = lmsg->ms_cmd.cm_func(lmsg);
60 	if (error == EASYNC && (lmsg->ms_flags & MSGF_DONE) == 0)
61 	    panic("netmsg_put_port: self-referential deadlock on netport");
62 	return(error);
63     } else {
64 	return(lwkt_default_putport(port, lmsg));
65     }
66 }
67 
68 static void
69 netisr_init(void)
70 {
71     int i;
72 
73     /* Create default per-cpu threads for generic protocol handling. */
74     for (i = 0; i < ncpus; ++i) {
75 	lwkt_create(netmsg_service_loop, NULL, NULL, &netisr_cpu[i], 0, i,
76 	    "netisr_cpu %d", i);
77 	netisr_cpu[i].td_msgport.mp_putport = netmsg_put_port;
78     }
79     lwkt_initport(&netisr_afree_rport, NULL);
80     netisr_afree_rport.mp_replyport = netisr_autofree_reply;
81 }
82 
83 SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL);
84 
85 void
86 netmsg_service_loop(void *arg)
87 {
88     struct netmsg *msg;
89 
90     while ((msg = lwkt_waitport(&curthread->td_msgport, NULL)))
91 	msg->nm_lmsg.ms_cmd.cm_func(&msg->nm_lmsg);
92 }
93 
94 /*
95  * Call the netisr directly.
96  * Queueing may be done in the msg port layer at its discretion.
97  */
98 void
99 netisr_dispatch(int num, struct mbuf *m)
100 {
101     /* just queue it for now XXX JH */
102     netisr_queue(num, m);
103 }
104 
105 /*
106  * Same as netisr_dispatch(), but always queue.
107  * This is either used in places where we are not confident that
108  * direct dispatch is possible, or where queueing is required.
109  */
110 int
111 netisr_queue(int num, struct mbuf *m)
112 {
113     struct netisr *ni;
114     struct netmsg_packet *pmsg;
115     lwkt_port_t port;
116 
117     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
118 	("netisr_queue: bad isr %d", num));
119 
120     ni = &netisrs[num];
121     if (ni->ni_handler == NULL) {
122 	printf("netisr_queue: unregistered isr %d\n", num);
123 	return (EIO);
124     }
125 
126     if (!(port = ni->ni_mport(m)))
127 	return (EIO);
128 
129     /* use better message allocation system with limits later XXX JH */
130     pmsg = malloc(sizeof(struct netmsg_packet), M_LWKTMSG, M_WAITOK);
131 
132     lwkt_initmsg(&pmsg->nm_lmsg, &netisr_afree_rport, 0,
133 		lwkt_cmd_func((void *)ni->ni_handler), lwkt_cmd_op_none);
134     pmsg->nm_packet = m;
135     lwkt_sendmsg(port, &pmsg->nm_lmsg);
136     return (0);
137 }
138 
139 void
140 netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler)
141 {
142     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
143 	("netisr_register: bad isr %d", num));
144 
145     netisrs[num].ni_mport = mportfn;
146     netisrs[num].ni_handler = handler;
147 }
148 
149 int
150 netisr_unregister(int num)
151 {
152     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
153 	("unregister_netisr: bad isr number: %d\n", num));
154 
155     /* XXX JH */
156     return (0);
157 }
158 
159 /*
160  * Return message port for default handler thread on CPU 0.
161  */
162 lwkt_port_t
163 cpu0_portfn(struct mbuf *m)
164 {
165     return (&netisr_cpu[0].td_msgport);
166 }
167 
168 /* ARGSUSED */
169 lwkt_port_t
170 cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused,
171 	    int req __unused)
172 {
173     return (&netisr_cpu[0].td_msgport);
174 }
175 
176 /*
177  * This function is used to call the netisr handler from the appropriate
178  * netisr thread for polling and other purposes.
179  */
180 void
181 schednetisr(int num)
182 {
183     struct netisr *ni = &netisrs[num];
184     struct netmsg *pmsg;
185     lwkt_port_t port = &netisr_cpu[0].td_msgport;
186 
187     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
188 	("schednetisr: bad isr %d", num));
189 
190     pmsg = malloc(sizeof(struct netmsg), M_LWKTMSG, M_NOWAIT);
191     if (pmsg) {
192 	lwkt_initmsg(&pmsg->nm_lmsg, &netisr_afree_rport, 0,
193 		    lwkt_cmd_func((void *)ni->ni_handler), lwkt_cmd_op_none);
194 	lwkt_sendmsg(port, &pmsg->nm_lmsg);
195     }
196 }
197