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.11 2004/04/09 22:34:09 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 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 64 while ((msg = lwkt_waitport(&curthread->td_msgport, NULL))) 65 msg->nm_handler(msg); 66 } 67 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); 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 */ 84 int 85 netisr_queue(int num, struct mbuf *m) 86 { 87 struct netisr *ni; 88 struct netmsg_packet *pmsg; 89 lwkt_port_t port; 90 91 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 92 ("netisr_queue: bad isr %d", num)); 93 94 ni = &netisrs[num]; 95 if (ni->ni_handler == NULL) { 96 printf("netisr_queue: unregistered isr %d\n", num); 97 return (EIO); 98 } 99 100 if (!(port = ni->ni_mport(m))) 101 return (EIO); 102 103 /* use better message allocation system with limits later XXX JH */ 104 if (!(pmsg = malloc(sizeof(struct netmsg_packet), M_LWKTMSG, M_NOWAIT))) 105 return (ENOBUFS); 106 107 lwkt_initmsg_rp(&pmsg->nm_lmsg, &netisr_afree_rport, CMD_NETMSG_NEWPKT); 108 pmsg->nm_packet = m; 109 pmsg->nm_handler = ni->ni_handler; 110 lwkt_sendmsg(port, &pmsg->nm_lmsg); 111 return (0); 112 } 113 114 void 115 netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler) 116 { 117 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 118 ("netisr_register: bad isr %d", num)); 119 120 netisrs[num].ni_mport = mportfn; 121 netisrs[num].ni_handler = handler; 122 } 123 124 int 125 netisr_unregister(int num) 126 { 127 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 128 ("unregister_netisr: bad isr number: %d\n", num)); 129 130 /* XXX JH */ 131 return (0); 132 } 133 134 /* 135 * Return message port for default handler thread on CPU 0. 136 */ 137 lwkt_port_t 138 cpu0_portfn(struct mbuf *m) 139 { 140 return (&netisr_cpu[0].td_msgport); 141 } 142 143 /* ARGSUSED */ 144 lwkt_port_t 145 cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused) 146 { 147 return (&netisr_cpu[0].td_msgport); 148 } 149 150 /* 151 * This function is used to call the netisr handler from the appropriate 152 * netisr thread for polling and other purposes. 153 */ 154 void 155 schednetisr(int num) 156 { 157 struct netisr *ni = &netisrs[num]; 158 struct netmsg *pmsg; 159 lwkt_port_t port = &netisr_cpu[0].td_msgport; 160 161 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 162 ("schednetisr: bad isr %d", num)); 163 164 if (!(pmsg = malloc(sizeof(struct netmsg), M_LWKTMSG, M_NOWAIT))) 165 return; 166 167 lwkt_initmsg_rp(&pmsg->nm_lmsg, &netisr_afree_rport, CMD_NETMSG_POLL); 168 pmsg->nm_handler = ni->ni_handler; 169 lwkt_sendmsg(port, &pmsg->nm_lmsg); 170 } 171