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 Add support for sharing legacy PCI interru...
details: https://anonhg.NetBSD.org/src/rev/e2eb1aebcc9e
branches: trunk
changeset: 968649:e2eb1aebcc9e
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Thu Jan 23 11:59:37 2020 +0000
description:
Add support for sharing legacy PCI interrupt sources.
diffstat:
sys/arch/arm/acpi/acpi_pci_machdep.c | 108 ++++++++++++++++++++++++++++++++++-
1 files changed, 105 insertions(+), 3 deletions(-)
diffs (163 lines):
diff -r c090f67529d0 -r e2eb1aebcc9e sys/arch/arm/acpi/acpi_pci_machdep.c
--- a/sys/arch/arm/acpi/acpi_pci_machdep.c Thu Jan 23 11:17:09 2020 +0000
+++ b/sys/arch/arm/acpi/acpi_pci_machdep.c Thu Jan 23 11:59:37 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_pci_machdep.c,v 1.13 2020/01/17 17:06:33 jmcneill Exp $ */
+/* $NetBSD: acpi_pci_machdep.c,v 1.14 2020/01/23 11:59:37 jmcneill Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -29,8 +29,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#define _INTR_PRIVATE
+
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.13 2020/01/17 17:06:33 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.14 2020/01/23 11:59:37 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -47,6 +49,8 @@
#include <arm/cpufunc.h>
+#include <arm/pic/picvar.h>
+
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pciconf.h>
@@ -78,6 +82,20 @@
static TAILQ_HEAD(, acpi_pci_pct) acpi_pci_chipset_tags =
TAILQ_HEAD_INITIALIZER(acpi_pci_chipset_tags);
+struct acpi_pci_intr;
+
+struct acpi_pci_intr {
+ struct pic_softc pi_pic;
+ int pi_irqbase;
+ int pi_irq;
+ uint32_t pi_unblocked;
+ void *pi_ih;
+ TAILQ_ENTRY(acpi_pci_intr) pi_list;
+};
+
+static TAILQ_HEAD(, acpi_pci_intr) acpi_pci_intrs =
+ TAILQ_HEAD_INITIALIZER(acpi_pci_intrs);
+
static const struct acpi_pci_quirk acpi_pci_quirks[] = {
/* OEM ID OEM Table ID Revision Seg Func */
{ "AMAZON", "GRAVITON", 0, -1, acpi_pci_graviton_init },
@@ -415,11 +433,70 @@
}
}
+static struct acpi_pci_intr *
+acpi_pci_md_intr_lookup(int irq)
+{
+ struct acpi_pci_intr *pi;
+
+ TAILQ_FOREACH(pi, &acpi_pci_intrs, pi_list)
+ if (pi->pi_irq == irq)
+ return pi;
+
+ return NULL;
+}
+
+static void
+acpi_pci_md_unblock_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irqmask)
+{
+ struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic;
+
+ pi->pi_unblocked |= irqmask;
+}
+
+static void
+acpi_pci_md_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t irqmask)
+{
+ struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic;
+
+ pi->pi_unblocked &= ~irqmask;
+}
+
+static int
+acpi_pci_md_find_pending_irqs(struct pic_softc *pic)
+{
+ struct acpi_pci_intr * const pi = (struct acpi_pci_intr *)pic;
+
+ pic_mark_pending_sources(pic, 0, pi->pi_unblocked);
+
+ return 1;
+}
+
+static void
+acpi_pci_md_establish_irq(struct pic_softc *pic, struct intrsource *is)
+{
+}
+
+static void
+acpi_pci_md_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
+{
+ snprintf(buf, len, "slot %d", irq);
+}
+
+static struct pic_ops acpi_pci_pic_ops = {
+ .pic_unblock_irqs = acpi_pci_md_unblock_irqs,
+ .pic_block_irqs = acpi_pci_md_block_irqs,
+ .pic_find_pending_irqs = acpi_pci_md_find_pending_irqs,
+ .pic_establish_irq = acpi_pci_md_establish_irq,
+ .pic_source_name = acpi_pci_md_source_name,
+};
+
static void *
acpi_pci_md_intr_establish(void *v, pci_intr_handle_t ih, int ipl,
int (*callback)(void *), void *arg, const char *xname)
{
struct acpi_pci_context * const ap = v;
+ struct acpi_pci_intr *pi;
+ int slot;
if ((ih & (ARM_PCI_INTR_MSI | ARM_PCI_INTR_MSIX)) != 0)
return arm_pci_msi_intr_establish(&ap->ap_pc, ih, ipl, callback, arg, xname);
@@ -427,7 +504,31 @@
const int irq = (int)__SHIFTOUT(ih, ARM_PCI_INTR_IRQ);
const int mpsafe = (ih & ARM_PCI_INTR_MPSAFE) ? IST_MPSAFE : 0;
- return intr_establish_xname(irq, ipl, IST_LEVEL | mpsafe, callback, arg, xname);
+ pi = acpi_pci_md_intr_lookup(irq);
+ if (pi == NULL) {
+ pi = kmem_zalloc(sizeof(*pi), KM_SLEEP);
+ pi->pi_irq = irq;
+ snprintf(pi->pi_pic.pic_name, sizeof(pi->pi_pic.pic_name),
+ "PCI irq %d", irq);
+ pi->pi_pic.pic_maxsources = 32;
+ pi->pi_pic.pic_ops = &acpi_pci_pic_ops;
+ pi->pi_irqbase = pic_add(&pi->pi_pic, PIC_IRQBASE_ALLOC);
+ TAILQ_INSERT_TAIL(&acpi_pci_intrs, pi, pi_list);
+ pi->pi_ih = intr_establish_xname(irq, IPL_SCHED, IST_LEVEL | IST_MPSAFE,
+ pic_handle_intr, &pi->pi_pic, device_xname(ap->ap_dev));
+ }
+ if (pi->pi_ih == NULL)
+ return NULL;
+
+ /* Find a free slot */
+ for (slot = 0; slot < pi->pi_pic.pic_maxsources; slot++)
+ if (pi->pi_pic.pic_sources[slot] == NULL)
+ break;
+ if (slot == pi->pi_pic.pic_maxsources)
+ return NULL;
+
+ return intr_establish_xname(pi->pi_irqbase + slot, ipl, IST_LEVEL | mpsafe,
+ callback, arg, xname);
}
static void
@@ -476,6 +577,7 @@
pct->pct_ap.ap_dev = sc->sc_dev;
pct->pct_ap.ap_pc = arm_acpi_pci_chipset;
pct->pct_ap.ap_pc.pc_conf_v = &pct->pct_ap;
+ pct->pct_ap.ap_pc.pc_intr_v = &pct->pct_ap;
pct->pct_ap.ap_seg = seg;
pct->pct_ap.ap_bus = bbn;
pct->pct_ap.ap_bst = acpi_softc->sc_memt;
Home |
Main Index |
Thread Index |
Old Index