Deleted Added
full compact
30c30
< __FBSDID("$FreeBSD: stable/10/sys/dev/pci/pci.c 279904 2015-03-12 07:07:41Z scottl $");
---
> __FBSDID("$FreeBSD: stable/10/sys/dev/pci/pci.c 280970 2015-04-01 21:48:54Z jhb $");
94a95,97
> #ifdef PCI_RES_BUS
> static int pci_detach(device_t dev);
> #endif
129a133,135
> #ifdef PCI_RES_BUS
> DEVMETHOD(device_detach, pci_detach),
> #else
130a137
> #endif
363a371,377
> #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
>
3228a3243,3400
> #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;
> char *cp;
> u_long start, end, count;
> int rid, sec_bus, sec_reg, sub_bus, sub_reg, sup_bus;
>
> 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 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);
>
> /* Quirk handling. */
> switch (pci_get_devid(dev)) {
> case 0x12258086: /* Intel 82454KX/GX (Orion) */
> sup_bus = pci_read_config(dev, 0x41, 1);
> if (sup_bus != 0xff) {
> sec_bus = sup_bus + 1;
> sub_bus = sup_bus + 1;
> PCI_WRITE_CONFIG(bus, dev, sec_reg, sec_bus, 1);
> PCI_WRITE_CONFIG(bus, dev, sub_reg, sub_bus, 1);
> }
> break;
>
> case 0x00dd10de:
> /* Compaq R3000 BIOS sets wrong subordinate bus number. */
> if ((cp = getenv("smbios.planar.maker")) == NULL)
> break;
> if (strncmp(cp, "Compal", 6) != 0) {
> freeenv(cp);
> break;
> }
> freeenv(cp);
> if ((cp = getenv("smbios.planar.product")) == NULL)
> break;
> if (strncmp(cp, "08A0", 4) != 0) {
> freeenv(cp);
> break;
> }
> freeenv(cp);
> if (sub_bus < 0xa) {
> sub_bus = 0xa;
> PCI_WRITE_CONFIG(bus, dev, sub_reg, sub_bus, 1);
> }
> break;
> }
>
> 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, 0ul, ~0ul, count);
>
> /*
> * If requested, clear secondary bus registers in
> * bridge devices to force a complete renumbering
> * rather than reserving the existing range. However,
> * preserve the existing size.
> */
> if (pci_clear_buses)
> goto clear;
>
> rid = 0;
> res = resource_list_reserve(rl, bus, dev, PCI_RES_BUS, &rid,
> start, end, count, 0);
> if (res != NULL)
> return;
>
> 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));
> }
>
> clear:
> 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(child);
> 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);
> }
>
> if (*rid != 0)
> return (NULL);
>
> if (resource_list_find(rl, PCI_RES_BUS, *rid) == NULL)
> resource_list_add(rl, PCI_RES_BUS, *rid, start, end, count);
> if (!resource_list_reserved(rl, PCI_RES_BUS, *rid)) {
> 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
>
3300a3473,3480
>
> #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
3392a3573,3575
> #ifdef PCI_RES_BUS
> int rid;
> #endif
3396a3580,3588
> #ifdef PCI_RES_BUS
> rid = 0;
> sc->sc_bus = bus_alloc_resource(dev, PCI_RES_BUS, &rid, busno, busno,
> 1, 0);
> if (sc->sc_bus == NULL) {
> device_printf(dev, "failed to allocate bus number\n");
> return (ENXIO);
> }
> #endif
3440a3633,3647
> #ifdef PCI_RES_BUS
> static int
> pci_detach(device_t dev)
> {
> struct pci_softc *sc;
> int error;
>
> error = bus_generic_detach(dev);
> if (error)
> return (error);
> sc = device_get_softc(dev);
> return (bus_release_resource(dev, PCI_RES_BUS, 0, sc->sc_bus));
> }
> #endif
>
3955a4163,4166
> #ifdef PCI_RES_BUS
> if (resource_list_release_active(rl, dev, child, PCI_RES_BUS) != 0)
> pci_printf(&dinfo->cfg, "Device leaked PCI bus numbers\n");
> #endif
4371a4583,4587
> #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
> case PCI_RES_BUS:
> return (pci_alloc_secbus(dev, child, rid, start, end, count,
> flags));
> #endif