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