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 } 174