Page MenuHomeFreeBSD

D53330.diff
No OneTemporary

D53330.diff

diff --git a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c
--- a/sys/dev/fdt/simplebus.c
+++ b/sys/dev/fdt/simplebus.c
@@ -40,6 +40,9 @@
#include <dev/fdt/simplebus.h>
+#include "pci_if.h"
+#include "pcib_if.h"
+
/*
* Bus interface.
*/
@@ -62,6 +65,21 @@
static const struct ofw_bus_devinfo *simplebus_get_devinfo(device_t bus,
device_t child);
+/*
+ * PCI interface for MSI interrupts
+ */
+static pci_get_id_t simplebus_get_id;
+static pci_alloc_msi_t simplebus_alloc_msi;
+
+/*
+ * PCIB interface
+ */
+static pcib_alloc_msi_t simplebus_pcib_alloc_msi;
+static pcib_release_msi_t simplebus_pcib_release_msi;
+static pcib_alloc_msix_t simplebus_pcib_alloc_msix;
+static pcib_release_msix_t simplebus_pcib_release_msix;
+static pcib_map_msi_t simplebus_pcib_map_msi;
+
/*
* Driver methods.
*/
@@ -105,6 +123,17 @@
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+ /* PCI interface for MSI interrupts */
+ DEVMETHOD(pci_get_id, simplebus_get_id),
+ DEVMETHOD(pci_alloc_msi, simplebus_alloc_msi),
+
+ /* PCIB interface */
+ DEVMETHOD(pcib_alloc_msi, simplebus_pcib_alloc_msi),
+ DEVMETHOD(pcib_release_msi, simplebus_pcib_release_msi),
+ DEVMETHOD(pcib_alloc_msix, simplebus_pcib_alloc_msix),
+ DEVMETHOD(pcib_release_msix, simplebus_pcib_release_msix),
+ DEVMETHOD(pcib_map_msi, simplebus_pcib_map_msi),
+
DEVMETHOD_END
};
@@ -534,3 +563,108 @@
rv += bus_print_child_footer(bus, child);
return (rv);
}
+
+static int
+simplebus_get_id(device_t dev, device_t child, enum pci_id_type type,
+ uintptr_t *id)
+{
+ phandle_t node, xref;
+ pcell_t *cells;
+ uintptr_t rid;
+ int error, ncells;
+
+ if (type != PCI_ID_MSI)
+ return (EINVAL);
+
+ node = ofw_bus_get_node(child);
+ error = ofw_bus_parse_xref_list_alloc(node, "msi-parent", "#msi-cells",
+ 0, &xref, &ncells, &cells);
+ if (error != 0)
+ return (error);
+
+ rid = 0;
+ if (ncells > 0)
+ rid = cells[0];
+
+ *id = rid;
+ return (0);
+}
+
+static int
+simplebus_alloc_msi(device_t bus, device_t child, int *count)
+{
+ struct simplebus_devinfo *ndi;
+ struct resource_list_entry *rle;
+ int error, i, irq_count, *irqs;
+
+ if (*count < 1)
+ return (EINVAL);
+
+ ndi = device_get_ivars(child);
+ if (ndi == NULL)
+ return (ENXIO);
+
+ /* Only MSI or non-MSI for now */
+ rle = resource_list_find(&ndi->rl, SYS_RES_IRQ, 0);
+ if (rle != NULL && rle->res != NULL)
+ return (ENXIO);
+
+ irq_count = *count;
+ irqs = mallocarray(irq_count, sizeof(int), M_DEVBUF, M_WAITOK | M_ZERO);
+
+ error = PCIB_ALLOC_MSI(bus, child, irq_count, irq_count, irqs);
+ if (error != 0)
+ goto out;
+
+ for (i = 0; i < irq_count; i++) {
+ error = bus_generic_rl_set_resource(bus, child, SYS_RES_IRQ,
+ i + 1, irqs[i], 1);
+ if (error != 0)
+ break;
+ }
+
+ /* Clean up resources if something failed */
+ if (error != 0) {
+ for (int j = 0; j < i; j++) {
+ bus_generic_rl_delete_resource(bus, child, SYS_RES_IRQ,
+ j + 1);
+ }
+ }
+out:
+ free(irqs, M_DEVBUF);
+ return (error);
+}
+
+static int
+simplebus_pcib_alloc_msi(device_t dev, device_t child, int count, int maxcount,
+ int *irqs)
+{
+ return (PCIB_ALLOC_MSI(device_get_parent(dev), child, count, maxcount,
+ irqs));
+}
+
+static int
+simplebus_pcib_release_msi(device_t dev, device_t child, int count, int *irqs)
+{
+ return (PCIB_RELEASE_MSI(device_get_parent(dev), child, count, irqs));
+}
+
+static int
+simplebus_pcib_alloc_msix(device_t dev, device_t child, int *irq)
+{
+ return (PCIB_ALLOC_MSIX(device_get_parent(dev), child, irq));
+}
+
+static int
+simplebus_pcib_release_msix(device_t dev, device_t child, int irq)
+{
+ return (PCIB_RELEASE_MSIX(device_get_parent(dev), child, irq));
+}
+
+static int
+simplebus_pcib_map_msi(device_t dev, device_t child, int irq, uint64_t *addr,
+ uint32_t *data)
+{
+ return (PCIB_MAP_MSI(device_get_parent(dev), child, irq, addr,
+ data));
+}

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 26, 10:15 AM (4 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24178713
Default Alt Text
D53330.diff (3 KB)

Event Timeline