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.2 2003/09/15 23:38:13 hsu Exp $ 7 */ 8 9 #include <sys/param.h> 10 #include <sys/systm.h> 11 #include <sys/proc.h> 12 #include <sys/interrupt.h> 13 #include <sys/socket.h> 14 #include <sys/sysctl.h> 15 #include <net/if.h> 16 #include <net/if_var.h> 17 #include <net/netisr.h> 18 #include <machine/cpufunc.h> 19 #include <machine/ipl.h> 20 21 int isrmask; 22 static int isrsoftint_installed; 23 static struct netisr netisrs[NETISR_MAX]; 24 25 /* SYSCTL_NODE(_net, OID_AUTO, isr, CTLFLAG_RW, 0, "netisr counters"); */ 26 27 static int netisr_directdispatch = 0; 28 /* 29 SYSCTL_INT(_net_isr, OID_AUTO, directdispatch, CTLFLAG_RW, 30 &netisr_directdispatch, 0, "enable direct dispatch"); 31 */ 32 33 static void 34 swi_net(void *arg) 35 { 36 int mask; 37 int bit; 38 39 while ((mask = isrmask) != 0) { 40 bit = bsfl(mask); 41 if (btrl(&isrmask, bit)) { 42 struct netisr *ni = &netisrs[bit]; 43 netisr_fn_t func = ni->ni_handler; 44 45 if (ni->ni_queue) { 46 while (1) { 47 struct mbuf *m; 48 int s; 49 50 s = splimp(); 51 IF_DEQUEUE(ni->ni_queue, m); 52 splx(s); 53 if (!m) 54 break; 55 func(m); 56 } 57 } else 58 func(NULL); 59 } 60 } 61 } 62 63 /* 64 * Call the netisr directly instead of queueing the packet, if possible. 65 */ 66 void 67 netisr_dispatch(int num, struct mbuf *m) 68 { 69 struct netisr *ni; 70 71 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 72 ("bad isr %d", num)); 73 74 ni = &netisrs[num]; 75 76 if (!ni->ni_queue) { 77 m_freem(m); 78 return; 79 } 80 81 if (netisr_directdispatch) { 82 /* 83 * missing check for concurrent execution from swi_net() XXX JH 84 * Address this after conversion to message ports. 85 */ 86 ni->ni_handler(m); 87 } else { 88 if (IF_HANDOFF(ni->ni_queue, m, NULL)) 89 schednetisr(num); 90 } 91 } 92 93 /* 94 * Same as netisr_dispatch(), but always queue. 95 * This is either used in places where we are not confident that 96 * direct dispatch is possible, or where queueing is required. 97 */ 98 int 99 netisr_queue(int num, struct mbuf *m) 100 { 101 struct netisr *ni; 102 103 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 104 ("bad isr %d", num)); 105 106 ni = &netisrs[num]; 107 108 if (!ni->ni_queue) { 109 m_freem(m); 110 return (ENOBUFS); 111 } 112 113 if (!IF_HANDOFF(ni->ni_queue, m, NULL)) 114 return (ENOBUFS); 115 116 schednetisr(num); 117 return (0); 118 } 119 120 int 121 netisr_register(int num, netisr_fn_t handler, struct ifqueue *ifq) 122 { 123 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 124 ("bad isr %d", num)); 125 126 if (isrsoftint_installed == 0) { 127 isrsoftint_installed = 1; 128 register_swi(SWI_NET, swi_net, NULL, "swi_net"); 129 } 130 netisrs[num].ni_handler = handler; 131 netisrs[num].ni_queue = ifq; 132 return (0); 133 } 134 135 int 136 netisr_unregister(int num) 137 { 138 KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))), 139 ("unregister_netisr: bad isr number: %d\n", num)); 140 141 if (netisrs[num].ni_queue != NULL) { 142 int s; 143 144 s = splimp(); 145 IF_DRAIN(netisrs[num].ni_queue); 146 splx(s); 147 } 148 netisrs[num].ni_handler = NULL; 149 return (0); 150 } 151