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.1/sys/powerpc/powerpc/intr_machdep.c 110180 2003-02-01 07:20:36Z 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 
  112         if (intr_initialized != 0)
  113                 panic("intr_init: interrupts intialized twice\n");
  114 
  115         intr_initialized++;
  116 
  117         intr_nirq = nirq;
  118         intr_handlers = malloc(nirq * sizeof(struct intr_handler), M_INTR,
  119             M_NOWAIT|M_ZERO);
  120         if (intr_handlers == NULL)
  121                 panic("intr_init: unable to allocate interrupt handler array");
  122         intr_stray_count = malloc(nirq * sizeof(u_long), M_INTR,
  123             M_NOWAIT|M_ZERO);
  124         if (intr_stray_count == NULL)
  125                 panic("intr_init: unable to allocate interrupt stray array");
  126 
  127         for (i = 0; i < nirq; i++) {
  128                 intr_handlers[i].ih_func = intr_stray_handler;
  129                 intr_handlers[i].ih_arg = &intr_handlers[i];
  130                 intr_handlers[i].ih_irq = i;
  131                 intr_handlers[i].ih_flags = 0;
  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, u_int flags)
  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         intr_handlers[irq].ih_flags = flags;
  159 
  160         mtmsr(msr);
  161 }
  162 
  163 int
  164 inthand_add(const char *name, u_int irq, void (*handler)(void *), void *arg,
  165     int flags, void **cookiep)
  166 {
  167         struct  intr_handler *ih;
  168         struct  ithd *ithd, *orphan;
  169         int     error = 0;
  170         int     created_ithd = 0;
  171 
  172         /*
  173          * Work around a race where more than one CPU may be registering
  174          * handlers on the same IRQ at the same time.
  175          */
  176         ih = &intr_handlers[irq];
  177         mtx_lock_spin(&intr_table_lock);
  178         ithd = ih->ih_ithd;
  179         mtx_unlock_spin(&intr_table_lock);
  180         if (ithd == NULL) {
  181                 error = ithread_create(&ithd, irq, 0, irq_disable,
  182                     irq_enable, "irq%d:", irq);
  183                 if (error)
  184                         return (error);
  185 
  186                 mtx_lock_spin(&intr_table_lock);
  187 
  188                 if (ih->ih_ithd == NULL) {
  189                         ih->ih_ithd = ithd;
  190                         created_ithd++;
  191                         mtx_unlock_spin(&intr_table_lock);
  192                 } else {
  193                         orphan = ithd;
  194                         ithd = ih->ih_ithd;
  195                         mtx_unlock_spin(&intr_table_lock);
  196                         ithread_destroy(orphan);
  197                 }
  198         }
  199 
  200         error = ithread_add_handler(ithd, name, handler, arg,
  201             ithread_priority(flags), flags, cookiep);
  202 
  203         if ((flags & INTR_FAST) == 0 || error) {
  204                 intr_setup(irq, sched_ithd, ih, flags);
  205                 error = 0;
  206         }
  207 
  208         if (error)
  209                 return (error);
  210 
  211         if (flags & INTR_FAST)
  212                 intr_setup(irq, handler, arg, flags);
  213 
  214         intr_stray_count[irq] = 0;
  215 
  216         return (0);
  217 }
  218 
  219 int
  220 inthand_remove(u_int irq, void *cookie)
  221 {
  222         struct  intr_handler *ih;
  223         int     error;
  224 
  225         error = ithread_remove_handler(cookie);
  226 
  227         if (error == 0) {
  228                 ih = &intr_handlers[irq];
  229 
  230                 mtx_lock_spin(&intr_table_lock);
  231 
  232                 if (ih->ih_ithd == NULL) {
  233                         intr_setup(irq, intr_stray_handler, ih, 0);
  234                 } else {
  235                         intr_setup(irq, sched_ithd, ih, 0);
  236                 }
  237 
  238                 mtx_unlock_spin(&intr_table_lock);
  239         }
  240 
  241         return (error);
  242 }
  243 
  244 void
  245 intr_handle(u_int irq)
  246 {
  247 
  248         intr_handlers[irq].ih_func(intr_handlers[irq].ih_arg);
  249         if ((intr_handlers[irq].ih_flags & INTR_FAST) != 0)
  250                 irq_enable(irq);
  251 }
  252 
  253 static void
  254 intr_stray_handler(void *cookie)
  255 {
  256         struct  intr_handler *ih;
  257 
  258         ih = (struct intr_handler *)cookie;
  259 
  260         if (intr_stray_count[ih->ih_irq] < MAX_STRAY_LOG) {
  261                 printf("stray irq %d\n", ih->ih_irq);
  262 
  263                 atomic_add_long(&intr_stray_count[ih->ih_irq], 1);
  264 
  265                 if (intr_stray_count[ih->ih_irq] >= MAX_STRAY_LOG)
  266                         printf("got %d stray irq %d's: not logging anymore\n",
  267                             MAX_STRAY_LOG, ih->ih_irq);
  268         }
  269 }
  270 
  271 static void
  272 sched_ithd(void *cookie)
  273 {
  274         struct  intr_handler *ih;
  275         int     error;
  276 
  277         ih = (struct intr_handler *)cookie;
  278 
  279         error = ithread_schedule(ih->ih_ithd, 0);
  280 
  281         if (error == EINVAL)
  282                 intr_stray_handler(ih);
  283 }

Cache object: 76755162eb3086b344edffba834fe6eb


[ 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.