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.7 2003/11/23 00:28:01 dillon Exp $ 7 */ 8 9 #include <sys/param.h> 10 #include <sys/systm.h> 11 #include <sys/kernel.h> 12 #include <sys/msgport.h> 13 #include <sys/msgport2.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 struct netmsg { 25 struct lwkt_msg nm_lmsg; 26 struct mbuf *nm_packet; 27 netisr_fn_t nm_handler; 28 }; 29 30 #define CMD_NETMSG_NEWPKT (MSG_CMD_NETMSG | 0x0001) 31 #define CMD_NETMSG_POLL (MSG_CMD_NETMSG | 0x0002) 32 33 static struct netisr netisrs[NETISR_MAX]; 34 35 /* Per-CPU thread to handle any protocol. */ 36 struct thread netisr_cpu[MAXCPU]; 37 38 static void 39 netisr_init(void) 40 { 41 int i; 42 43 /* Create default per-cpu threads for generic protocol handling. */ 44 for (i = 0; i < ncpus; ++i) 45 lwkt_create(netmsg_service_loop, NULL, NULL, &netisr_cpu[i], 0, i, 46 "netisr_cpu %d", i); 47 } 48 49 SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL); 50 51 void 52 netmsg_service_loop(void *arg) 53 { 54 struct netmsg *msg; 55 56 while ((msg = lwkt_waitport(&curthread->td_msgport, NULL))) { 57 struct mbuf *m = msg->nm_packet; 58 netisr_fn_t handler = msg->nm_handler; 59 60 if (handler) { 61 handler(m); 62 } else if (m) { 63 while (m->m_type == MT_TAG) 64 m = m->m_next; 65 KKASSERT(m != NULL); 66 m_freem(m); 67 } 68 free(msg, M_TEMP); 69 } 70 } 71 72 /* 73 * Call the netisr directly. 74 * Queueing may be done in the msg port layer at its discretion. 75 */ 76 void 77 netisr_dispatch(int num, struct mbuf *m) 78 { 79 /* just queue it for now XXX JH */ 80 netisr_queue(num, m); 81 } 82 83 /* 84 * Same as netisr_dispatch(), but always queue. 85 * This is either used in places where we are not confident that 86 * direct dispatch is possible, or where queueing is required. 87 */ 88 int 89 netisr_queue(int num, struct mbuf *m) 90 { 91 struct netisr *ni; 92 struct netmsg *pmsg; 93 lwkt_port_t port; 94 95 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 96 ("netisr_queue: bad isr %d", num)); 97 98 ni = &netisrs[num]; 99 if (ni->ni_handler == NULL) { 100 printf("netisr_queue: unregistered isr %d\n", num); 101 return EIO; 102 } 103 104 /* use better message allocation system with limits later XXX JH */ 105 if (!(pmsg = malloc(sizeof(struct netmsg), M_TEMP, M_NOWAIT))) 106 return ENOBUFS; 107 108 if (!(port = ni->ni_mport(m))) 109 return EIO; 110 111 lwkt_initmsg(&pmsg->nm_lmsg, port, CMD_NETMSG_NEWPKT); 112 pmsg->nm_packet = m; 113 pmsg->nm_handler = ni->ni_handler; 114 lwkt_sendmsg(port, &pmsg->nm_lmsg); 115 return (0); 116 } 117 118 void 119 netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler) 120 { 121 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 122 ("netisr_register: bad isr %d", num)); 123 124 netisrs[num].ni_mport = mportfn; 125 netisrs[num].ni_handler = handler; 126 } 127 128 int 129 netisr_unregister(int num) 130 { 131 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 132 ("unregister_netisr: bad isr number: %d\n", num)); 133 134 /* XXX JH */ 135 return (0); 136 } 137 138 /* 139 * Return message port for default handler thread on CPU 0. 140 */ 141 lwkt_port_t 142 cpu0_portfn(struct mbuf *m) 143 { 144 return (&netisr_cpu[0].td_msgport); 145 } 146 147 /* 148 * This function is used to call the netisr handler from the appropriate 149 * netisr thread for polling and other purposes. pmsg->nm_packet will be 150 * undefined. At the moment operation is restricted to non-packet ISRs only. 151 */ 152 void 153 schednetisr(int num) 154 { 155 struct netisr *ni = &netisrs[num]; 156 struct netmsg *pmsg; 157 lwkt_port_t port = &netisr_cpu[0].td_msgport; 158 159 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 160 ("schednetisr: bad isr %d", num)); 161 162 if (!(pmsg = malloc(sizeof(struct netmsg), M_TEMP, M_NOWAIT))) 163 return; 164 165 lwkt_initmsg(&pmsg->nm_lmsg, port, CMD_NETMSG_POLL); 166 pmsg->nm_handler = ni->ni_handler; 167 lwkt_sendmsg(port, &pmsg->nm_lmsg); 168 } 169