Commit | Line | Data |
---|---|---|
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 |
27 | static struct netisr netisrs[NETISR_MAX]; |
28 | ||
29 | /* Per-CPU thread to handle any protocol. */ | |
30 | struct thread netisr_cpu[MAXCPU]; | |
3227f1b8 MD |
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 | } | |
ef0fdad1 MD |
42 | |
43 | static void | |
bf82f9b7 | 44 | netisr_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 |
57 | SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL); |
58 | ||
8bde602d | 59 | void |
bf82f9b7 | 60 | netmsg_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 | */ | |
72 | void | |
73 | netisr_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 | 84 | int |
8bde602d | 85 | netisr_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 |
113 | void |
114 | netisr_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 | ||
123 | int | |
8bde602d | 124 | netisr_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 | */ | |
136 | lwkt_port_t | |
137 | cpu0_portfn(struct mbuf *m) | |
138 | { | |
139 | return (&netisr_cpu[0].td_msgport); | |
140 | } | |
141 | ||
9eeaa8a9 JH |
142 | /* ARGSUSED */ |
143 | lwkt_port_t | |
144 | cpu0_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 | */ |
153 | void | |
154 | schednetisr(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 | } |