summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2017-02-25 16:53:10 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2017-02-25 16:53:10 +0000
commit3f9cdfb0e749a8ee3a5e441fb752b55bbec3509c (patch)
tree235af1d9db0c4f490a861aeec2174869ee649108 /sys
parent2b5bdee33543957e19ded870b22ddcc8086c432f (diff)
MSI interrupts are established in a different way as well. Instead of
simply hooking up the interrupt handler and returning an MD cookie, we need to pass back information for the PCI controller to configure its interrupt correctly. For this, add another establish routine into the FDT-based interrupt API which looks up msi-controller nodes and calls their MSI-specific establish function if requested. ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/arm64/arm64/intr.c46
-rw-r--r--sys/arch/arm64/include/intr.h6
2 files changed, 49 insertions, 3 deletions
diff --git a/sys/arch/arm64/arm64/intr.c b/sys/arch/arm64/arm64/intr.c
index 4eadea2bc73..53ab09c2266 100644
--- a/sys/arch/arm64/arm64/intr.c
+++ b/sys/arch/arm64/arm64/intr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.c,v 1.4 2017/02/24 17:16:41 patrick Exp $ */
+/* $OpenBSD: intr.c,v 1.5 2017/02/25 16:53:09 patrick Exp $ */
/*
* Copyright (c) 2011 Dale Rahn <drahn@openbsd.org>
*
@@ -28,6 +28,7 @@
#include <dev/ofw/openfirm.h>
uint32_t arm_intr_get_parent(int);
+uint32_t arm_intr_msi_get_parent(int);
void *arm_intr_prereg_establish_fdt(void *, int *, int, int (*)(void *),
void *, char *);
@@ -81,6 +82,19 @@ arm_intr_get_parent(int node)
return phandle;
}
+uint32_t
+arm_intr_msi_get_parent(int node)
+{
+ uint32_t phandle = 0;
+
+ while (node && !phandle) {
+ phandle = OF_getpropint(node, "msi-parent", 0);
+ node = OF_parent(node);
+ }
+
+ return phandle;
+}
+
/*
* Interrupt pre-registration.
*
@@ -187,7 +201,7 @@ arm_intr_register_fdt(struct interrupt_controller *ic)
ic->ic_cells = OF_getpropint(ic->ic_node, "#interrupt-cells", 0);
ic->ic_phandle = OF_getpropint(ic->ic_node, "phandle", 0);
- if (ic->ic_cells == 0 || ic->ic_phandle == 0)
+ if (ic->ic_phandle == 0)
return;
KASSERT(ic->ic_cells <= MAX_INTERRUPT_CELLS);
@@ -364,6 +378,34 @@ arm_intr_establish_fdt_imap(int node, int *reg, int nreg, int acells,
return ih;
}
+void *
+arm_intr_establish_fdt_msi(int node, uint64_t *addr, uint64_t *data,
+ int level, int (*func)(void *), void *cookie, char *name)
+{
+ struct interrupt_controller *ic;
+ struct arm_intr_handle *ih;
+ uint32_t phandle;
+ void *val = NULL;
+
+ phandle = arm_intr_msi_get_parent(node);
+ LIST_FOREACH(ic, &interrupt_controllers, ic_list) {
+ if (ic->ic_phandle == phandle)
+ break;
+ }
+
+ if (ic == NULL || ic->ic_establish_msi == NULL)
+ return NULL;
+
+ val = ic->ic_establish_msi(ic->ic_cookie, addr, data,
+ level, func, cookie, name);
+
+ 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)
{
diff --git a/sys/arch/arm64/include/intr.h b/sys/arch/arm64/include/intr.h
index a4f2a65a463..ef788d965e9 100644
--- a/sys/arch/arm64/include/intr.h
+++ b/sys/arch/arm64/include/intr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.h,v 1.3 2017/02/24 17:16:41 patrick Exp $ */
+/* $OpenBSD: intr.h,v 1.4 2017/02/25 16:53:09 patrick Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -134,6 +134,8 @@ struct interrupt_controller {
void *ic_cookie;
void *(*ic_establish)(void *, int *, int, int (*)(void *),
void *, char *);
+ void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int,
+ int (*)(void *), void *, char *);
void (*ic_disestablish)(void *);
LIST_ENTRY(interrupt_controller) ic_list;
@@ -149,6 +151,8 @@ void *arm_intr_establish_fdt_idx(int, int, int, int (*)(void *),
void *, char *);
void *arm_intr_establish_fdt_imap(int, int *, int, int, int, int (*)(void *),
void *, char *);
+void *arm_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int ,
+ int (*)(void *), void *, char *);
void arm_intr_disestablish_fdt(void *);
void *arm_intr_parent_establish_fdt(void *, int *, int,