summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_intr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/subr_intr.c')
-rw-r--r--sys/kern/subr_intr.c534
1 files changed, 278 insertions, 256 deletions
diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c
index 1c97fd4..96319ad 100644
--- a/sys/kern/subr_intr.c
+++ b/sys/kern/subr_intr.c
@@ -1,7 +1,6 @@
/*-
- * Copyright (c) 2012-2014 Jakub Wojciech Klama <jceel@FreeBSD.org>.
- * Copyright (c) 2015 Svatopluk Kraus
- * Copyright (c) 2015 Michal Meloun
+ * Copyright (c) 2015-2016 Svatopluk Kraus
+ * Copyright (c) 2015-2016 Michal Meloun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,8 +23,6 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD$
*/
#include <sys/cdefs.h>
@@ -38,6 +35,7 @@ __FBSDID("$FreeBSD$");
* - to complete things for removable PICs
*/
+#include "opt_acpi.h"
#include "opt_ddb.h"
#include "opt_platform.h"
@@ -52,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/interrupt.h>
#include <sys/conf.h>
#include <sys/cpuset.h>
+#include <sys/rman.h>
#include <sys/sched.h>
#include <sys/smp.h>
#include <machine/atomic.h>
@@ -112,6 +111,35 @@ u_int irq_next_free;
#define IRQ_INVALID nitems(irq_sources)
+/*
+ * XXX - All stuff around struct intr_dev_data is considered as temporary
+ * until better place for storing struct intr_map_data will be find.
+ *
+ * For now, there are two global interrupt numbers spaces:
+ * <0, NIRQ) ... interrupts without config data
+ * managed in irq_sources[]
+ * IRQ_DDATA_BASE + <0, 2 * NIRQ) ... interrupts with config data
+ * managed in intr_ddata_tab[]
+ *
+ * Read intr_ddata_lookup() to see how these spaces are worked with.
+ * Note that each interrupt number from second space duplicates some number
+ * from first space at this moment. An interrupt number from first space can
+ * be duplicated even multiple times in second space.
+ */
+struct intr_dev_data {
+ device_t idd_dev;
+ intptr_t idd_xref;
+ u_int idd_irq;
+ struct intr_map_data idd_data;
+ struct intr_irqsrc * idd_isrc;
+};
+
+static struct intr_dev_data *intr_ddata_tab[2 * NIRQ];
+static u_int intr_ddata_first_unused;
+
+#define IRQ_DDATA_BASE 10000
+CTASSERT(IRQ_DDATA_BASE > IRQ_INVALID);
+
#ifdef SMP
static boolean_t irq_assign_cpu = FALSE;
#endif
@@ -173,12 +201,10 @@ static inline void
isrc_increment_count(struct intr_irqsrc *isrc)
{
- /*
- * XXX - It should be atomic for PPI interrupts. It was proven that
- * the lost is measurable easily for timer PPI interrupts.
- */
- isrc->isrc_count[0]++;
- /*atomic_add_long(&isrc->isrc_count[0], 1);*/
+ if (isrc->isrc_flags & INTR_ISRCF_PPI)
+ atomic_add_long(&isrc->isrc_count[0], 1);
+ else
+ isrc->isrc_count[0]++;
}
/*
@@ -233,6 +259,16 @@ isrc_setup_counters(struct intr_irqsrc *isrc)
isrc_update_name(isrc, NULL);
}
+/*
+ * Virtualization for interrupt source interrupt counters release.
+ */
+static void
+isrc_release_counters(struct intr_irqsrc *isrc)
+{
+
+ panic("%s: not implemented", __func__);
+}
+
#ifdef SMP
/*
* Virtualization for interrupt source IPI counters setup.
@@ -279,8 +315,8 @@ intr_irq_handler(struct trapframe *tf)
* be called straight from the interrupt controller, when associated interrupt
* source is learned.
*/
-void
-intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
+int
+intr_isrc_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
{
KASSERT(isrc != NULL, ("%s: no source", __func__));
@@ -293,57 +329,16 @@ intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
error = isrc->isrc_filter(isrc->isrc_arg, tf);
PIC_POST_FILTER(isrc->isrc_dev, isrc);
if (error == FILTER_HANDLED)
- return;
- } else
+ return (0);
+ } else
#endif
if (isrc->isrc_event != NULL) {
if (intr_event_handle(isrc->isrc_event, tf) == 0)
- return;
+ return (0);
}
isrc_increment_straycount(isrc);
- PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc);
-
- device_printf(isrc->isrc_dev, "stray irq <%s> disabled",
- isrc->isrc_name);
-}
-
-/*
- * Allocate interrupt source.
- */
-static struct intr_irqsrc *
-isrc_alloc(u_int type, u_int extsize)
-{
- struct intr_irqsrc *isrc;
-
- isrc = malloc(sizeof(*isrc) + extsize, M_INTRNG, M_WAITOK | M_ZERO);
- isrc->isrc_irq = IRQ_INVALID; /* just to be safe */
- isrc->isrc_type = type;
- isrc->isrc_nspc_type = INTR_IRQ_NSPC_NONE;
- isrc->isrc_trig = INTR_TRIGGER_CONFORM;
- isrc->isrc_pol = INTR_POLARITY_CONFORM;
- CPU_ZERO(&isrc->isrc_cpu);
- return (isrc);
-}
-
-/*
- * Free interrupt source.
- */
-static void
-isrc_free(struct intr_irqsrc *isrc)
-{
-
- free(isrc, M_INTRNG);
-}
-
-void
-intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(isrc->isrc_name, INTR_ISRC_NAMELEN, fmt, ap);
- va_end(ap);
+ return (EINVAL);
}
/*
@@ -356,8 +351,8 @@ intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
* immediately. However, if only one free handle left which is reused
* constantly...
*/
-static int
-isrc_alloc_irq_locked(struct intr_irqsrc *isrc)
+static inline int
+isrc_alloc_irq(struct intr_irqsrc *isrc)
{
u_int maxirqs, irq;
@@ -383,46 +378,35 @@ found:
isrc->isrc_irq = irq;
irq_sources[irq] = isrc;
- intr_irq_set_name(isrc, "irq%u", irq);
- isrc_setup_counters(isrc);
-
irq_next_free = irq + 1;
if (irq_next_free >= maxirqs)
irq_next_free = 0;
return (0);
}
-#ifdef notyet
+
/*
* Free unique interrupt number (resource handle) from interrupt source.
*/
-static int
+static inline int
isrc_free_irq(struct intr_irqsrc *isrc)
{
- u_int maxirqs;
- mtx_assert(&isrc_table_lock, MA_NOTOWNED);
+ mtx_assert(&isrc_table_lock, MA_OWNED);
- maxirqs = nitems(irq_sources);
- if (isrc->isrc_irq >= maxirqs)
+ if (isrc->isrc_irq >= nitems(irq_sources))
return (EINVAL);
-
- mtx_lock(&isrc_table_lock);
- if (irq_sources[isrc->isrc_irq] != isrc) {
- mtx_unlock(&isrc_table_lock);
+ if (irq_sources[isrc->isrc_irq] != isrc)
return (EINVAL);
- }
irq_sources[isrc->isrc_irq] = NULL;
isrc->isrc_irq = IRQ_INVALID; /* just to be safe */
- mtx_unlock(&isrc_table_lock);
-
return (0);
}
-#endif
+
/*
* Lookup interrupt source by interrupt number (resource handle).
*/
-static struct intr_irqsrc *
+static inline struct intr_irqsrc *
isrc_lookup(u_int irq)
{
@@ -432,158 +416,159 @@ isrc_lookup(u_int irq)
}
/*
- * Lookup interrupt source by namespace description.
+ * Initialize interrupt source and register it into global interrupt table.
*/
-static struct intr_irqsrc *
-isrc_namespace_lookup(device_t dev, uint16_t type, uint16_t num)
+int
+intr_isrc_register(struct intr_irqsrc *isrc, device_t dev, u_int flags,
+ const char *fmt, ...)
{
- u_int irq;
- struct intr_irqsrc *isrc;
+ int error;
+ va_list ap;
- mtx_assert(&isrc_table_lock, MA_OWNED);
+ bzero(isrc, sizeof(struct intr_irqsrc));
+ isrc->isrc_dev = dev;
+ isrc->isrc_irq = IRQ_INVALID; /* just to be safe */
+ isrc->isrc_flags = flags;
+
+ va_start(ap, fmt);
+ vsnprintf(isrc->isrc_name, INTR_ISRC_NAMELEN, fmt, ap);
+ va_end(ap);
- for (irq = 0; irq < nitems(irq_sources); irq++) {
- isrc = irq_sources[irq];
- if (isrc != NULL && isrc->isrc_dev == dev &&
- isrc->isrc_nspc_type == type && isrc->isrc_nspc_num == num)
- return (isrc);
+ mtx_lock(&isrc_table_lock);
+ error = isrc_alloc_irq(isrc);
+ if (error != 0) {
+ mtx_unlock(&isrc_table_lock);
+ return (error);
}
- return (NULL);
+ /*
+ * Setup interrupt counters, but not for IPI sources. Those are setup
+ * later and only for used ones (up to INTR_IPI_COUNT) to not exhaust
+ * our counter pool.
+ */
+ if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
+ isrc_setup_counters(isrc);
+ mtx_unlock(&isrc_table_lock);
+ return (0);
}
/*
- * Map interrupt source according to namespace into framework. If such mapping
- * does not exist, create it. Return unique interrupt number (resource handle)
- * associated with mapped interrupt source.
+ * Deregister interrupt source from global interrupt table.
*/
-u_int
-intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num)
+int
+intr_isrc_deregister(struct intr_irqsrc *isrc)
{
- struct intr_irqsrc *isrc, *new_isrc;
int error;
- new_isrc = isrc_alloc(INTR_ISRCT_NAMESPACE, 0);
-
mtx_lock(&isrc_table_lock);
- isrc = isrc_namespace_lookup(dev, type, num);
- if (isrc != NULL) {
- mtx_unlock(&isrc_table_lock);
- isrc_free(new_isrc);
- return (isrc->isrc_irq); /* already mapped */
- }
+ if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
+ isrc_release_counters(isrc);
+ error = isrc_free_irq(isrc);
+ mtx_unlock(&isrc_table_lock);
+ return (error);
+}
- error = isrc_alloc_irq_locked(new_isrc);
- if (error != 0) {
+static struct intr_dev_data *
+intr_ddata_alloc(u_int extsize)
+{
+ struct intr_dev_data *ddata;
+
+ ddata = malloc(sizeof(*ddata) + extsize, M_INTRNG, M_WAITOK | M_ZERO);
+
+ mtx_lock(&isrc_table_lock);
+ if (intr_ddata_first_unused >= nitems(intr_ddata_tab)) {
mtx_unlock(&isrc_table_lock);
- isrc_free(new_isrc);
- return (IRQ_INVALID); /* no space left */
+ free(ddata, M_INTRNG);
+ return (NULL);
}
-
- new_isrc->isrc_dev = dev;
- new_isrc->isrc_nspc_type = type;
- new_isrc->isrc_nspc_num = num;
+ intr_ddata_tab[intr_ddata_first_unused] = ddata;
+ ddata->idd_irq = IRQ_DDATA_BASE + intr_ddata_first_unused++;
mtx_unlock(&isrc_table_lock);
-
- return (new_isrc->isrc_irq);
+ return (ddata);
}
-#ifdef FDT
-/*
- * Lookup interrupt source by FDT description.
- */
static struct intr_irqsrc *
-isrc_fdt_lookup(intptr_t xref, pcell_t *cells, u_int ncells)
+intr_ddata_lookup(u_int irq, struct intr_map_data **datap)
{
- u_int irq, cellsize;
+ int error;
struct intr_irqsrc *isrc;
+ struct intr_dev_data *ddata;
- mtx_assert(&isrc_table_lock, MA_OWNED);
+ isrc = isrc_lookup(irq);
+ if (isrc != NULL) {
+ if (datap != NULL)
+ *datap = NULL;
+ return (isrc);
+ }
- cellsize = ncells * sizeof(*cells);
- for (irq = 0; irq < nitems(irq_sources); irq++) {
- isrc = irq_sources[irq];
- if (isrc != NULL && isrc->isrc_type == INTR_ISRCT_FDT &&
- isrc->isrc_xref == xref && isrc->isrc_ncells == ncells &&
- memcmp(isrc->isrc_cells, cells, cellsize) == 0)
- return (isrc);
+ if (irq < IRQ_DDATA_BASE)
+ return (NULL);
+
+ irq -= IRQ_DDATA_BASE;
+ if (irq >= nitems(intr_ddata_tab))
+ return (NULL);
+
+ ddata = intr_ddata_tab[irq];
+ if (ddata->idd_isrc == NULL) {
+ error = intr_map_irq(ddata->idd_dev, ddata->idd_xref,
+ &ddata->idd_data, &irq);
+ if (error != 0)
+ return (NULL);
+ ddata->idd_isrc = isrc_lookup(irq);
}
- return (NULL);
+ if (datap != NULL)
+ *datap = &ddata->idd_data;
+ return (ddata->idd_isrc);
}
+#ifdef DEV_ACPI
/*
- * Map interrupt source according to FDT data into framework. If such mapping
+ * Map interrupt source according to ACPI info into framework. If such mapping
* does not exist, create it. Return unique interrupt number (resource handle)
* associated with mapped interrupt source.
*/
u_int
-intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
+intr_acpi_map_irq(device_t dev, u_int irq, enum intr_polarity pol,
+ enum intr_trigger trig)
{
- struct intr_irqsrc *isrc, *new_isrc;
- u_int cellsize;
- intptr_t xref;
- int error;
-
- xref = (intptr_t)node; /* It's so simple for now. */
-
- cellsize = ncells * sizeof(*cells);
- new_isrc = isrc_alloc(INTR_ISRCT_FDT, cellsize);
-
- mtx_lock(&isrc_table_lock);
- isrc = isrc_fdt_lookup(xref, cells, ncells);
- if (isrc != NULL) {
- mtx_unlock(&isrc_table_lock);
- isrc_free(new_isrc);
- return (isrc->isrc_irq); /* already mapped */
- }
-
- error = isrc_alloc_irq_locked(new_isrc);
- if (error != 0) {
- mtx_unlock(&isrc_table_lock);
- isrc_free(new_isrc);
- return (IRQ_INVALID); /* no space left */
- }
-
- new_isrc->isrc_xref = xref;
- new_isrc->isrc_ncells = ncells;
- memcpy(new_isrc->isrc_cells, cells, cellsize);
- mtx_unlock(&isrc_table_lock);
-
- return (new_isrc->isrc_irq);
+ struct intr_dev_data *ddata;
+
+ ddata = intr_ddata_alloc(0);
+ if (ddata == NULL)
+ return (0xFFFFFFFF); /* no space left */
+
+ ddata->idd_dev = dev;
+ ddata->idd_data.type = INTR_MAP_DATA_ACPI;
+ ddata->idd_data.acpi.irq = irq;
+ ddata->idd_data.acpi.pol = pol;
+ ddata->idd_data.acpi.trig = trig;
+ return (ddata->idd_irq);
}
#endif
-
+#ifdef FDT
/*
- * Register interrupt source into interrupt controller.
+ * Map interrupt source according to FDT data into framework. If such mapping
+ * does not exist, create it. Return unique interrupt number (resource handle)
+ * associated with mapped interrupt source.
*/
-static int
-isrc_register(struct intr_irqsrc *isrc)
+u_int
+intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
{
- struct intr_pic *pic;
- boolean_t is_percpu;
- int error;
-
- if (isrc->isrc_flags & INTR_ISRCF_REGISTERED)
- return (0);
-
- if (isrc->isrc_dev == NULL) {
- pic = pic_lookup(NULL, isrc->isrc_xref);
- if (pic == NULL || pic->pic_dev == NULL)
- return (ESRCH);
- isrc->isrc_dev = pic->pic_dev;
- }
-
- error = PIC_REGISTER(isrc->isrc_dev, isrc, &is_percpu);
- if (error != 0)
- return (error);
+ struct intr_dev_data *ddata;
+ u_int cellsize;
- mtx_lock(&isrc_table_lock);
- isrc->isrc_flags |= INTR_ISRCF_REGISTERED;
- if (is_percpu)
- isrc->isrc_flags |= INTR_ISRCF_PERCPU;
- isrc_update_name(isrc, NULL);
- mtx_unlock(&isrc_table_lock);
- return (0);
+ cellsize = ncells * sizeof(*cells);
+ ddata = intr_ddata_alloc(cellsize);
+ if (ddata == NULL)
+ return (0xFFFFFFFF); /* no space left */
+
+ ddata->idd_xref = (intptr_t)node;
+ ddata->idd_data.type = INTR_MAP_DATA_FDT;
+ ddata->idd_data.fdt.ncells = ncells;
+ ddata->idd_data.fdt.cells = (pcell_t *)(ddata + 1);
+ memcpy(ddata->idd_data.fdt.cells, cells, cellsize);
+ return (ddata->idd_irq);
}
+#endif
#ifdef INTR_SOLO
/*
@@ -678,7 +663,7 @@ intr_isrc_assign_cpu(void *arg, int cpu)
* informed if the call is successfull.
*/
if (irq_assign_cpu) {
- error = PIC_BIND(isrc->isrc_dev, isrc);
+ error = PIC_BIND_INTR(isrc->isrc_dev, isrc);
if (error) {
CPU_ZERO(&isrc->isrc_cpu);
mtx_unlock(&isrc_table_lock);
@@ -774,7 +759,7 @@ isrc_add_handler(struct intr_irqsrc *isrc, const char *name,
/*
* Lookup interrupt controller locked.
*/
-static struct intr_pic *
+static inline struct intr_pic *
pic_lookup_locked(device_t dev, intptr_t xref)
{
struct intr_pic *pic;
@@ -801,7 +786,6 @@ pic_lookup(device_t dev, intptr_t xref)
mtx_lock(&pic_list_lock);
pic = pic_lookup_locked(dev, xref);
mtx_unlock(&pic_list_lock);
-
return (pic);
}
@@ -871,7 +855,7 @@ intr_pic_register(device_t dev, intptr_t xref)
* Unregister interrupt controller.
*/
int
-intr_pic_unregister(device_t dev, intptr_t xref)
+intr_pic_deregister(device_t dev, intptr_t xref)
{
panic("%s: not implemented", __func__);
@@ -923,12 +907,73 @@ intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
}
int
-intr_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
- void *arg, u_int irq, int flags, void **cookiep)
+intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data,
+ u_int *irqp)
{
- const char *name;
+ int error;
+ struct intr_irqsrc *isrc;
+ struct intr_pic *pic;
+
+ if (data == NULL)
+ return (EINVAL);
+
+ pic = pic_lookup(dev, xref);
+ if (pic == NULL || pic->pic_dev == NULL)
+ return (ESRCH);
+
+ error = PIC_MAP_INTR(pic->pic_dev, data, &isrc);
+ if (error == 0)
+ *irqp = isrc->isrc_irq;
+ return (error);
+}
+
+int
+intr_alloc_irq(device_t dev, struct resource *res)
+{
+ struct intr_map_data *data;
+ struct intr_irqsrc *isrc;
+
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), &data);
+ if (isrc == NULL)
+ return (EINVAL);
+
+ return (PIC_ALLOC_INTR(isrc->isrc_dev, isrc, res, data));
+}
+
+int
+intr_release_irq(device_t dev, struct resource *res)
+{
+ struct intr_map_data *data;
struct intr_irqsrc *isrc;
+
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), &data);
+ if (isrc == NULL)
+ return (EINVAL);
+
+ return (PIC_RELEASE_INTR(isrc->isrc_dev, isrc, res, data));
+}
+
+int
+intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt,
+ driver_intr_t hand, void *arg, int flags, void **cookiep)
+{
int error;
+ struct intr_map_data *data;
+ struct intr_irqsrc *isrc;
+ const char *name;
+
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), &data);
+ if (isrc == NULL)
+ return (EINVAL);
name = device_get_nameunit(dev);
@@ -947,21 +992,7 @@ intr_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
debugf("irq %u cannot solo on %s\n", irq, name);
return (EINVAL);
}
-#endif
- isrc = isrc_lookup(irq);
- if (isrc == NULL) {
- debugf("irq %u without source on %s\n", irq, name);
- return (EINVAL);
- }
-
- error = isrc_register(isrc);
- if (error != 0) {
- debugf("irq %u map error %d on %s\n", irq, error, name);
- return (error);
- }
-
-#ifdef INTR_SOLO
if (flags & INTR_SOLO) {
error = iscr_setup_filter(isrc, name, (intr_irq_filter_t *)filt,
arg, cookiep);
@@ -978,24 +1009,32 @@ intr_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
return (error);
mtx_lock(&isrc_table_lock);
- isrc->isrc_handlers++;
- if (isrc->isrc_handlers == 1) {
- PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
- PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc);
+ error = PIC_SETUP_INTR(isrc->isrc_dev, isrc, res, data);
+ if (error == 0) {
+ isrc->isrc_handlers++;
+ if (isrc->isrc_handlers == 1)
+ PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
}
mtx_unlock(&isrc_table_lock);
- return (0);
+ if (error != 0)
+ intr_event_remove_handler(*cookiep);
+ return (error);
}
int
-intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
+intr_teardown_irq(device_t dev, struct resource *res, void *cookie)
{
- struct intr_irqsrc *isrc;
int error;
+ struct intr_map_data *data;
+ struct intr_irqsrc *isrc;
- isrc = isrc_lookup(irq);
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), &data);
if (isrc == NULL || isrc->isrc_handlers == 0)
return (EINVAL);
+
#ifdef INTR_SOLO
if (isrc->isrc_filter != NULL) {
if (isrc != cookie)
@@ -1005,8 +1044,8 @@ intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
isrc->isrc_filter = NULL;
isrc->isrc_arg = NULL;
isrc->isrc_handlers = 0;
- PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc);
PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
+ PIC_TEARDOWN_INTR(isrc->isrc_dev, isrc, res, data);
isrc_update_name(isrc, NULL);
mtx_unlock(&isrc_table_lock);
return (0);
@@ -1019,10 +1058,9 @@ intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
if (error == 0) {
mtx_lock(&isrc_table_lock);
isrc->isrc_handlers--;
- if (isrc->isrc_handlers == 0) {
- PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc);
+ if (isrc->isrc_handlers == 0)
PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
- }
+ PIC_TEARDOWN_INTR(isrc->isrc_dev, isrc, res, data);
intrcnt_updatename(isrc);
mtx_unlock(&isrc_table_lock);
}
@@ -1030,36 +1068,16 @@ intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
}
int
-intr_irq_config(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
+intr_describe_irq(device_t dev, struct resource *res, void *cookie,
+ const char *descr)
{
+ int error;
struct intr_irqsrc *isrc;
- isrc = isrc_lookup(irq);
- if (isrc == NULL)
- return (EINVAL);
-
- if (isrc->isrc_handlers != 0)
- return (EBUSY); /* interrrupt is enabled (active) */
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
- /*
- * Once an interrupt is enabled, we do not change its configuration.
- * A controller PIC_ENABLE_INTR() method is called when an interrupt
- * is going to be enabled. In this method, a controller should setup
- * the interrupt according to saved configuration parameters.
- */
- isrc->isrc_trig = trig;
- isrc->isrc_pol = pol;
-
- return (0);
-}
-
-int
-intr_irq_describe(u_int irq, void *cookie, const char *descr)
-{
- struct intr_irqsrc *isrc;
- int error;
-
- isrc = isrc_lookup(irq);
+ isrc = intr_ddata_lookup(rman_get_start(res), NULL);
if (isrc == NULL || isrc->isrc_handlers == 0)
return (EINVAL);
#ifdef INTR_SOLO
@@ -1084,11 +1102,14 @@ intr_irq_describe(u_int irq, void *cookie, const char *descr)
#ifdef SMP
int
-intr_irq_bind(u_int irq, int cpu)
+intr_bind_irq(device_t dev, struct resource *res, int cpu)
{
struct intr_irqsrc *isrc;
- isrc = isrc_lookup(irq);
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), NULL);
if (isrc == NULL || isrc->isrc_handlers == 0)
return (EINVAL);
#ifdef INTR_SOLO
@@ -1135,7 +1156,7 @@ intr_irq_shuffle(void *arg __unused)
for (i = 0; i < NIRQ; i++) {
isrc = irq_sources[i];
if (isrc == NULL || isrc->isrc_handlers == 0 ||
- isrc->isrc_flags & INTR_ISRCF_PERCPU)
+ isrc->isrc_flags & INTR_ISRCF_PPI)
continue;
if (isrc->isrc_event != NULL &&
@@ -1151,7 +1172,7 @@ intr_irq_shuffle(void *arg __unused)
* for bound ISRC. The best thing we can do is to clear
* isrc_cpu so inconsistency with ie_cpu will be detectable.
*/
- if (PIC_BIND(isrc->isrc_dev, isrc) != 0)
+ if (PIC_BIND_INTR(isrc->isrc_dev, isrc) != 0)
CPU_ZERO(&isrc->isrc_cpu);
}
mtx_unlock(&isrc_table_lock);
@@ -1196,6 +1217,7 @@ intr_pic_init_secondary(void)
DB_SHOW_COMMAND(irqs, db_show_irqs)
{
u_int i, irqsum;
+ u_long num;
struct intr_irqsrc *isrc;
for (irqsum = 0, i = 0; i < NIRQ; i++) {
@@ -1203,11 +1225,11 @@ DB_SHOW_COMMAND(irqs, db_show_irqs)
if (isrc == NULL)
continue;
+ num = isrc->isrc_count != NULL ? isrc->isrc_count[0] : 0;
db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
isrc->isrc_name, isrc->isrc_cpu.__bits[0],
- isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "",
- isrc->isrc_count[0]);
- irqsum += isrc->isrc_count[0];
+ isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "", num);
+ irqsum += num;
}
db_printf("irq total %u\n", irqsum);
}
OpenPOWER on IntegriCloud