]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/kern_intr.c
This commit was generated by cvs2svn to compensate for changes in r95908,
[FreeBSD/FreeBSD.git] / sys / kern / kern_intr.c
1 /*
2  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  *
28  */
29
30
31 #include <sys/param.h>
32 #include <sys/bus.h>
33 #include <sys/rtprio.h>
34 #include <sys/systm.h>
35 #include <sys/interrupt.h>
36 #include <sys/kernel.h>
37 #include <sys/kthread.h>
38 #include <sys/ktr.h>
39 #include <sys/lock.h>
40 #include <sys/malloc.h>
41 #include <sys/mutex.h>
42 #include <sys/proc.h>
43 #include <sys/random.h>
44 #include <sys/resourcevar.h>
45 #include <sys/sysctl.h>
46 #include <sys/unistd.h>
47 #include <sys/vmmeter.h>
48 #include <machine/atomic.h>
49 #include <machine/cpu.h>
50 #include <machine/md_var.h>
51 #include <machine/stdarg.h>
52
53 #include <net/netisr.h>         /* prototype for legacy_setsoftnet */
54
55 struct  int_entropy {
56         struct  proc *proc;
57         int     vector;
58 };
59
60 void    *net_ih;
61 void    *vm_ih;
62 void    *softclock_ih;
63 struct  ithd *clk_ithd;
64 struct  ithd *tty_ithd;
65
66 static MALLOC_DEFINE(M_ITHREAD, "ithread", "Interrupt Threads");
67
68 static void     ithread_update(struct ithd *);
69 static void     ithread_loop(void *);
70 static void     start_softintr(void *);
71 static void     swi_net(void *);
72
73 u_char
74 ithread_priority(enum intr_type flags)
75 {
76         u_char pri;
77
78         flags &= (INTR_TYPE_TTY | INTR_TYPE_BIO | INTR_TYPE_NET |
79             INTR_TYPE_CAM | INTR_TYPE_MISC | INTR_TYPE_CLK | INTR_TYPE_AV);
80         switch (flags) {
81         case INTR_TYPE_TTY:
82                 pri = PI_TTYLOW;
83                 break;
84         case INTR_TYPE_BIO:
85                 /*
86                  * XXX We need to refine this.  BSD/OS distinguishes
87                  * between tape and disk priorities.
88                  */
89                 pri = PI_DISK;
90                 break;
91         case INTR_TYPE_NET:
92                 pri = PI_NET;
93                 break;
94         case INTR_TYPE_CAM:
95                 pri = PI_DISK;          /* XXX or PI_CAM? */
96                 break;
97         case INTR_TYPE_AV:              /* Audio/video */
98                 pri = PI_AV;
99                 break;
100         case INTR_TYPE_CLK:
101                 pri = PI_REALTIME;
102                 break;
103         case INTR_TYPE_MISC:
104                 pri = PI_DULL;          /* don't care */
105                 break;
106         default:
107                 /* We didn't specify an interrupt level. */
108                 panic("ithread_priority: no interrupt type in flags");
109         }
110
111         return pri;
112 }
113
114 /*
115  * Regenerate the name (p_comm) and priority for a threaded interrupt thread.
116  */
117 static void
118 ithread_update(struct ithd *ithd)
119 {
120         struct intrhand *ih;
121         struct thread *td;
122         struct proc *p;
123         int entropy;
124
125         mtx_assert(&ithd->it_lock, MA_OWNED);
126         td = ithd->it_td;
127         if (td == NULL)
128                 return;
129         p = td->td_proc;
130
131         strncpy(p->p_comm, ithd->it_name, sizeof(ithd->it_name));
132         ih = TAILQ_FIRST(&ithd->it_handlers);
133         if (ih == NULL) {
134                 mtx_lock_spin(&sched_lock);
135                 td->td_priority = PRI_MAX_ITHD;
136                 td->td_base_pri = PRI_MAX_ITHD;
137                 mtx_unlock_spin(&sched_lock);
138                 ithd->it_flags &= ~IT_ENTROPY;
139                 return;
140         }
141         entropy = 0;
142         mtx_lock_spin(&sched_lock);
143         td->td_priority = ih->ih_pri;
144         td->td_base_pri = ih->ih_pri;
145         mtx_unlock_spin(&sched_lock);
146         TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) {
147                 if (strlen(p->p_comm) + strlen(ih->ih_name) + 1 <
148                     sizeof(p->p_comm)) {
149                         strcat(p->p_comm, " ");
150                         strcat(p->p_comm, ih->ih_name);
151                 } else if (strlen(p->p_comm) + 1 == sizeof(p->p_comm)) {
152                         if (p->p_comm[sizeof(p->p_comm) - 2] == '+')
153                                 p->p_comm[sizeof(p->p_comm) - 2] = '*';
154                         else
155                                 p->p_comm[sizeof(p->p_comm) - 2] = '+';
156                 } else
157                         strcat(p->p_comm, "+");
158                 if (ih->ih_flags & IH_ENTROPY)
159                         entropy++;
160         }
161         if (entropy)
162                 ithd->it_flags |= IT_ENTROPY;
163         else
164                 ithd->it_flags &= ~IT_ENTROPY;
165         CTR2(KTR_INTR, "%s: updated %s\n", __func__, p->p_comm);
166 }
167
168 int
169 ithread_create(struct ithd **ithread, int vector, int flags,
170     void (*disable)(int), void (*enable)(int), const char *fmt, ...)
171 {
172         struct ithd *ithd;
173         struct thread *td;
174         struct proc *p;
175         int error;
176         va_list ap;
177
178         /* The only valid flag during creation is IT_SOFT. */
179         if ((flags & ~IT_SOFT) != 0)
180                 return (EINVAL);
181
182         ithd = malloc(sizeof(struct ithd), M_ITHREAD, M_WAITOK | M_ZERO);
183         ithd->it_vector = vector;
184         ithd->it_disable = disable;
185         ithd->it_enable = enable;
186         ithd->it_flags = flags;
187         TAILQ_INIT(&ithd->it_handlers);
188         mtx_init(&ithd->it_lock, "ithread", NULL, MTX_DEF);
189
190         va_start(ap, fmt);
191         vsnprintf(ithd->it_name, sizeof(ithd->it_name), fmt, ap);
192         va_end(ap);
193
194         error = kthread_create(ithread_loop, ithd, &p, RFSTOPPED | RFHIGHPID,
195             "%s", ithd->it_name);
196         if (error) {
197                 mtx_destroy(&ithd->it_lock);
198                 free(ithd, M_ITHREAD);
199                 return (error);
200         }
201         td = FIRST_THREAD_IN_PROC(p);   /* XXXKSE */
202         td->td_ksegrp->kg_pri_class = PRI_ITHD;
203         td->td_priority = PRI_MAX_ITHD;
204         p->p_stat = SWAIT;
205         ithd->it_td = td;
206         td->td_ithd = ithd;
207         if (ithread != NULL)
208                 *ithread = ithd;
209
210         CTR2(KTR_INTR, "%s: created %s", __func__, ithd->it_name);
211         return (0);
212 }
213
214 int
215 ithread_destroy(struct ithd *ithread)
216 {
217
218         struct thread *td;
219         struct proc *p;
220         if (ithread == NULL)
221                 return (EINVAL);
222
223         td = ithread->it_td;
224         p = td->td_proc;
225         mtx_lock(&ithread->it_lock);
226         if (!TAILQ_EMPTY(&ithread->it_handlers)) {
227                 mtx_unlock(&ithread->it_lock);
228                 return (EINVAL);
229         }
230         ithread->it_flags |= IT_DEAD;
231         mtx_lock_spin(&sched_lock);
232         if (p->p_stat == SWAIT) {
233                 p->p_stat = SRUN; /* XXXKSE */
234                 setrunqueue(td);
235         }
236         mtx_unlock_spin(&sched_lock);
237         mtx_unlock(&ithread->it_lock);
238         CTR2(KTR_INTR, "%s: killing %s", __func__, ithread->it_name);
239         return (0);
240 }
241
242 int
243 ithread_add_handler(struct ithd* ithread, const char *name,
244     driver_intr_t handler, void *arg, u_char pri, enum intr_type flags,
245     void **cookiep)
246 {
247         struct intrhand *ih, *temp_ih;
248
249         if (ithread == NULL || name == NULL || handler == NULL)
250                 return (EINVAL);
251         if ((flags & INTR_FAST) !=0)
252                 flags |= INTR_EXCL;
253
254         ih = malloc(sizeof(struct intrhand), M_ITHREAD, M_WAITOK | M_ZERO);
255         ih->ih_handler = handler;
256         ih->ih_argument = arg;
257         ih->ih_name = name;
258         ih->ih_ithread = ithread;
259         ih->ih_pri = pri;
260         if (flags & INTR_FAST)
261                 ih->ih_flags = IH_FAST | IH_EXCLUSIVE;
262         else if (flags & INTR_EXCL)
263                 ih->ih_flags = IH_EXCLUSIVE;
264         if (flags & INTR_MPSAFE)
265                 ih->ih_flags |= IH_MPSAFE;
266         if (flags & INTR_ENTROPY)
267                 ih->ih_flags |= IH_ENTROPY;
268
269         mtx_lock(&ithread->it_lock);
270         if ((flags & INTR_EXCL) !=0 && !TAILQ_EMPTY(&ithread->it_handlers))
271                 goto fail;
272         if (!TAILQ_EMPTY(&ithread->it_handlers) &&
273             (TAILQ_FIRST(&ithread->it_handlers)->ih_flags & IH_EXCLUSIVE) != 0)
274                 goto fail;
275
276         TAILQ_FOREACH(temp_ih, &ithread->it_handlers, ih_next)
277             if (temp_ih->ih_pri > ih->ih_pri)
278                     break;
279         if (temp_ih == NULL)
280                 TAILQ_INSERT_TAIL(&ithread->it_handlers, ih, ih_next);
281         else
282                 TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next);
283         ithread_update(ithread);
284         mtx_unlock(&ithread->it_lock);
285
286         if (cookiep != NULL)
287                 *cookiep = ih;
288         CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name,
289             ithread->it_name);
290         return (0);
291
292 fail:
293         mtx_unlock(&ithread->it_lock);
294         free(ih, M_ITHREAD);
295         return (EINVAL);
296 }
297
298 int
299 ithread_remove_handler(void *cookie)
300 {
301         struct intrhand *handler = (struct intrhand *)cookie;
302         struct ithd *ithread;
303 #ifdef INVARIANTS
304         struct intrhand *ih;
305 #endif
306
307         if (handler == NULL)
308                 return (EINVAL);
309         ithread = handler->ih_ithread;
310         KASSERT(ithread != NULL,
311             ("interrupt handler \"%s\" has a NULL interrupt thread",
312                 handler->ih_name));
313         CTR3(KTR_INTR, "%s: removing %s from %s", __func__, handler->ih_name,
314             ithread->it_name);
315         mtx_lock(&ithread->it_lock);
316 #ifdef INVARIANTS
317         TAILQ_FOREACH(ih, &ithread->it_handlers, ih_next)
318                 if (ih == handler)
319                         goto ok;
320         mtx_unlock(&ithread->it_lock);
321         panic("interrupt handler \"%s\" not found in interrupt thread \"%s\"",
322             ih->ih_name, ithread->it_name);
323 ok:
324 #endif
325         /*
326          * If the interrupt thread is already running, then just mark this
327          * handler as being dead and let the ithread do the actual removal.
328          */
329         mtx_lock_spin(&sched_lock);
330         if (ithread->it_td->td_proc->p_stat != SWAIT) {
331                 handler->ih_flags |= IH_DEAD;
332
333                 /*
334                  * Ensure that the thread will process the handler list
335                  * again and remove this handler if it has already passed
336                  * it on the list.
337                  */
338                 ithread->it_need = 1;
339         } else 
340                 TAILQ_REMOVE(&ithread->it_handlers, handler, ih_next);
341         mtx_unlock_spin(&sched_lock);
342         if ((handler->ih_flags & IH_DEAD) != 0)
343                 msleep(handler, &ithread->it_lock, PUSER, "itrmh", 0);
344         ithread_update(ithread);
345         mtx_unlock(&ithread->it_lock);
346         free(handler, M_ITHREAD);
347         return (0);
348 }
349
350 int
351 ithread_schedule(struct ithd *ithread, int do_switch)
352 {
353         struct int_entropy entropy;
354         struct thread *td;
355         struct proc *p;
356
357         /*
358          * If no ithread or no handlers, then we have a stray interrupt.
359          */
360         if ((ithread == NULL) || TAILQ_EMPTY(&ithread->it_handlers))
361                 return (EINVAL);
362
363         /*
364          * If any of the handlers for this ithread claim to be good
365          * sources of entropy, then gather some.
366          */
367         if (harvest.interrupt && ithread->it_flags & IT_ENTROPY) {
368                 entropy.vector = ithread->it_vector;
369                 entropy.proc = curthread->td_proc;;
370                 random_harvest(&entropy, sizeof(entropy), 2, 0,
371                     RANDOM_INTERRUPT);
372         }
373
374         td = ithread->it_td;
375         p = td->td_proc;
376         KASSERT(p != NULL, ("ithread %s has no process", ithread->it_name));
377         CTR4(KTR_INTR, "%s: pid %d: (%s) need = %d", __func__, p->p_pid, p->p_comm,
378             ithread->it_need);
379
380         /*
381          * Set it_need to tell the thread to keep running if it is already
382          * running.  Then, grab sched_lock and see if we actually need to
383          * put this thread on the runqueue.  If so and the do_switch flag is
384          * true and it is safe to switch, then switch to the ithread
385          * immediately.  Otherwise, set the needresched flag to guarantee
386          * that this ithread will run before any userland processes.
387          */
388         ithread->it_need = 1;
389         mtx_lock_spin(&sched_lock);
390         if (p->p_stat == SWAIT) {
391                 CTR2(KTR_INTR, "%s: setrunqueue %d", __func__, p->p_pid);
392                 p->p_stat = SRUN;
393                 setrunqueue(td); /* XXXKSE */
394                 if (do_switch && curthread->td_critnest == 1 &&
395                     curthread->td_proc->p_stat == SRUN) {
396                         if (curthread != PCPU_GET(idlethread))
397                                 setrunqueue(curthread);
398                         curthread->td_proc->p_stats->p_ru.ru_nivcsw++;
399                         mi_switch();
400                 } else
401                         curthread->td_kse->ke_flags |= KEF_NEEDRESCHED;
402         } else {
403                 CTR4(KTR_INTR, "%s: pid %d: it_need %d, state %d",
404                     __func__, p->p_pid, ithread->it_need, p->p_stat);
405         }
406         mtx_unlock_spin(&sched_lock);
407
408         return (0);
409 }
410
411 int
412 swi_add(struct ithd **ithdp, const char *name, driver_intr_t handler, 
413             void *arg, int pri, enum intr_type flags, void **cookiep)
414 {
415         struct ithd *ithd;
416         int error;
417
418         if (flags & (INTR_FAST | INTR_ENTROPY))
419                 return (EINVAL);
420
421         ithd = (ithdp != NULL) ? *ithdp : NULL;
422
423         if (ithd != NULL) {
424                 if ((ithd->it_flags & IT_SOFT) == 0)
425                         return(EINVAL);
426         } else {
427                 error = ithread_create(&ithd, pri, IT_SOFT, NULL, NULL,
428                     "swi%d:", pri);
429                 if (error)
430                         return (error);
431
432                 if (ithdp != NULL)
433                         *ithdp = ithd;
434         }
435         return (ithread_add_handler(ithd, name, handler, arg,
436                     (pri * RQ_PPQ) + PI_SOFT, flags, cookiep));
437 }
438
439
440 /*
441  * Schedule a heavyweight software interrupt process. 
442  */
443 void
444 swi_sched(void *cookie, int flags)
445 {
446         struct intrhand *ih = (struct intrhand *)cookie;
447         struct ithd *it = ih->ih_ithread;
448         int error;
449
450         atomic_add_int(&cnt.v_intr, 1); /* one more global interrupt */
451                 
452         CTR3(KTR_INTR, "swi_sched pid %d(%s) need=%d",
453                 it->it_td->td_proc->p_pid, it->it_td->td_proc->p_comm, it->it_need);
454
455         /*
456          * Set ih_need for this handler so that if the ithread is already
457          * running it will execute this handler on the next pass.  Otherwise,
458          * it will execute it the next time it runs.
459          */
460         atomic_store_rel_int(&ih->ih_need, 1);
461         if (!(flags & SWI_DELAY)) {
462                 error = ithread_schedule(it, !cold);
463                 KASSERT(error == 0, ("stray software interrupt"));
464         }
465 }
466
467 /*
468  * This is the main code for interrupt threads.
469  */
470 void
471 ithread_loop(void *arg)
472 {
473         struct ithd *ithd;              /* our thread context */
474         struct intrhand *ih;            /* and our interrupt handler chain */
475         struct thread *td;
476         struct proc *p;
477         
478         td = curthread;
479         p = td->td_proc;
480         ithd = (struct ithd *)arg;      /* point to myself */
481         KASSERT(ithd->it_td == td && td->td_ithd == ithd,
482             ("%s: ithread and proc linkage out of sync", __func__));
483
484         /*
485          * As long as we have interrupts outstanding, go through the
486          * list of handlers, giving each one a go at it.
487          */
488         for (;;) {
489                 /*
490                  * If we are an orphaned thread, then just die.
491                  */
492                 if (ithd->it_flags & IT_DEAD) {
493                         CTR3(KTR_INTR, "%s: pid %d: (%s) exiting", __func__,
494                             p->p_pid, p->p_comm);
495                         td->td_ithd = NULL;
496                         mtx_destroy(&ithd->it_lock);
497                         mtx_lock(&Giant);
498                         free(ithd, M_ITHREAD);
499                         kthread_exit(0);
500                 }
501
502                 CTR4(KTR_INTR, "%s: pid %d: (%s) need=%d", __func__,
503                      p->p_pid, p->p_comm, ithd->it_need);
504                 while (ithd->it_need) {
505                         /*
506                          * Service interrupts.  If another interrupt
507                          * arrives while we are running, they will set
508                          * it_need to denote that we should make
509                          * another pass.
510                          */
511                         atomic_store_rel_int(&ithd->it_need, 0);
512 restart:
513                         TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) {
514                                 if (ithd->it_flags & IT_SOFT && !ih->ih_need)
515                                         continue;
516                                 atomic_store_rel_int(&ih->ih_need, 0);
517                                 CTR6(KTR_INTR,
518                                     "%s: pid %d ih=%p: %p(%p) flg=%x", __func__,
519                                     p->p_pid, (void *)ih,
520                                     (void *)ih->ih_handler, ih->ih_argument,
521                                     ih->ih_flags);
522
523                                 if ((ih->ih_flags & IH_DEAD) != 0) {
524                                         mtx_lock(&ithd->it_lock);
525                                         TAILQ_REMOVE(&ithd->it_handlers, ih,
526                                             ih_next);
527                                         wakeup(ih);
528                                         mtx_unlock(&ithd->it_lock);
529                                         goto restart;
530                                 }
531                                 if ((ih->ih_flags & IH_MPSAFE) == 0)
532                                         mtx_lock(&Giant);
533                                 ih->ih_handler(ih->ih_argument);
534                                 if ((ih->ih_flags & IH_MPSAFE) == 0)
535                                         mtx_unlock(&Giant);
536                         }
537                 }
538
539                 /*
540                  * Processed all our interrupts.  Now get the sched
541                  * lock.  This may take a while and it_need may get
542                  * set again, so we have to check it again.
543                  */
544                 mtx_assert(&Giant, MA_NOTOWNED);
545                 mtx_lock_spin(&sched_lock);
546                 if (!ithd->it_need) {
547                         /*
548                          * Should we call this earlier in the loop above?
549                          */
550                         if (ithd->it_enable != NULL)
551                                 ithd->it_enable(ithd->it_vector);
552                         p->p_stat = SWAIT; /* we're idle */
553                         p->p_stats->p_ru.ru_nvcsw++;
554                         CTR2(KTR_INTR, "%s: pid %d: done", __func__, p->p_pid);
555                         mi_switch();
556                         CTR2(KTR_INTR, "%s: pid %d: resumed", __func__, p->p_pid);
557                 }
558                 mtx_unlock_spin(&sched_lock);
559         }
560 }
561
562 /*
563  * Start standard software interrupt threads
564  */
565 static void
566 start_softintr(void *dummy)
567 {
568
569         if (swi_add(NULL, "net", swi_net, NULL, SWI_NET, 0, &net_ih) ||
570             swi_add(&clk_ithd, "clock", softclock, NULL, SWI_CLOCK,
571                 INTR_MPSAFE, &softclock_ih) ||
572             swi_add(NULL, "vm", swi_vm, NULL, SWI_VM, 0, &vm_ih))
573                 panic("died while creating standard software ithreads");
574
575         PROC_LOCK(clk_ithd->it_td->td_proc);
576         clk_ithd->it_td->td_proc->p_flag |= P_NOLOAD;
577         PROC_UNLOCK(clk_ithd->it_td->td_proc);
578 }
579 SYSINIT(start_softintr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softintr, NULL)
580
581 void
582 legacy_setsoftnet(void)
583 {
584         swi_sched(net_ih, 0);
585 }
586
587 /*
588  * XXX: This should really be in the network code somewhere and installed
589  * via a SI_SUB_SOFINTR, SI_ORDER_MIDDLE sysinit.
590  */
591 void    (*netisrs[32])(void);
592 volatile unsigned int   netisr; /* scheduling bits for network */
593
594 int
595 register_netisr(num, handler)
596         int num;
597         netisr_t *handler;
598 {
599         
600         if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) {
601                 printf("register_netisr: bad isr number: %d\n", num);
602                 return (EINVAL);
603         }
604         netisrs[num] = handler;
605         return (0);
606 }
607
608 int
609 unregister_netisr(num)
610         int num;
611 {
612         
613         if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) {
614                 printf("unregister_netisr: bad isr number: %d\n", num);
615                 return (EINVAL);
616         }
617         netisrs[num] = NULL;
618         return (0);
619 }
620
621 #ifdef DEVICE_POLLING
622         void netisr_pollmore(void);
623 #endif
624
625 static void
626 swi_net(void *dummy)
627 {
628         u_int bits;
629         int i;
630
631 #ifdef DEVICE_POLLING
632     for (;;) {
633         int pollmore;
634 #endif
635         bits = atomic_readandclear_int(&netisr);
636 #ifdef DEVICE_POLLING
637         if (bits == 0)
638                 return;
639         pollmore = bits & (1 << NETISR_POLL);
640 #endif
641         while ((i = ffs(bits)) != 0) {
642                 i--;
643                 if (netisrs[i] != NULL)
644                         netisrs[i]();
645                 else
646                         printf("swi_net: unregistered isr number: %d.\n", i);
647                 bits &= ~(1 << i);
648         }
649 #ifdef DEVICE_POLLING
650         if (pollmore)
651                 netisr_pollmore();
652     }
653 #endif
654 }
655
656 /* 
657  * Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
658  * The data for this machine dependent, and the declarations are in machine
659  * dependent code.  The layout of intrnames and intrcnt however is machine
660  * independent.
661  *
662  * We do not know the length of intrcnt and intrnames at compile time, so
663  * calculate things at run time.
664  */
665 static int
666 sysctl_intrnames(SYSCTL_HANDLER_ARGS)
667 {
668         return (sysctl_handle_opaque(oidp, intrnames, eintrnames - intrnames, 
669            req));
670 }
671
672 SYSCTL_PROC(_hw, OID_AUTO, intrnames, CTLTYPE_OPAQUE | CTLFLAG_RD,
673     NULL, 0, sysctl_intrnames, "", "Interrupt Names");
674
675 static int
676 sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
677 {
678         return (sysctl_handle_opaque(oidp, intrcnt, 
679             (char *)eintrcnt - (char *)intrcnt, req));
680 }
681
682 SYSCTL_PROC(_hw, OID_AUTO, intrcnt, CTLTYPE_OPAQUE | CTLFLAG_RD,
683     NULL, 0, sysctl_intrcnt, "", "Interrupt Counts");