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.10 2004/04/05 18:53:03 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 /* 60 * We must construct a custom putport function (which runs in the context 61 * of the message originator) 62 * Our custom putport must check for self-referential messages, which can 63 * occur when the so_upcall routine is called (e.g. nfs). Self referential 64 * messages are simply executed synchronously. 65 */ 66 static int 67 netmsg_put_port(lwkt_port_t port, lwkt_msg_t lmsg) 68 { 69 if (port->mp_td == curthread) { 70 struct netmsg *msg = (void *)lmsg; 71 return(msg->nm_handler(msg)); 72 } 73 return(lwkt_default_putport(port, lmsg)); 74 } 75 76 void 77 netmsg_service_loop(void *arg) 78 { 79 int error; 80 thread_t td; 81 struct netmsg *msg; 82 83 td = curthread; 84 td->td_msgport.mp_putport = netmsg_put_port; 85 86 while ((msg = lwkt_waitport(&td->td_msgport, NULL))) { 87 error = msg->nm_handler(msg); 88 lwkt_replymsg(&msg->nm_lmsg, error); 89 } 90 } 91 92 /* 93 * Call the netisr directly. 94 * Queueing may be done in the msg port layer at its discretion. 95 */ 96 void 97 netisr_dispatch(int num, struct mbuf *m) 98 { 99 /* just queue it for now XXX JH */ 100 netisr_queue(num, m); 101 } 102 103 /* 104 * Same as netisr_dispatch(), but always queue. 105 * This is either used in places where we are not confident that 106 * direct dispatch is possible, or where queueing is required. 107 */ 108 int 109 netisr_queue(int num, struct mbuf *m) 110 { 111 struct netisr *ni; 112 struct netmsg_packet *pmsg; 113 lwkt_port_t port; 114 115 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 116 ("netisr_queue: bad isr %d", num)); 117 118 ni = &netisrs[num]; 119 if (ni->ni_handler == NULL) { 120 printf("netisr_queue: unregistered isr %d\n", num); 121 return (EIO); 122 } 123 124 if (!(port = ni->ni_mport(m))) 125 return (EIO); 126 127 /* use better message allocation system with limits later XXX JH */ 128 if (!(pmsg = malloc(sizeof(struct netmsg_packet), M_LWKTMSG, M_NOWAIT))) 129 return (ENOBUFS); 130 131 lwkt_initmsg_rp(&pmsg->nm_lmsg, &netisr_afree_rport, CMD_NETMSG_NEWPKT); 132 pmsg->nm_packet = m; 133 pmsg->nm_handler = ni->ni_handler; 134 lwkt_sendmsg(port, &pmsg->nm_lmsg); 135 return (0); 136 } 137 138 void 139 netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler) 140 { 141 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 142 ("netisr_register: bad isr %d", num)); 143 144 netisrs[num].ni_mport = mportfn; 145 netisrs[num].ni_handler = handler; 146 } 147 148 int 149 netisr_unregister(int num) 150 { 151 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 152 ("unregister_netisr: bad isr number: %d\n", num)); 153 154 /* XXX JH */ 155 return (0); 156 } 157 158 /* 159 * Return message port for default handler thread on CPU 0. 160 */ 161 lwkt_port_t 162 cpu0_portfn(struct mbuf *m) 163 { 164 return (&netisr_cpu[0].td_msgport); 165 } 166 167 /* ARGSUSED */ 168 lwkt_port_t 169 cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused) 170 { 171 return (&netisr_cpu[0].td_msgport); 172 } 173 174 /* 175 * This function is used to call the netisr handler from the appropriate 176 * netisr thread for polling and other purposes. 177 */ 178 void 179 schednetisr(int num) 180 { 181 struct netisr *ni = &netisrs[num]; 182 struct netmsg *pmsg; 183 lwkt_port_t port = &netisr_cpu[0].td_msgport; 184 185 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 186 ("schednetisr: bad isr %d", num)); 187 188 if (!(pmsg = malloc(sizeof(struct netmsg), M_LWKTMSG, M_NOWAIT))) 189 return; 190 191 lwkt_initmsg_rp(&pmsg->nm_lmsg, &netisr_afree_rport, CMD_NETMSG_POLL); 192 pmsg->nm_handler = ni->ni_handler; 193 lwkt_sendmsg(port, &pmsg->nm_lmsg); 194 } 195