summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/arm/cortex/ampintc.c3
-rw-r--r--sys/arch/armv7/armv7/intr.c88
-rw-r--r--sys/arch/armv7/include/intr.h5
3 files changed, 83 insertions, 13 deletions
diff --git a/sys/arch/arm/cortex/ampintc.c b/sys/arch/arm/cortex/ampintc.c
index 048af313f4c..892e67f64c4 100644
--- a/sys/arch/arm/cortex/ampintc.c
+++ b/sys/arch/arm/cortex/ampintc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ampintc.c,v 1.11 2016/08/06 11:04:47 patrick Exp $ */
+/* $OpenBSD: ampintc.c,v 1.12 2016/08/06 17:25:14 patrick Exp $ */
/*
* Copyright (c) 2007,2009,2011 Dale Rahn <drahn@openbsd.org>
*
@@ -285,6 +285,7 @@ ampintc_attach(struct device *parent, struct device *self, void *aux)
sc->sc_ic.ic_node = faa->fa_node;
sc->sc_ic.ic_cookie = self;
sc->sc_ic.ic_establish = ampintc_intr_establish_fdt;
+ sc->sc_ic.ic_disestablish = ampintc_intr_disestablish;
arm_intr_register_fdt(&sc->sc_ic);
}
diff --git a/sys/arch/armv7/armv7/intr.c b/sys/arch/armv7/armv7/intr.c
index c0aaa59f180..847f124831c 100644
--- a/sys/arch/armv7/armv7/intr.c
+++ b/sys/arch/armv7/armv7/intr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.c,v 1.8 2016/08/04 12:17:36 kettenis Exp $ */
+/* $OpenBSD: intr.c,v 1.9 2016/08/06 17:25:15 patrick Exp $ */
/*
* Copyright (c) 2011 Dale Rahn <drahn@openbsd.org>
*
@@ -30,8 +30,9 @@
uint32_t arm_intr_get_parent(int);
-void *arm_intr_prereg_fdt(void *, int *, int, int (*)(void *),
+void *arm_intr_prereg_establish_fdt(void *, int *, int, int (*)(void *),
void *, char *);
+void arm_intr_prereg_disestablish_fdt(void *);
int arm_dflt_splraise(int);
int arm_dflt_spllower(int);
@@ -127,13 +128,16 @@ struct intr_prereg {
int (*ip_func)(void *);
void *ip_arg;
char *ip_name;
+
+ struct interrupt_controller *ip_ic;
+ void *ip_ih;
};
LIST_HEAD(, intr_prereg) prereg_interrupts =
LIST_HEAD_INITIALIZER(prereg_interrupts);
void *
-arm_intr_prereg_fdt(void *cookie, int *cell, int level,
+arm_intr_prereg_establish_fdt(void *cookie, int *cell, int level,
int (*func)(void *), void *arg, char *name)
{
struct interrupt_controller *ic = cookie;
@@ -154,6 +158,21 @@ arm_intr_prereg_fdt(void *cookie, int *cell, int level,
}
void
+arm_intr_prereg_disestablish_fdt(void *cookie)
+{
+ struct intr_prereg *ip = cookie;
+ struct interrupt_controller *ic = ip->ip_ic;
+
+ if (ip->ip_ic != NULL && ip->ip_ih != NULL)
+ ic->ic_disestablish(ip->ip_ih);
+
+ if (ip->ip_ic != NULL)
+ LIST_REMOVE(ip, ip_list);
+
+ free(ip, M_DEVBUF, sizeof(*ip));
+}
+
+void
arm_intr_init_fdt_recurse(int node)
{
struct interrupt_controller *ic;
@@ -163,7 +182,8 @@ arm_intr_init_fdt_recurse(int node)
M_DEVBUF, M_ZERO | M_WAITOK);
ic->ic_node = node;
ic->ic_cookie = ic;
- ic->ic_establish = arm_intr_prereg_fdt;
+ ic->ic_establish = arm_intr_prereg_establish_fdt;
+ ic->ic_disestablish = arm_intr_prereg_disestablish_fdt;
arm_intr_register_fdt(ic);
}
@@ -186,8 +206,7 @@ LIST_HEAD(, interrupt_controller) interrupt_controllers =
void
arm_intr_register_fdt(struct interrupt_controller *ic)
{
- struct intr_prereg *ip;
- void *ih;
+ struct intr_prereg *ip, *tip;
ic->ic_cells = OF_getpropint(ic->ic_node, "#interrupt-cells", 0);
ic->ic_phandle = OF_getpropint(ic->ic_node, "phandle", 0);
@@ -198,17 +217,25 @@ arm_intr_register_fdt(struct interrupt_controller *ic)
LIST_INSERT_HEAD(&interrupt_controllers, ic, ic_list);
/* Establish pre-registered interrupt handlers. */
- LIST_FOREACH(ip, &prereg_interrupts, ip_list) {
+ LIST_FOREACH_SAFE(ip, &prereg_interrupts, ip_list, tip) {
if (ip->ip_phandle != ic->ic_phandle)
continue;
- ih = ic->ic_establish(ic->ic_cookie, ip->ip_cell,
+ ip->ip_ic = ic;
+ ip->ip_ih = ic->ic_establish(ic->ic_cookie, ip->ip_cell,
ip->ip_level, ip->ip_func, ip->ip_arg, ip->ip_name);
- if (ih == NULL)
+ if (ip->ip_ih == NULL)
printf("can't establish interrupt %s\n", ip->ip_name);
+
+ LIST_REMOVE(ip, ip_list);
}
}
+struct arm_intr_handle {
+ struct interrupt_controller *ih_ic;
+ void *ih_ih;
+};
+
void *
arm_intr_establish_fdt(int node, int level, int (*func)(void *),
void *cookie, char *name)
@@ -223,6 +250,7 @@ arm_intr_establish_fdt_idx(int node, int idx, int level, int (*func)(void *),
struct interrupt_controller *ic;
int i, len, ncells, extended = 1;
uint32_t *cell, *cells, phandle;
+ struct arm_intr_handle *ih;
void *val = NULL;
len = OF_getproplen(node, "interrupts-extended");
@@ -279,7 +307,25 @@ arm_intr_establish_fdt_idx(int node, int idx, int level, int (*func)(void *),
}
free(cells, M_TEMP, len);
- return val;
+
+ if (val == NULL)
+ return NULL;
+
+ ih = malloc(sizeof(*ih), M_DEVBUF, M_WAITOK);
+ ih->ih_ic = ic;
+ ih->ih_ih = val;
+
+ return ih;
+}
+
+void
+arm_intr_disestablish_fdt(void *cookie)
+{
+ struct arm_intr_handle *ih = cookie;
+ struct interrupt_controller *ic = ih->ih_ic;
+
+ ic->ic_disestablish(ih->ih_ih);
+ free(ih, M_DEVBUF, sizeof(*ih));
}
/*
@@ -292,7 +338,9 @@ arm_intr_parent_establish_fdt(void *cookie, int *cell, int level,
int (*func)(void *), void *arg, char *name)
{
struct interrupt_controller *ic = cookie;
+ struct arm_intr_handle *ih;
uint32_t phandle;
+ void *val;
phandle = arm_intr_get_parent(ic->ic_node);
LIST_FOREACH(ic, &interrupt_controllers, ic_list) {
@@ -302,7 +350,25 @@ arm_intr_parent_establish_fdt(void *cookie, int *cell, int level,
if (ic == NULL)
return NULL;
- return ic->ic_establish(ic->ic_cookie, cell, level, func, arg, name);
+ val = ic->ic_establish(ic->ic_cookie, cell, level, func, arg, name);
+ if (val == NULL)
+ return NULL;
+
+ ih = malloc(sizeof(*ih), M_DEVBUF, M_WAITOK);
+ ih->ih_ic = ic;
+ ih->ih_ih = val;
+
+ return ih;
+}
+
+void
+arm_intr_parent_disestablish_fdt(void *cookie)
+{
+ struct arm_intr_handle *ih = cookie;
+ struct interrupt_controller *ic = ih->ih_ic;
+
+ ic->ic_disestablish(ih->ih_ih);
+ free(ih, M_DEVBUF, sizeof(*ih));
}
int
diff --git a/sys/arch/armv7/include/intr.h b/sys/arch/armv7/include/intr.h
index 647c2c26e91..5bbdbaf8d81 100644
--- a/sys/arch/armv7/include/intr.h
+++ b/sys/arch/armv7/include/intr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.h,v 1.4 2016/08/04 12:17:36 kettenis Exp $ */
+/* $OpenBSD: intr.h,v 1.5 2016/08/06 17:25:15 patrick Exp $ */
/* $NetBSD: intr.h,v 1.12 2003/06/16 20:00:59 thorpej Exp $ */
/*
@@ -150,6 +150,7 @@ struct interrupt_controller {
void *ic_cookie;
void *(*ic_establish)(void *, int *, int, int (*)(void *),
void *, char *);
+ void (*ic_disestablish)(void *);
LIST_ENTRY(interrupt_controller) ic_list;
uint32_t ic_phandle;
@@ -162,9 +163,11 @@ void *arm_intr_establish_fdt(int, int, int (*)(void *),
void *, char *);
void *arm_intr_establish_fdt_idx(int, int, int, int (*)(void *),
void *, char *);
+void arm_intr_disestablish_fdt(void *);
void *arm_intr_parent_establish_fdt(void *, int *, int,
int (*)(void *), void *, char *);
+void arm_intr_parent_disestablish_fdt(void *);
#ifdef DIAGNOSTIC
/*