2 * Copyright (c) 2003 Jeffrey Hsu
3 * Copyright (c) 2003 Jonathan Lemon
4 * Copyright (c) 2003 Matthew Dillon
6 * $DragonFly: src/sys/net/netisr.c,v 1.16 2004/04/24 06:55:57 hsu Exp $
10 #include <sys/systm.h>
11 #include <sys/kernel.h>
12 #include <sys/malloc.h>
13 #include <sys/msgport.h>
15 #include <sys/interrupt.h>
16 #include <sys/socket.h>
17 #include <sys/sysctl.h>
19 #include <net/if_var.h>
20 #include <net/netisr.h>
21 #include <machine/cpufunc.h>
22 #include <machine/ipl.h>
24 #include <sys/thread2.h>
25 #include <sys/msgport2.h>
27 static struct netisr netisrs[NETISR_MAX];
29 /* Per-CPU thread to handle any protocol. */
30 struct thread netisr_cpu[MAXCPU];
31 lwkt_port netisr_afree_rport;
34 * netisr_afree_rport replymsg function, only used to handle async
35 * messages which the sender has abandoned to their fate.
38 netisr_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
44 * We must construct a custom putport function (which runs in the context
45 * of the message originator)
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.
54 netmsg_put_port(lwkt_port_t port, lwkt_msg_t lmsg)
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");
64 return(lwkt_default_putport(port, lmsg));
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,
77 netisr_cpu[i].td_msgport.mp_putport = netmsg_put_port;
79 lwkt_initport(&netisr_afree_rport, NULL);
80 netisr_afree_rport.mp_replyport = netisr_autofree_reply;
83 SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL);
86 netmsg_service_loop(void *arg)
90 while ((msg = lwkt_waitport(&curthread->td_msgport, NULL)))
91 msg->nm_lmsg.ms_cmd.cm_func(&msg->nm_lmsg);
95 * Call the netisr directly.
96 * Queueing may be done in the msg port layer at its discretion.
99 netisr_dispatch(int num, struct mbuf *m)
101 /* just queue it for now XXX JH */
102 netisr_queue(num, m);
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.
111 netisr_queue(int num, struct mbuf *m)
114 struct netmsg_packet *pmsg;
117 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
118 ("netisr_queue: bad isr %d", num));
121 if (ni->ni_handler == NULL) {
122 printf("netisr_queue: unregistered isr %d\n", num);
126 if (!(port = ni->ni_mport(m)))
129 /* use better message allocation system with limits later XXX JH */
130 pmsg = malloc(sizeof(struct netmsg_packet), M_LWKTMSG, M_WAITOK);
132 lwkt_initmsg(&pmsg->nm_lmsg, &netisr_afree_rport, 0,
133 lwkt_cmd_func((void *)ni->ni_handler), lwkt_cmd_op_none);
135 lwkt_sendmsg(port, &pmsg->nm_lmsg);
140 netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler)
142 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
143 ("netisr_register: bad isr %d", num));
145 netisrs[num].ni_mport = mportfn;
146 netisrs[num].ni_handler = handler;
150 netisr_unregister(int num)
152 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
153 ("unregister_netisr: bad isr number: %d\n", num));
160 * Return message port for default handler thread on CPU 0.
163 cpu0_portfn(struct mbuf *m)
165 return (&netisr_cpu[0].td_msgport);
170 cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused,
173 return (&netisr_cpu[0].td_msgport);
177 * This function is used to call the netisr handler from the appropriate
178 * netisr thread for polling and other purposes.
183 struct netisr *ni = &netisrs[num];
185 lwkt_port_t port = &netisr_cpu[0].td_msgport;
187 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
188 ("schednetisr: bad isr %d", num));
190 pmsg = malloc(sizeof(struct netmsg), M_LWKTMSG, M_NOWAIT);
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);