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