Page MenuHomeFreeBSD

D59169.id186204.diff
No OneTemporary

D59169.id186204.diff

diff --git a/sys/arm64/acpica/acpi_iort.c b/sys/arm64/acpica/acpi_iort.c
--- a/sys/arm64/acpica/acpi_iort.c
+++ b/sys/arm64/acpica/acpi_iort.c
@@ -763,6 +763,19 @@
return (NULL);
}
+int
+acpi_iort_lookup_pci_id(device_t bus, device_t child, uintptr_t *devid)
+{
+ struct iort_node *node;
+
+ node = acpi_iort_lookup_iwb_node(bus, child);
+ if (!node)
+ return (ENODEV);
+
+ *devid = node->entries.mappings[0].outbase;
+ return (0);
+}
+
int
acpi_iort_lookup_its_from_iwb(device_t dev, int *its_id)
{
@@ -786,6 +799,54 @@
return (ENODEV);
}
+int
+acpi_iort_alloc_msis(device_t bus, device_t dev, int *count)
+{
+ int *irqs;
+ int irq_count;
+ int error;
+ int i;
+ int its_id;
+ u_int xref;
+ int pxm;
+
+ irq_count = *count;
+ irqs = mallocarray(irq_count, sizeof(int), M_DEVBUF, M_WAITOK | M_ZERO);
+
+ error = acpi_iort_lookup_its_from_iwb(dev, &its_id);
+ if (error)
+ return (error);
+
+ error = acpi_iort_its_lookup(its_id, &xref, &pxm);
+ if (error)
+ return (error);
+
+ error = intr_alloc_msi(bus, dev, xref, irq_count, irq_count, irqs);
+ if (error)
+ return (error);
+
+ for (i = 0; i < irq_count; i++) {
+ error = bus_generic_rl_set_resource(bus, dev, SYS_RES_IRQ,
+ i + 1, irqs[i], 1);
+ if (error != 0)
+ break;
+ }
+
+ *count = irq_count;
+
+ /* Clean up resources if something failed */
+ if (error != 0) {
+ for (int j = 0; j < i; j++) {
+ bus_generic_rl_delete_resource(bus, dev, SYS_RES_IRQ,
+ j + 1);
+
+ }
+ }
+
+ free(irqs, M_DEVBUF);
+ return (error);
+}
+
device_t
acpi_iort_get_iwb_dev(int iwb_id)
{
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -158,6 +158,11 @@
static isa_pnp_probe_t acpi_isa_pnp_probe;
+#ifdef __aarch64__
+static pci_get_id_t acpi_pci_get_id;
+static pci_alloc_msi_t acpi_pci_alloc_msi;
+#endif
+
static void acpi_reserve_resources(device_t dev);
static int acpi_sysres_alloc(device_t dev);
static uint32_t acpi_isa_get_logicalid(device_t dev);
@@ -251,6 +256,12 @@
/* ISA emulation */
DEVMETHOD(isa_pnp_probe, acpi_isa_pnp_probe),
+ /* PCI emulation */
+#ifdef __aarch64__
+ DEVMETHOD(pci_get_id, acpi_pci_get_id),
+ DEVMETHOD(pci_alloc_msi, acpi_pci_alloc_msi),
+#endif
+
DEVMETHOD_END
};
@@ -2333,6 +2344,36 @@
return_VALUE (result);
}
+#ifdef __aarch64__
+static int
+acpi_pci_get_id(device_t dev, device_t child, enum pci_id_type type,
+ uintptr_t *id)
+{
+ if (dev != device_get_parent(child))
+ return (EINVAL);
+
+ if (type != PCI_ID_MSI)
+ return (EINVAL);
+
+ if (!acpi_iort_lookup_pci_id(dev, child, id))
+ return (0);
+
+ return (ENXIO);
+}
+
+static int
+acpi_pci_alloc_msi(device_t bus, device_t child, int *count)
+{
+ if (bus != device_get_parent(child))
+ return (EINVAL);
+
+ if (!acpi_iort_alloc_msis(bus, child, count))
+ return (0);
+
+ return (ENXIO);
+}
+#endif
+
/*
* Look for a MCFG table. If it is present, use the settings for
* domain (segment) 0 to setup PCI config space access via the memory
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -639,6 +639,8 @@
uint64_t *xref, u_int *devid);
int acpi_iort_lookup_its_from_iwb(device_t dev, int *its_id);
device_t acpi_iort_get_iwb_dev(int iwb_id);
+int acpi_iort_lookup_pci_id(device_t bus, device_t child, uintptr_t *devid);
+int acpi_iort_alloc_msis(device_t bus, device_t child, int *count);
#endif
#endif /* _KERNEL */
#endif /* !_ACPIVAR_H_ */

File Metadata

Mime Type
text/plain
Expires
Fri, Sep 25, 6:40 AM (8 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39585542
Default Alt Text
D59169.id186204.diff (3 KB)

Event Timeline