The cam_sim structure was being deallocated unconditionally by device
[dragonfly.git] / sys / net / netisr.c
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.9 2004/03/06 19:40:30 dillon 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 static void
44 netisr_init(void)
45 {
46     int i;
47
48     /* Create default per-cpu threads for generic protocol handling. */
49     for (i = 0; i < ncpus; ++i) {
50         lwkt_create(netmsg_service_loop, NULL, NULL, &netisr_cpu[i], 0, i,
51             "netisr_cpu %d", i);
52     }
53     lwkt_initport(&netisr_afree_rport, NULL);
54     netisr_afree_rport.mp_replyport = netisr_autofree_reply;
55 }
56
57 SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL);
58
59 void
60 netmsg_service_loop(void *arg)
61 {
62     struct netmsg *msg;
63     int error;
64
65     while ((msg = lwkt_waitport(&curthread->td_msgport, NULL))) {
66         error = msg->nm_handler(msg);
67         lwkt_replymsg(&msg->nm_lmsg, error);
68     }
69 }
70
71 /*
72  * Call the netisr directly.
73  * Queueing may be done in the msg port layer at its discretion.
74  */
75 void
76 netisr_dispatch(int num, struct mbuf *m)
77 {
78     /* just queue it for now XXX JH */
79     netisr_queue(num, m);
80 }
81
82 /*
83  * Same as netisr_dispatch(), but always queue.
84  * This is either used in places where we are not confident that
85  * direct dispatch is possible, or where queueing is required.
86  */
87 int
88 netisr_queue(int num, struct mbuf *m)
89 {
90     struct netisr *ni;
91     struct netmsg_packet *pmsg;
92     lwkt_port_t port;
93
94     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
95         ("netisr_queue: bad isr %d", num));
96
97     ni = &netisrs[num];
98     if (ni->ni_handler == NULL) {
99         printf("netisr_queue: unregistered isr %d\n", num);
100         return (EIO);
101     }
102
103     if (!(port = ni->ni_mport(m)))
104         return (EIO);
105
106     /* use better message allocation system with limits later XXX JH */
107     if (!(pmsg = malloc(sizeof(struct netmsg_packet), M_LWKTMSG, M_NOWAIT)))
108         return (ENOBUFS);
109
110     lwkt_initmsg_rp(&pmsg->nm_lmsg, &netisr_afree_rport, CMD_NETMSG_NEWPKT);
111     pmsg->nm_packet = m;
112     pmsg->nm_handler = ni->ni_handler;
113     lwkt_sendmsg(port, &pmsg->nm_lmsg);
114     return (0);
115 }
116
117 void
118 netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler)
119 {
120     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
121         ("netisr_register: bad isr %d", num));
122
123     netisrs[num].ni_mport = mportfn;
124     netisrs[num].ni_handler = handler;
125 }
126
127 int
128 netisr_unregister(int num)
129 {
130     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
131         ("unregister_netisr: bad isr number: %d\n", num));
132
133     /* XXX JH */
134     return (0);
135 }
136
137 /*
138  * Return message port for default handler thread on CPU 0.
139  */
140 lwkt_port_t
141 cpu0_portfn(struct mbuf *m)
142 {
143     return (&netisr_cpu[0].td_msgport);
144 }
145
146 /* ARGSUSED */
147 lwkt_port_t
148 cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused)
149 {
150     return (&netisr_cpu[0].td_msgport);
151 }
152
153 /*
154  * This function is used to call the netisr handler from the appropriate
155  * netisr thread for polling and other purposes.
156  */
157 void
158 schednetisr(int num)
159 {
160     struct netisr *ni = &netisrs[num];
161     struct netmsg *pmsg;
162     lwkt_port_t port = &netisr_cpu[0].td_msgport;
163
164     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
165         ("schednetisr: bad isr %d", num));
166
167     if (!(pmsg = malloc(sizeof(struct netmsg), M_LWKTMSG, M_NOWAIT)))
168         return;
169
170     lwkt_initmsg_rp(&pmsg->nm_lmsg, &netisr_afree_rport, CMD_NETMSG_POLL);
171     pmsg->nm_handler = ni->ni_handler;
172     lwkt_sendmsg(port, &pmsg->nm_lmsg);
173 }