Author: gonzo
Date: Mon Mar 12 01:23:09 2012
New Revision: 232847
URL: http://svn.freebsd.org/changeset/base/232847

Log:
  - Rename apb_intr to apb_filter since it's a filter handler
  - Pass interrupt trapframe for handlers dow the chain
  - Add PMC interrupt handler
      PMC interrupt is a special case, so we want handle it as soon as possible
      with minimum overhead. So we handle it apb filter routine.

Modified:
  head/sys/mips/atheros/apb.c

Modified: head/sys/mips/atheros/apb.c
==============================================================================
--- head/sys/mips/atheros/apb.c Mon Mar 12 01:19:41 2012        (r232846)
+++ head/sys/mips/atheros/apb.c Mon Mar 12 01:23:09 2012        (r232847)
@@ -36,6 +36,10 @@ __FBSDID("$FreeBSD$");
 #include <sys/module.h>
 #include <sys/rman.h>
 #include <sys/malloc.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/pmc.h>
+#include <sys/pmckern.h>
 
 #include <machine/bus.h>
 #include <machine/intr_machdep.h>
@@ -44,6 +48,8 @@ __FBSDID("$FreeBSD$");
 #include <mips/atheros/ar71xxreg.h>
 #include <mips/atheros/ar71xx_setup.h>
 
+#define        APB_INTR_PMC    5
+
 #undef APB_DEBUG
 #ifdef APB_DEBUG
 #define dprintf printf
@@ -63,7 +69,7 @@ static int    apb_deactivate_resource(devic
 static struct resource_list *
                apb_get_resource_list(device_t, device_t);
 static void    apb_hinted_child(device_t, const char *, int);
-static int     apb_intr(void *);
+static int     apb_filter(void *);
 static int     apb_probe(device_t);
 static int     apb_release_resource(device_t, device_t, int, int,
                    struct resource *);
@@ -132,7 +138,7 @@ apb_attach(device_t dev)
        }
 
        if ((bus_setup_intr(dev, sc->sc_misc_irq, INTR_TYPE_MISC, 
-           apb_intr, NULL, sc, &sc->sc_misc_ih))) {
+           apb_filter, NULL, sc, &sc->sc_misc_ih))) {
                device_printf(dev,
                    "WARNING: unable to register interrupt handler\n");
                return (ENXIO);
@@ -142,6 +148,12 @@ apb_attach(device_t dev)
        bus_enumerate_hinted_children(dev);
        bus_generic_attach(dev);
 
+       /*
+        * Unmask performance counter IRQ
+        */
+       apb_unmask_irq((void*)APB_INTR_PMC);
+       sc->sc_intr_counter[APB_INTR_PMC] = mips_intrcnt_create("apb irq5: 
pmc");
+
        return (0);
 }
 
@@ -329,11 +341,12 @@ apb_teardown_intr(device_t dev, device_t
 }
 
 static int
-apb_intr(void *arg)
+apb_filter(void *arg)
 {
        struct apb_softc *sc = arg;
        struct intr_event *event;
        uint32_t reg, irq;
+       struct thread *td;
 
        reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS);
        for (irq = 0; irq < APB_NIRQS; irq++) {
@@ -354,14 +367,34 @@ apb_intr(void *arg)
 
                        event = sc->sc_eventstab[irq];
                        if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
+                               if (irq == APB_INTR_PMC) {
+                                       register_t s;
+                                       struct trapframe *tf = 
PCPU_GET(curthread)->td_intr_frame;
+                                       s = intr_disable();
+                                       
mips_intrcnt_inc(sc->sc_intr_counter[irq]);
+
+                                       if (pmc_intr && 
(*pmc_intr)(PCPU_GET(cpuid), tf)) {
+                                               intr_restore(s);
+                                               continue;
+                                       }
+
+                                       intr_restore(s);
+                                       td = PCPU_GET(curthread);
+
+                                       if (pmc_hook && (td->td_pflags & 
TDP_CALLCHAIN))
+                                               pmc_hook(PCPU_GET(curthread),
+                                                       PMC_FN_USER_CALLCHAIN, 
tf);
+                               
+                                       continue;
+
+                               }
                                /* Ignore timer interrupts */
                                if (irq != 0)
                                        printf("Stray APB IRQ %d\n", irq);
                                continue;
                        }
 
-                       /* TODO: frame instead of NULL? */
-                       intr_event_handle(event, NULL);
+                       intr_event_handle(event, 
PCPU_GET(curthread)->td_intr_frame);
                        mips_intrcnt_inc(sc->sc_intr_counter[irq]);
                }
        }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to