Revamp the initial lwkt_abortmsg() support to normalize the abstraction. Now
[dragonfly.git] / sys / net / netisr.c
CommitLineData
ef0fdad1 1/*-
8bde602d
JH
2 * Copyright (c) 2003 Jeffrey Hsu
3 * Copyright (c) 2003 Jonathan Lemon
ef0fdad1
MD
4 * Copyright (c) 2003 Matthew Dillon
5 *
b44419cb 6 * $DragonFly: src/sys/net/netisr.c,v 1.13 2004/04/20 01:52:26 dillon Exp $
ef0fdad1
MD
7 */
8
9#include <sys/param.h>
10#include <sys/systm.h>
bf82f9b7 11#include <sys/kernel.h>
9eeaa8a9 12#include <sys/malloc.h>
bf82f9b7 13#include <sys/msgport.h>
ef0fdad1
MD
14#include <sys/proc.h>
15#include <sys/interrupt.h>
8bde602d
JH
16#include <sys/socket.h>
17#include <sys/sysctl.h>
18#include <net/if.h>
19#include <net/if_var.h>
ef0fdad1
MD
20#include <net/netisr.h>
21#include <machine/cpufunc.h>
22#include <machine/ipl.h>
23
3227f1b8
MD
24#include <sys/thread2.h>
25#include <sys/msgport2.h>
26
bf82f9b7
MD
27static struct netisr netisrs[NETISR_MAX];
28
29/* Per-CPU thread to handle any protocol. */
30struct thread netisr_cpu[MAXCPU];
3227f1b8
MD
31lwkt_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 */
37static void
38netisr_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
39{
40 free(msg, M_LWKTMSG);
41}
ef0fdad1
MD
42
43static void
bf82f9b7 44netisr_init(void)
ef0fdad1 45{
bf82f9b7
MD
46 int i;
47
48 /* Create default per-cpu threads for generic protocol handling. */
3227f1b8 49 for (i = 0; i < ncpus; ++i) {
bf82f9b7
MD
50 lwkt_create(netmsg_service_loop, NULL, NULL, &netisr_cpu[i], 0, i,
51 "netisr_cpu %d", i);
3227f1b8
MD
52 }
53 lwkt_initport(&netisr_afree_rport, NULL);
54 netisr_afree_rport.mp_replyport = netisr_autofree_reply;
ef0fdad1
MD
55}
56
bf82f9b7
MD
57SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL);
58
8bde602d 59void
bf82f9b7 60netmsg_service_loop(void *arg)
8bde602d 61{
12967093
MD
62 struct netmsg *msg;
63
a80cf23b 64 while ((msg = lwkt_waitport(&curthread->td_msgport, NULL)))
b44419cb 65 msg->nm_lmsg.ms_cmd.cm_func(&msg->nm_lmsg);
bf82f9b7 66}
8bde602d 67
bf82f9b7
MD
68/*
69 * Call the netisr directly.
70 * Queueing may be done in the msg port layer at its discretion.
71 */
72void
73netisr_dispatch(int num, struct mbuf *m)
74{
75 /* just queue it for now XXX JH */
76 netisr_queue(num, m);
8bde602d
JH
77}
78
79/*
80 * Same as netisr_dispatch(), but always queue.
81 * This is either used in places where we are not confident that
82 * direct dispatch is possible, or where queueing is required.
83 */
ef0fdad1 84int
8bde602d 85netisr_queue(int num, struct mbuf *m)
ef0fdad1 86{
5944299a 87 struct netisr *ni;
9eeaa8a9 88 struct netmsg_packet *pmsg;
bf82f9b7 89 lwkt_port_t port;
8bde602d
JH
90
91 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
1748bf82 92 ("netisr_queue: bad isr %d", num));
8bde602d 93
5944299a
MD
94 ni = &netisrs[num];
95 if (ni->ni_handler == NULL) {
96 printf("netisr_queue: unregistered isr %d\n", num);
9eeaa8a9 97 return (EIO);
5944299a
MD
98 }
99
bf82f9b7 100 if (!(port = ni->ni_mport(m)))
9eeaa8a9
JH
101 return (EIO);
102
103 /* use better message allocation system with limits later XXX JH */
f20847c9 104 pmsg = malloc(sizeof(struct netmsg_packet), M_LWKTMSG, M_WAITOK);
8bde602d 105
b44419cb
MD
106 lwkt_initmsg(&pmsg->nm_lmsg, &netisr_afree_rport, 0,
107 lwkt_cmd_func((void *)ni->ni_handler), lwkt_cmd_op_none);
bf82f9b7 108 pmsg->nm_packet = m;
bf82f9b7 109 lwkt_sendmsg(port, &pmsg->nm_lmsg);
8bde602d
JH
110 return (0);
111}
112
bf82f9b7
MD
113void
114netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler)
8bde602d
JH
115{
116 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
1748bf82 117 ("netisr_register: bad isr %d", num));
8bde602d 118
bf82f9b7 119 netisrs[num].ni_mport = mportfn;
8bde602d 120 netisrs[num].ni_handler = handler;
ef0fdad1
MD
121}
122
123int
8bde602d 124netisr_unregister(int num)
ef0fdad1 125{
8bde602d
JH
126 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
127 ("unregister_netisr: bad isr number: %d\n", num));
128
bf82f9b7 129 /* XXX JH */
ef0fdad1
MD
130 return (0);
131}
bf82f9b7
MD
132
133/*
134 * Return message port for default handler thread on CPU 0.
135 */
136lwkt_port_t
137cpu0_portfn(struct mbuf *m)
138{
139 return (&netisr_cpu[0].td_msgport);
140}
141
9eeaa8a9
JH
142/* ARGSUSED */
143lwkt_port_t
144cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused)
145{
146 return (&netisr_cpu[0].td_msgport);
147}
148
bf82f9b7
MD
149/*
150 * This function is used to call the netisr handler from the appropriate
9eeaa8a9 151 * netisr thread for polling and other purposes.
bf82f9b7
MD
152 */
153void
154schednetisr(int num)
155{
156 struct netisr *ni = &netisrs[num];
157 struct netmsg *pmsg;
158 lwkt_port_t port = &netisr_cpu[0].td_msgport;
159
160 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
1748bf82 161 ("schednetisr: bad isr %d", num));
bf82f9b7 162
9eeaa8a9 163 if (!(pmsg = malloc(sizeof(struct netmsg), M_LWKTMSG, M_NOWAIT)))
bf82f9b7
MD
164 return;
165
b44419cb
MD
166 lwkt_initmsg(&pmsg->nm_lmsg, &netisr_afree_rport, 0,
167 lwkt_cmd_func((void *)ni->ni_handler), lwkt_cmd_op_none);
bf82f9b7
MD
168 lwkt_sendmsg(port, &pmsg->nm_lmsg);
169}