summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2017-02-25 16:53:09 +0000
committerpatrick <patrick@openbsd.org>2017-02-25 16:53:09 +0000
commitbc127a3b177fbe1edb843341c2ac1dcbce3a9d36 (patch)
tree6651479ccc61b89cc4cdcdcdc17faf1ff1a78c60
parentDisable loop idiom recognition for _libc_memset and _libc_memcpy. These are (diff)
downloadwireguard-openbsd-bc127a3b177fbe1edb843341c2ac1dcbce3a9d36.tar.xz
wireguard-openbsd-bc127a3b177fbe1edb843341c2ac1dcbce3a9d36.zip
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@
-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,