The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/powerpc/intr_machdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1991 The Regents of the University of California.
    3  * All rights reserved.
    4  *
    5  * This code is derived from software contributed to Berkeley by
    6  * William Jolitz.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  */
   36 /*-
   37  * Copyright (c) 2002 Benno Rice.
   38  * All rights reserved.
   39  *
   40  * Redistribution and use in source and binary forms, with or without
   41  * modification, are permitted provided that the following conditions
   42  * are met:
   43  * 1. Redistributions of source code must retain the above copyright
   44  *    notice, this list of conditions and the following disclaimer.
   45  * 2. Redistributions in binary form must reproduce the above copyright
   46  *    notice, this list of conditions and the following disclaimer in the
   47  *    documentation and/or other materials provided with the distribution.
   48  *
   49  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   59  * SUCH DAMAGE.
   60  *
   61  *      from: @(#)isa.c 7.2 (Berkeley) 5/13/91
   62  *      form: src/sys/i386/isa/intr_machdep.c,v 1.57 2001/07/20
   63  *
   64  * $FreeBSD: releng/5.0/sys/powerpc/powerpc/intr_machdep.c 99651 2002-07-09 11:12:20Z benno $
   65  */
   66 
   67 #include <sys/param.h>
   68 #include <sys/systm.h>
   69 #include <sys/kernel.h>
   70 #include <sys/queue.h>
   71 #include <sys/bus.h>
   72 #include <sys/interrupt.h>
   73 #include <sys/lock.h>
   74 #include <sys/malloc.h>
   75 #include <sys/mutex.h>
   76 #include <sys/pcpu.h>
   77 #include <sys/vmmeter.h>
   78 
   79 #include <machine/frame.h>
   80 #include <machine/interruptvar.h>
   81 #include <machine/intr_machdep.h>
   82 #include <machine/trap.h>
   83 
   84 #define MAX_STRAY_LOG   5
   85 
   86 MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
   87 
   88 static int      intr_initialized = 0;
   89 
   90 static u_int            intr_nirq;
   91 static struct           intr_handler *intr_handlers;
   92 static u_long           *intr_stray_count;
   93 
   94 static struct           mtx intr_table_lock;
   95 
   96 extern int      extint, extsize;
   97 extern u_long   extint_call;
   98 
   99 static ih_func_t        intr_stray_handler;
  100 static ih_func_t        sched_ithd;
  101 
  102 static void             (*irq_enable)(int);
  103 static void             (*irq_disable)(int);
  104 
  105 void
  106 intr_init(void (*handler)(void), int nirq, void (*irq_e)(int),
  107     void (*irq_d)(int))
  108 {
  109         int             i;
  110         u_int32_t       msr;
  111         u_long          offset;
  112 
  113         if (intr_initialized != 0)
  114                 panic("intr_init: interrupts intialized twice\n");
  115 
  116         intr_initialized++;
  117 
  118         intr_nirq = nirq;
  119         intr_handlers = malloc(nirq * sizeof(struct intr_handler), M_INTR,
  120             M_NOWAIT|M_ZERO);
  121         if (intr_handlers == NULL)
  122                 panic("intr_init: unable to allocate interrupt handler array");
  123         intr_stray_count = malloc(nirq * sizeof(u_long), M_INTR,
  124             M_NOWAIT|M_ZERO);
  125         if (intr_stray_count == NULL)
  126                 panic("intr_init: unable to allocate interrupt stray array");
  127 
  128         for (i = 0; i < nirq; i++) {
  129                 intr_handlers[i].ih_func = intr_stray_handler;
  130                 intr_handlers[i].ih_arg = &intr_handlers[i];
  131                 intr_handlers[i].ih_irq = i;
  132         }
  133 
  134         msr = mfmsr();
  135         mtmsr(msr & ~PSL_EE);
  136 
  137         ext_intr_install(handler);
  138 
  139         mtmsr(msr);
  140 
  141         irq_enable = irq_e;
  142         irq_disable = irq_d;
  143 
  144         mtx_init(&intr_table_lock, "ithread table lock", NULL, MTX_SPIN);
  145 }
  146 
  147 void
  148 intr_setup(u_int irq, ih_func_t *ihf, void *iha)
  149 {
  150         u_int32_t       msr;
  151 
  152         msr = mfmsr();
  153         mtmsr(msr & ~PSL_EE);
  154 
  155         intr_handlers[irq].ih_func = ihf;
  156         intr_handlers[irq].ih_arg = iha;
  157         intr_handlers[irq].ih_irq = irq;
  158 
  159         mtmsr(msr);
  160 }
  161 
  162 int
  163 inthand_add(const char *name, u_int irq, void (*handler)(void *), void *arg,
  164     int flags, void **cookiep)
  165 {
  166         struct  intr_handler *ih;
  167         struct  ithd *ithd, *orphan;
  168         int     error = 0;
  169         int     created_ithd = 0;
  170 
  171         /*
  172          * Work around a race where more than one CPU may be registering
  173          * handlers on the same IRQ at the same time.
  174          */
  175         ih = &intr_handlers[irq];
  176         mtx_lock_spin(&intr_table_lock);
  177         ithd = ih->ih_ithd;
  178         mtx_unlock_spin(&intr_table_lock);
  179         if (ithd == NULL) {
  180                 error = ithread_create(&ithd, irq, 0, irq_disable,
  181                     irq_enable, "irq%d:", irq);
  182                 if (error)
  183                         return (error);
  184 
  185                 mtx_lock_spin(&intr_table_lock);
  186 
  187                 if (ih->ih_ithd == NULL) {
  188                         ih->ih_ithd = ithd;
  189                         created_ithd++;
  190                         mtx_unlock_spin(&intr_table_lock);
  191                 } else {
  192                         orphan = ithd;
  193                         ithd = ih->ih_ithd;
  194                         mtx_unlock_spin(&intr_table_lock);
  195                         ithread_destroy(orphan);
  196                 }
  197         }
  198 
  199         error = ithread_add_handler(ithd, name, handler, arg,
  200             ithread_priority(flags), flags, cookiep);
  201 
  202         if ((flags & INTR_FAST) == 0 || error) {
  203                 intr_setup(irq, sched_ithd, ih);
  204                 error = 0;
  205         }
  206 
  207         if (error)
  208                 return (error);
  209 
  210         if (flags & INTR_FAST)
  211                 intr_setup(irq, handler, arg);
  212 
  213         intr_stray_count[irq] = 0;
  214 
  215         return (0);
  216 }
  217 
  218 int
  219 inthand_remove(u_int irq, void *cookie)
  220 {
  221         struct  intr_handler *ih;
  222         int     error;
  223 
  224         error = ithread_remove_handler(cookie);
  225 
  226         if (error == 0) {
  227                 ih = &intr_handlers[irq];
  228 
  229                 mtx_lock_spin(&intr_table_lock);
  230 
  231                 if (ih->ih_ithd == NULL) {
  232                         intr_setup(irq, intr_stray_handler, ih);
  233                 } else {
  234                         intr_setup(irq, sched_ithd, ih);
  235                 }
  236 
  237                 mtx_unlock_spin(&intr_table_lock);
  238         }
  239 
  240         return (error);
  241 }
  242 
  243 void
  244 intr_handle(u_int irq)
  245 {
  246 
  247         intr_handlers[irq].ih_func(intr_handlers[irq].ih_arg);
  248 }
  249 
  250 static void
  251 intr_stray_handler(void *cookie)
  252 {
  253         struct  intr_handler *ih;
  254 
  255         ih = (struct intr_handler *)cookie;
  256 
  257         if (intr_stray_count[ih->ih_irq] < MAX_STRAY_LOG) {
  258                 printf("stray irq %d\n", ih->ih_irq);
  259 
  260                 atomic_add_long(&intr_stray_count[ih->ih_irq], 1);
  261 
  262                 if (intr_stray_count[ih->ih_irq] >= MAX_STRAY_LOG)
  263                         printf("got %d stray irq %d's: not logging anymore\n",
  264                             MAX_STRAY_LOG, ih->ih_irq);
  265         }
  266 }
  267 
  268 static void
  269 sched_ithd(void *cookie)
  270 {
  271         struct  intr_handler *ih;
  272         int     error;
  273 
  274         ih = (struct intr_handler *)cookie;
  275 
  276         error = ithread_schedule(ih->ih_ithd, 0);
  277 
  278         if (error == EINVAL)
  279                 intr_stray_handler(ih);
  280 }

Cache object: 4f3563ac3058fe5b089a5a470a3ac891


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.