Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/acpi arm: ACPI: Add support for simple sharing ...
details: https://anonhg.NetBSD.org/src/rev/08ae5aca2a9e
branches: trunk
changeset: 985099:08ae5aca2a9e
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sun Aug 08 10:28:26 2021 +0000
description:
arm: ACPI: Add support for simple sharing of platform interrupts
Allow sharing of platform interrupts provided that the type, ipl, and
mpsafe-ness are the same.
diffstat:
sys/arch/arm/acpi/acpi_machdep.c | 139 ++++++++++++++++++++++++++++++++++++--
1 files changed, 130 insertions(+), 9 deletions(-)
diffs (177 lines):
diff -r 0dda477c89ad -r 08ae5aca2a9e sys/arch/arm/acpi/acpi_machdep.c
--- a/sys/arch/arm/acpi/acpi_machdep.c Sun Aug 08 07:17:18 2021 +0000
+++ b/sys/arch/arm/acpi/acpi_machdep.c Sun Aug 08 10:28:26 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_machdep.c,v 1.24 2021/08/07 18:40:45 jmcneill Exp $ */
+/* $NetBSD: acpi_machdep.c,v 1.25 2021/08/08 10:28:26 jmcneill Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
#include "pci.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.24 2021/08/07 18:40:45 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.25 2021/08/08 10:28:26 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -63,6 +63,27 @@
extern struct arm32_bus_dma_tag acpi_coherent_dma_tag;
extern struct arm32_bus_dma_tag arm_generic_dma_tag;
+struct acpi_intrhandler {
+ int (*ah_fn)(void *);
+ void *ah_arg;
+ TAILQ_ENTRY(acpi_intrhandler) ah_list;
+};
+
+struct acpi_intrvec {
+ int ai_irq;
+ int ai_ipl;
+ int ai_type;
+ bool ai_mpsafe;
+ int ai_refcnt;
+ void *ai_arg;
+ void *ai_ih;
+ TAILQ_HEAD(, acpi_intrhandler) ai_handlers;
+ TAILQ_ENTRY(acpi_intrvec) ai_list;
+};
+
+static TAILQ_HEAD(, acpi_intrvec) acpi_intrvecs =
+ TAILQ_HEAD_INITIALIZER(acpi_intrvecs);
+
bus_dma_tag_t arm_acpi_dma32_tag(struct acpi_softc *, struct acpi_devnode *);
bus_dma_tag_t arm_acpi_dma64_tag(struct acpi_softc *, struct acpi_devnode *);
@@ -256,10 +277,116 @@
cpsid(I32_bit);
}
+static struct acpi_intrvec *
+acpi_md_intr_lookup(int irq)
+{
+ struct acpi_intrvec *ai;
+
+ TAILQ_FOREACH(ai, &acpi_intrvecs, ai_list) {
+ if (ai->ai_irq == irq) {
+ return ai;
+ }
+ }
+
+ return NULL;
+}
+
+static int
+acpi_md_intr(void *arg)
+{
+ struct acpi_intrvec *ai = arg;
+ struct acpi_intrhandler *ah;
+ int rv = 0;
+
+ TAILQ_FOREACH(ah, &ai->ai_handlers, ah_list) {
+ rv += ah->ah_fn(ah->ah_arg);
+ }
+
+ return rv;
+}
+
void *
acpi_md_intr_establish(uint32_t irq, int ipl, int type, int (*handler)(void *), void *arg, bool mpsafe, const char *xname)
{
- return intr_establish_xname(irq, ipl, type | (mpsafe ? IST_MPSAFE : 0), handler, arg, xname);
+ struct acpi_intrvec *ai;
+ struct acpi_intrhandler *ah;
+
+ ai = acpi_md_intr_lookup(irq);
+ if (ai == NULL) {
+ ai = kmem_zalloc(sizeof(*ai), KM_SLEEP);
+ ai->ai_refcnt = 0;
+ ai->ai_irq = irq;
+ ai->ai_ipl = ipl;
+ ai->ai_type = type;
+ ai->ai_mpsafe = mpsafe;
+ ai->ai_arg = arg;
+ TAILQ_INIT(&ai->ai_handlers);
+ if (arg == NULL) {
+ ai->ai_ih = intr_establish_xname(irq, ipl,
+ type | (mpsafe ? IST_MPSAFE : 0), handler, NULL,
+ xname);
+ } else {
+ ai->ai_ih = intr_establish_xname(irq, ipl,
+ type | (mpsafe ? IST_MPSAFE : 0), acpi_md_intr, ai,
+ xname);
+ }
+ if (ai->ai_ih == NULL) {
+ kmem_free(ai, sizeof(*ai));
+ return NULL;
+ }
+ TAILQ_INSERT_TAIL(&acpi_intrvecs, ai, ai_list);
+ } else {
+ if (ai->ai_arg == NULL) {
+ printf("ACPI: cannot share irq with NULL arg\n");
+ return NULL;
+ }
+ if (ai->ai_ipl != ipl) {
+ printf("ACPI: cannot share irq with different ipl\n");
+ return NULL;
+ }
+ if (ai->ai_type != type) {
+ printf("ACPI: cannot share edge and level interrupts\n");
+ return NULL;
+ }
+ if (ai->ai_mpsafe != mpsafe) {
+ printf("ACPI: cannot share between mpsafe/non-mpsafe\n");
+ return NULL;
+ }
+ }
+
+ ai->ai_refcnt++;
+
+ ah = kmem_zalloc(sizeof(*ah), KM_SLEEP);
+ ah->ah_fn = handler;
+ ah->ah_arg = arg;
+ TAILQ_INSERT_TAIL(&ai->ai_handlers, ah, ah_list);
+
+ return ai->ai_ih;
+}
+
+void
+acpi_md_intr_disestablish(void *ih)
+{
+ struct acpi_intrvec *ai;
+ struct acpi_intrhandler *ah;
+
+ TAILQ_FOREACH(ai, &acpi_intrvecs, ai_list) {
+ if (ai->ai_ih == ih) {
+ KASSERT(ai->ai_refcnt > 0);
+ if (ai->ai_refcnt > 1) {
+ panic("%s: cannot disestablish shared irq", __func__);
+ }
+
+ TAILQ_REMOVE(&acpi_intrvecs, ai, ai_list);
+ ah = TAILQ_FIRST(&ai->ai_handlers);
+ kmem_free(ah, sizeof(*ah));
+ intr_disestablish(ai->ai_ih);
+ kmem_free(ai, sizeof(*ai));
+ return;
+ }
+ }
+
+ panic("%s: interrupt not established", __func__);
}
void
@@ -274,12 +401,6 @@
intr_unmask(ih);
}
-void
-acpi_md_intr_disestablish(void *ih)
-{
- intr_disestablish(ih);
-}
-
int
acpi_md_sleep(int state)
{
Home |
Main Index |
Thread Index |
Old Index