summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2015-04-01 21:48:54 +0000
committerjhb <jhb@FreeBSD.org>2015-04-01 21:48:54 +0000
commit5fdf8ec7775f40bbf293206a9670387f9b26b1e2 (patch)
tree0444ef99cffa06c0c3a81e7fa07483f56507ff35 /sys/dev/acpica
parent971b9a0eebccdc50b69052744c2221c13bd1a980 (diff)
downloadFreeBSD-src-5fdf8ec7775f40bbf293206a9670387f9b26b1e2.zip
FreeBSD-src-5fdf8ec7775f40bbf293206a9670387f9b26b1e2.tar.gz
MFC 261790:
Add support for managing PCI bus numbers. As with BARs and PCI-PCI bridge I/O windows, the default is to preserve the firmware-assigned resources. PCI bus numbers are only managed if NEW_PCIB is enabled and the architecture defines a PCI_RES_BUS resource type. - Add a helper API to create top-level PCI bus resource managers for each PCI domain/segment. Host-PCI bridge drivers use this API to allocate bus numbers from their associated domain. - Change the PCI bus and CardBus drivers to allocate a bus resource for their bus number from the parent PCI bridge device. - Change the PCI-PCI and PCI-CardBus bridge drivers to allocate the full range of bus numbers from secbus to subbus from their parent bridge. The drivers also always program their primary bus register. The bridge drivers also support growing their bus range by extending the bus resource and updating subbus to match the larger range. - Add support for managing PCI bus resources to the Host-PCI bridge drivers used for amd64 and i386 (acpi_pcib, mptable_pcib, legacy_pcib, and qpi_pcib). - Define a PCI_RES_BUS resource type for amd64 and i386. PR: 197076
Diffstat (limited to 'sys/dev/acpica')
-rw-r--r--sys/dev/acpica/acpi_pcib_acpi.c87
-rw-r--r--sys/dev/acpica/acpi_pcib_pci.c2
2 files changed, 88 insertions, 1 deletions
diff --git a/sys/dev/acpica/acpi_pcib_acpi.c b/sys/dev/acpica/acpi_pcib_acpi.c
index 882834d..545f641 100644
--- a/sys/dev/acpica/acpi_pcib_acpi.c
+++ b/sys/dev/acpica/acpi_pcib_acpi.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <dev/acpica/acpivar.h>
#include <machine/pci_cfgreg.h>
+#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
@@ -96,6 +97,11 @@ static struct resource *acpi_pcib_acpi_alloc_resource(device_t dev,
static int acpi_pcib_acpi_adjust_resource(device_t dev,
device_t child, int type, struct resource *r,
u_long start, u_long end);
+#ifdef PCI_RES_BUS
+static int acpi_pcib_acpi_release_resource(device_t dev,
+ device_t child, int type, int rid,
+ struct resource *r);
+#endif
#endif
static device_method_t acpi_pcib_acpi_methods[] = {
@@ -115,7 +121,11 @@ static device_method_t acpi_pcib_acpi_methods[] = {
#else
DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
#endif
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+ DEVMETHOD(bus_release_resource, acpi_pcib_acpi_release_resource),
+#else
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+#endif
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
@@ -271,6 +281,20 @@ acpi_pcib_producer_handler(ACPI_RESOURCE *res, void *context)
}
#endif
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+static int
+first_decoded_bus(struct acpi_hpcib_softc *sc, u_long *startp)
+{
+ struct resource_list_entry *rle;
+
+ rle = resource_list_find(&sc->ap_host_res.hr_rl, PCI_RES_BUS, 0);
+ if (rle == NULL)
+ return (ENXIO);
+ *startp = rle->start;
+ return (0);
+}
+#endif
+
static int
acpi_pcib_acpi_attach(device_t dev)
{
@@ -278,6 +302,11 @@ acpi_pcib_acpi_attach(device_t dev)
ACPI_STATUS status;
static int bus0_seen = 0;
u_int slot, func, busok;
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+ struct resource *bus_res;
+ u_long start;
+ int rid;
+#endif
uint8_t busno;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -389,6 +418,39 @@ acpi_pcib_acpi_attach(device_t dev)
}
}
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+ /*
+ * If nothing else worked, hope that ACPI at least lays out the
+ * Host-PCI bridges in order and that as a result the next free
+ * bus number is our bus number.
+ */
+ if (busok == 0) {
+ /*
+ * If we have a region of bus numbers, use the first
+ * number for our bus.
+ */
+ if (first_decoded_bus(sc, &start) == 0)
+ sc->ap_bus = start;
+ else {
+ rid = 0;
+ bus_res = pci_domain_alloc_bus(sc->ap_segment, dev, &rid, 0,
+ PCI_BUSMAX, 1, 0);
+ if (bus_res == NULL) {
+ device_printf(dev,
+ "could not allocate bus number\n");
+ pcib_host_res_free(dev, &sc->ap_host_res);
+ return (ENXIO);
+ }
+ sc->ap_bus = rman_get_start(bus_res);
+ pci_domain_release_bus(sc->ap_segment, dev, rid, bus_res);
+ }
+ } else {
+#ifdef INVARIANTS
+ if (first_decoded_bus(sc, &start) == 0)
+ KASSERT(start == sc->ap_bus, ("bus number mismatch"));
+#endif
+ }
+#else
/*
* If nothing else worked, hope that ACPI at least lays out the
* host-PCI bridges in order and that as a result our unit number
@@ -399,6 +461,7 @@ acpi_pcib_acpi_attach(device_t dev)
sc->ap_bus = device_get_unit(dev);
device_printf(dev, "trying bus number %d\n", sc->ap_bus);
}
+#endif
/* If this is bus 0 on segment 0, note that it has been seen already. */
if (sc->ap_segment == 0 && sc->ap_bus == 0)
@@ -534,6 +597,11 @@ acpi_pcib_acpi_alloc_resource(device_t dev, device_t child, int type, int *rid,
#ifdef NEW_PCIB
sc = device_get_softc(dev);
+#ifdef PCI_RES_BUS
+ if (type == PCI_RES_BUS)
+ return (pci_domain_alloc_bus(sc->ap_segment, child, rid, start, end,
+ count, flags));
+#endif
res = pcib_host_res_alloc(&sc->ap_host_res, child, type, rid, start, end,
count, flags);
@@ -562,7 +630,26 @@ acpi_pcib_acpi_adjust_resource(device_t dev, device_t child, int type,
struct acpi_hpcib_softc *sc;
sc = device_get_softc(dev);
+#ifdef PCI_RES_BUS
+ if (type == PCI_RES_BUS)
+ return (pci_domain_adjust_bus(sc->ap_segment, child, r, start,
+ end));
+#endif
return (pcib_host_res_adjust(&sc->ap_host_res, child, type, r, start,
end));
}
+
+#ifdef PCI_RES_BUS
+int
+acpi_pcib_acpi_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct acpi_hpcib_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (type == PCI_RES_BUS)
+ return (pci_domain_release_bus(sc->ap_segment, child, rid, r));
+ return (bus_generic_release_resource(dev, child, type, rid, r));
+}
+#endif
#endif
diff --git a/sys/dev/acpica/acpi_pcib_pci.c b/sys/dev/acpica/acpi_pcib_pci.c
index de26a4a..d3f4cbc 100644
--- a/sys/dev/acpica/acpi_pcib_pci.c
+++ b/sys/dev/acpica/acpi_pcib_pci.c
@@ -120,7 +120,7 @@ acpi_pcib_pci_attach(device_t dev)
pcib_attach_common(dev);
sc = device_get_softc(dev);
sc->ap_handle = acpi_get_handle(dev);
- return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_pcibsc.secbus));
+ return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_pcibsc.bus.sec));
}
static int
OpenPOWER on IntegriCloud