PERFORCE change 231353 for review
John Baldwin
jhb at FreeBSD.org
Mon Jul 22 21:24:29 UTC 2013
http://p4web.freebsd.org/@@231353?ac=10
Change 231353 by jhb at jhb_jhbbsd on 2013/07/22 21:24:19
WIP changes to move the secbus resource up into the PCI bus
layer a bit.
Affected files ...
.. //depot/projects/pci/sys/dev/pccbb/pccbb_pci.c#9 edit
.. //depot/projects/pci/sys/dev/pci/pci.c#45 edit
.. //depot/projects/pci/sys/dev/pci/pci_pci.c#43 edit
.. //depot/projects/pci/sys/dev/pci/pcib_private.h#27 edit
Differences ...
==== //depot/projects/pci/sys/dev/pccbb/pccbb_pci.c#9 (text+ko) ====
@@ -326,8 +326,6 @@
sc->pribus = pcib_get_bus(parent);
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1);
- sc->bus.sec_reg = PCIR_SECBUS_2;
- sc->bus.sub_reg = PCIR_SUBBUS_2;
pcib_setup_secbus(brdev, &sc->bus);
#endif
SLIST_INIT(&sc->rl);
==== //depot/projects/pci/sys/dev/pci/pci.c#45 (text+ko) ====
@@ -349,6 +349,13 @@
SYSCTL_INT(_hw_pci, OID_AUTO, clear_bars, CTLFLAG_RDTUN, &pci_clear_bars, 0,
"Ignore firmware-assigned resources for BARs.");
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+static int pci_clear_buses;
+TUNABLE_INT("hw.pci.clear_buses", &pci_clear_buses);
+SYSCTL_INT(_hw_pci, OID_AUTO, clear_buses, CTLFLAG_RDTUN, &pci_clear_buses, 0,
+ "Ignore firmware-assigned bus numbers.");
+#endif
+
static int
pci_has_quirk(uint32_t devid, int quirk)
{
@@ -3195,6 +3202,134 @@
bus_release_resource(self, SYS_RES_MEMORY, rid, res);
}
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+static void
+pci_reserve_secbus(device_t bus, device_t dev, pcicfgregs *cfg,
+ struct resource_list *rl)
+{
+ struct resource *res;
+ u_long start, end, count;
+ int rid, sec_bus, sec_reg, sub_bus, sub_reg;
+
+ switch (cfg->hdrtype & PCIM_HDRTYPE) {
+ case PCIM_HDRTYPE_BRIDGE:
+ sec_reg = PCIR_SECBUS_1;
+ sub_reg = PCIR_SUBBUS_1;
+ break;
+ case PCIM_HDRTYPE_CARDBUS:
+ sec_reg = PCIR_SECBUS_2;
+ sub_reg = PCIR_SUBBUS_2;
+ break;
+ default:
+ return;
+ }
+
+ /*
+ * If requested, clear secondary bus registers in bridge devices
+ * to force a complete renumbering rather than reserving the
+ * existing range.
+ */
+ if (pci_clear_buses) {
+ PCI_WRITE_CONFIG(bus, dev, sec_reg, 0, 1);
+ PCI_WRITE_CONFIG(bus, dev, sub_reg, 0, 1);
+ return;
+ }
+
+ /*
+ * If the existing bus range is valid, attempt to reserve it
+ * from our parent. If this fails for any reason, clear the
+ * secbus and subbus registers.
+ *
+ * XXX: Should we reset sub_bus to sec_bus if it is < sec_bus?
+ * This would at least preserve the existing sec_bus if it is
+ * valid.
+ */
+ sec_bus = PCI_READ_CONFIG(bus, dev, sec_reg, 1);
+ sub_bus = PCI_READ_CONFIG(bus, dev, sub_reg, 1);
+ if (bootverbose)
+ printf("\tsecbus=%d, subbus=%d\n", sec_bus, sub_bus);
+ if (sec_bus > 0 && sub_bus >= sec_bus) {
+ start = sec_bus;
+ end = sub_bus;
+ count = end - start + 1;
+
+ resource_list_add(rl, PCI_RES_BUS, 0, start, end, count);
+ rid = 0;
+ res = resource_list_reserve(rl, bus, dev, PCI_RES_BUS, &rid,
+ start, end, count, 0);
+ if (res == NULL) {
+ if (bootverbose)
+ device_printf(bus,
+ "pci%d:%d:%d:%d secbus failed to allocate\n",
+ pci_get_domain(dev), pci_get_bus(dev),
+ pci_get_slot(dev), pci_get_function(dev));
+ resource_list_delete(rl, PCI_RES_BUS, 0);
+ }
+ } else
+ res = NULL;
+ if (res == NULL) {
+ PCI_WRITE_CONFIG(bus, dev, sec_reg, 0, 1);
+ PCI_WRITE_CONFIG(bus, dev, sub_reg, 0, 1);
+ }
+}
+
+static struct resource *
+pci_alloc_secbus(device_t dev, device_t child, int *rid, u_long start,
+ u_long end, u_long count, u_int flags)
+{
+ struct pci_devinfo *dinfo;
+ pcicfgregs *cfg;
+ struct resource_list *rl;
+ struct resource *res;
+ int sec_reg, sub_reg;
+
+ dinfo = device_get_ivars(dev);
+ cfg = &dinfo->cfg;
+ rl = &dinfo->resources;
+ switch (cfg->hdrtype & PCIM_HDRTYPE) {
+ case PCIM_HDRTYPE_BRIDGE:
+ sec_reg = PCIR_SECBUS_1;
+ sub_reg = PCIR_SUBBUS_1;
+ break;
+ case PCIM_HDRTYPE_CARDBUS:
+ sec_reg = PCIR_SECBUS_2;
+ sub_reg = PCIR_SUBBUS_2;
+ break;
+ default:
+ return (NULL);
+ }
+
+ /*
+ * rid 0 is used to request an already reserved range while
+ * rid 1 is used to request an arbitrary range with a specific
+ * count.
+ */
+ if (*rid > 1)
+ return (NULL);
+
+ if (*rid == 1) {
+ *rid = 0;
+ resource_list_add(rl, PCI_RES_BUS, *rid, start, end, count);
+ res = resource_list_reserve(rl, dev, child, PCI_RES_BUS, rid,
+ start, end, count, flags & ~RF_ACTIVE);
+ if (res == NULL) {
+ resource_list_delete(rl, PCI_RES_BUS, *rid);
+ device_printf(child, "allocating %lu bus%s failed\n",
+ count, count == 1 ? "" : "es");
+ return (NULL);
+ }
+ if (bootverbose)
+ device_printf(child,
+ "Lazy allocation of %lu bus%s at %lu\n", count,
+ count == 1 ? "" : "es", rman_get_start(res));
+ PCI_WRITE_CONFIG(dev, child, sec_reg, rman_get_start(res), 1);
+ PCI_WRITE_CONFIG(dev, child, sub_reg, rman_get_end(res), 1);
+ }
+ return (resource_list_alloc(rl, dev, child, PCI_RES_BUS, rid, start,
+ end, count, flags));
+}
+#endif
+
void
pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
{
@@ -3267,6 +3402,14 @@
else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_UHCI)
uhci_early_takeover(dev);
}
+
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+ /*
+ * Reserve resources for secondary bus ranges behind bridge
+ * devices.
+ */
+ pci_reserve_secbus(bus, dev, cfg, rl);
+#endif
}
void
@@ -3736,6 +3879,10 @@
retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+#ifdef PCI_RES_BUS
+ /* XXX: Maybe? */
+ retval += resource_list_print_type(rl, "bus", PCI_RES_BUS, "%ld");
+#endif
if (device_get_flags(dev))
retval += printf(" flags %#x", device_get_flags(dev));
@@ -4211,7 +4358,6 @@
{
struct pci_devinfo *dinfo = device_get_ivars(child);
struct resource_list *rl = &dinfo->resources;
- struct resource_list_entry *rle;
struct resource *res;
struct pci_map *pm;
pci_addr_t map, testval;
@@ -4284,23 +4430,16 @@
* Allocate enough resource, and then write back the
* appropriate BAR for that resource.
*/
- res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid,
- start, end, count, flags & ~RF_ACTIVE);
+ resource_list_add(rl, type, *rid, start, end, count);
+ res = resource_list_reserve(rl, dev, child, type, rid, start, end,
+ count, flags & ~RF_ACTIVE);
if (res == NULL) {
+ resource_list_delete(rl, type, *rid);
device_printf(child,
"%#lx bytes of rid %#x res %d failed (%#lx, %#lx).\n",
count, *rid, type, start, end);
goto out;
}
- resource_list_add(rl, type, *rid, start, end, count);
- rle = resource_list_find(rl, type, *rid);
- if (rle == NULL)
- panic("pci_reserve_map: unexpectedly can't find resource.");
- rle->res = res;
- rle->start = rman_get_start(res);
- rle->end = rman_get_end(res);
- rle->count = count;
- rle->flags = RLE_RESERVED;
if (bootverbose)
device_printf(child,
"Lazy allocation of %#lx bytes rid %#x type %d at %#lx\n",
@@ -4334,17 +4473,8 @@
switch (type) {
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
case PCI_RES_BUS:
- /*
- * If rid 0 is not already allocated, create a new
- * resource list entry.
- */
- if (*rid != 0)
- return (NULL);
- rle = resource_list_find(rl, type, *rid);
- if (rle != NULL && rle->res != NULL)
- return (NULL);
- resource_list_add(rl, type, *rid, start, end, count);
- break;
+ return (pci_alloc_secbus(dev, child, rid, start, end, count,
+ flags));
#endif
case SYS_RES_IRQ:
/*
==== //depot/projects/pci/sys/dev/pci/pci_pci.c#43 (text+ko) ====
@@ -539,6 +539,16 @@
char buf[64];
int error, rid;
+ switch (pci_read_config(dev, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) {
+ case PCIM_HDRTYPE_BRIDGE:
+ bus->sub_reg = PCIR_SUBBUS_1;
+ break;
+ case PCIM_HDRTYPE_CARDBUS:
+ bus->sub_reg = PCIR_SUBBUS_2;
+ break;
+ default:
+ panic("not a PCI bridge");
+ }
bus->dev = dev;
bus->rman.rm_start = 0;
bus->rman.rm_end = PCI_BUSMAX;
@@ -550,41 +560,15 @@
panic("Failed to initialize %s bus number rman",
device_get_nameunit(dev));
-#if 0
- /*
- * XXX: Should we reset subbus to secbus if it is < secbus?
- * This would at least preserve the existing secbus if it is
- * valid.
- */
- if (bus->sub < bus->sec)
- bus->sub = bus->sec;
-#endif
+ /* Allocate any existing bus range. */
+ rid = 0;
+ bus->res = bus_alloc_resource_any(dev, PCI_RES_BUS, &rid, 0);
- /*
- * Allocate a resource for the existing secondary bus number
- * range if it is valid.
- */
- if (bus->sec != 0 && bus->sub >= bus->sec) {
- rid = 0;
- bus->res = bus_alloc_resource(dev, PCI_RES_BUS, &rid, bus->sec,
- bus->sub, bus->sub - bus->sec + 1, 0);
- if (bus->res == NULL) {
- if (bootverbose || 1)
- device_printf(dev,
- "failed to allocate initial secbus range: %u-%u\n",
- bus->sec, bus->sub);
-#if 0
- /* XXX: Should we clear these on failure? */
- bus->sec = 0;
- bus->sub = 0;
-#endif
- }
- /* XXX */
- if (bus->res != NULL)
- device_printf(dev,
- "allocated initial secbus range %lu-%lu\n",
- rman_get_start(bus->res), rman_get_end(bus->res));
- }
+ /* XXX */
+ if (bus->res != NULL)
+ device_printf(dev,
+ "allocated initial secbus range %lu-%lu\n",
+ rman_get_start(bus->res), rman_get_end(bus->res));
/*
* If we don't have a valid resource, allocate a fresh resource
@@ -600,7 +584,7 @@
* This doesn't use bus_alloc_resource_any() as the
* count of 1 is explicit.
*/
- rid = 0;
+ rid = 1;
bus->res = bus_alloc_resource(dev, PCI_RES_BUS, &rid, 0ul, ~0ul,
1, 0);
if (bus->res != NULL) {
@@ -610,25 +594,22 @@
device_printf(bus->dev,
"allocated initial secbus %lu\n",
rman_get_start(bus->res));
- bus->sec = rman_get_start(bus->res);
- bus->sub = rman_get_end(bus->res);
} else
device_printf(bus->dev,
"failed to allocate secondary bus number\n");
}
/*
- * Add the initial resource to the rman and write updated
- * secbus and subbus registers.
+ * Add the initial resource to the rman.
*/
if (bus->res != NULL) {
error = rman_manage_region(&bus->rman, rman_get_start(bus->res),
rman_get_end(bus->res));
if (error)
panic("Failed to add resource to rman");
+ bus->sec = rman_get_start(bus->res);
+ bus->sub = rman_get_end(bus->res);
}
- pci_write_config(dev, bus->sec_reg, bus->sec, 1);
- pci_write_config(dev, bus->sub_reg, bus->sub, 1);
}
static struct resource *
@@ -637,7 +618,8 @@
{
struct resource *res;
- res = rman_reserve_resource(&bus->rman, start, end, count, flags, child);
+ res = rman_reserve_resource(&bus->rman, start, end, count, flags,
+ child);
if (res == NULL)
return (NULL);
@@ -968,6 +950,8 @@
* Quirk handling.
*/
switch (pci_get_devid(dev)) {
+#if 0
+ /* XXX: This is now broken */
case 0x12258086: /* Intel 82454KX/GX (Orion) */
{
uint8_t supbus;
@@ -979,6 +963,7 @@
}
break;
}
+#endif
/*
* The i82380FB mobile docking controller is a PCI-PCI bridge,
@@ -992,6 +977,7 @@
sc->flags |= PCIB_SUBTRACTIVE;
break;
+#if !defined(NEW_PCIB) && !defined(PCI_RES_BUS)
/* Compaq R3000 BIOS sets wrong subordinate bus number. */
case 0x00dd10de:
{
@@ -1017,6 +1003,7 @@
}
break;
}
+#endif
}
if (pci_msi_device_blacklisted(dev))
@@ -1039,8 +1026,6 @@
#ifdef NEW_PCIB
#ifdef PCI_RES_BUS
- sc->bus.sec_reg = PCIR_SECBUS_1;
- sc->bus.sub_reg = PCIR_SUBBUS_1;
pcib_setup_secbus(dev, &sc->bus);
#endif
pcib_probe_windows(sc);
==== //depot/projects/pci/sys/dev/pci/pcib_private.h#27 (text+ko) ====
@@ -91,7 +91,6 @@
struct rman rman;
struct resource *res;
const char *name;
- int sec_reg;
int sub_reg;
#endif
};
More information about the p4-projects
mailing list