Date: Sat, 7 Mar 2015 19:21:29 GMT From: John-Mark Gurney <jmg@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 1206967 for review Message-ID: <201503071921.t27JLTcu095821@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@1206967?ac=10 Change 1206967 by jmg@jmg_carbon2 on 2015/03/07 19:21:28 add a _add_child method to PCI so that sub-classes like ACPI can override adding a child.. The function _add_children will detect if a child is present and has a device node does not exist, and then call _add_child (preventing duplicates).. Also add a child is present bus function for PCI, so that drivers can start using it.. Currently, it does a simplistic check of the devvendor not being all ones, but I will expand it to read PCIe registers in the future... document why a DELAY(1) is needed so you don't have to go back through history to figure out why.. Affected files ... .. //depot/projects/pciehotplug/sys/dev/acpica/acpi_pci.c#3 edit .. //depot/projects/pciehotplug/sys/dev/pci/pci.c#5 edit .. //depot/projects/pciehotplug/sys/dev/pci/pci_if.m#3 edit .. //depot/projects/pciehotplug/sys/dev/pci/pci_pci.c#3 edit .. //depot/projects/pciehotplug/sys/dev/pci/pci_private.h#4 edit .. //depot/projects/pciehotplug/sys/dev/pci/pcib_if.m#3 edit .. //depot/projects/pciehotplug/sys/dev/pci/pcie_hp.c#4 edit Differences ... ==== //depot/projects/pciehotplug/sys/dev/acpica/acpi_pci.c#3 (text+ko) ==== @@ -83,6 +83,8 @@ int state); static void acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child); static bus_dma_tag_t acpi_pci_get_dma_tag(device_t bus, device_t child); +static device_t acpi_pci_add_child_method(device_t, uint32_t, uint8_t, uint8_t, + uint8_t); #ifdef PCI_IOV static device_t acpi_pci_create_iov_child(device_t bus, device_t pf, @@ -103,6 +105,7 @@ /* PCI interface */ DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method), + DEVMETHOD(pci_add_child, acpi_pci_add_child_method), #ifdef PCI_IOV DEVMETHOD(pci_create_iov_child, acpi_pci_create_iov_child), #endif @@ -223,6 +226,15 @@ return (error); } +static device_t +acpi_pci_add_child_method(device_t dev, uint32_t d, uint8_t b, uint8_t s, + uint8_t f) +{ + + return pci_add_child_size(dev, d, b, s, f, + sizeof(struct acpi_pci_devinfo)); +} + static void acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child) { @@ -322,7 +334,7 @@ * pci_add_children() doesn't find. We currently just ignore * these devices. */ - pci_add_children(dev, domain, busno, sizeof(struct acpi_pci_devinfo)); + pci_add_children(dev); AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1, acpi_pci_save_handle, NULL, dev, NULL); ==== //depot/projects/pciehotplug/sys/dev/pci/pci.c#5 (text+ko) ==== @@ -120,8 +120,12 @@ u_int irq); static uint16_t pci_get_rid_method(device_t dev, device_t child); +static int pci_child_present(device_t, uint8_t, uint8_t, uint8_t); +static int pci_bus_child_present(device_t dev, device_t child); +static device_t pci_add_child_method(device_t, uint32_t, uint8_t, + uint8_t, uint8_t); -static struct pci_devinfo * pci_fill_devinfo(device_t pcib, int d, int b, int s, +static struct pci_devinfo *pci_fill_devinfo(device_t pcib, int d, int b, int s, int f, uint16_t vid, uint16_t did, size_t size); static device_method_t pci_methods[] = { @@ -162,6 +166,7 @@ DEVMETHOD(bus_remap_intr, pci_remap_intr_method), DEVMETHOD(bus_suspend_child, pci_suspend_child), DEVMETHOD(bus_resume_child, pci_resume_child), + DEVMETHOD(bus_child_present, pci_bus_child_present), /* PCI interface */ DEVMETHOD(pci_read_config, pci_read_config_method), @@ -189,6 +194,7 @@ DEVMETHOD(pci_msix_count, pci_msix_count_method), DEVMETHOD(pci_get_rid, pci_get_rid_method), DEVMETHOD(pci_child_added, pci_child_added_method), + DEVMETHOD(pci_add_child, pci_add_child_method), #ifdef PCI_IOV DEVMETHOD(pci_iov_attach, pci_iov_attach_method), DEVMETHOD(pci_iov_detach, pci_iov_detach_method), @@ -535,7 +541,7 @@ } return (ln2size); } - + /* return log2 of address range supported by map register */ static int @@ -599,7 +605,8 @@ /* read configuration header into pcicfgregs structure */ struct pci_devinfo * -pci_read_device(device_t pcib, int d, int b, int s, int f, size_t size) +pci_read_device(device_t pcib, uint32_t d, uint8_t b, uint8_t s, uint8_t f, + size_t size) { #define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w) uint16_t vid, did; @@ -1697,7 +1704,7 @@ free(used, M_DEVBUF); return (EINVAL); } - + /* Make sure none of the resources are allocated. */ for (i = 0; i < msix->msix_table_len; i++) { if (msix->msix_table[i].mte_vector == 0) @@ -1994,7 +2001,7 @@ struct msix_table_entry *mte; struct msix_vector *mv; uint64_t addr; - uint32_t data; + uint32_t data; int error, i, j; /* @@ -3498,40 +3505,33 @@ #endif } -static struct pci_devinfo * -pci_identify_function(device_t pcib, device_t dev, int domain, int busno, - int slot, int func, size_t dinfo_size) -{ - struct pci_devinfo *dinfo; - - dinfo = pci_read_device(pcib, domain, busno, slot, func, dinfo_size); - if (dinfo != NULL) - pci_add_child(dev, dinfo); - - return (dinfo); -} - void -pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size) +pci_add_children(device_t dev) { -#define REG(n, w) PCIB_READ_CONFIG(pcib, busno, s, f, n, w) - device_t pcib = device_get_parent(dev); - struct pci_devinfo *dinfo; + device_t pcib, child; int maxslots; int s, f, pcifunchigh; + uint32_t domain; + uint8_t busno; uint8_t hdrtype; int first_func; + pcib = device_get_parent(dev); + domain = pcib_get_domain(pcib); + busno = pcib_get_bus(pcib); + /* * Try to detect a device at slot 0, function 0. If it exists, try to * enable ARI. We must enable ARI before detecting the rest of the * functions on this bus as ARI changes the set of slots and functions * that are legal on this bus. */ - dinfo = pci_identify_function(pcib, dev, domain, busno, 0, 0, - dinfo_size); - if (dinfo != NULL && pci_enable_ari) - PCIB_TRY_ENABLE_ARI(pcib, dinfo->cfg.dev); + if (pci_child_present(pcib, busno, 0, 0) == -1 && + pci_find_dbsf(domain, busno, 0, 0) == NULL) { + child = PCI_ADD_CHILD(dev, domain, busno, 0, 0); + if (pci_enable_ari) + PCIB_TRY_ENABLE_ARI(pcib, child); + } /* * Start looking for new devices on slot 0 at function 1 because we @@ -3539,23 +3539,22 @@ */ first_func = 1; - KASSERT(dinfo_size >= sizeof(struct pci_devinfo), - ("dinfo_size too small")); maxslots = PCIB_MAXSLOTS(pcib); for (s = 0; s <= maxslots; s++, first_func = 0) { pcifunchigh = 0; f = 0; - DELAY(1); - hdrtype = REG(PCIR_HDRTYPE, 1); + DELAY(1); /* work around AMD8111 probe failures */ + hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1); if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) continue; if (hdrtype & PCIM_MFDEV) pcifunchigh = PCIB_MAXFUNCS(pcib); - for (f = first_func; f <= pcifunchigh; f++) - pci_identify_function(pcib, dev, domain, busno, s, f, - dinfo_size); + for (f = first_func; f <= pcifunchigh; f++) { + if (pci_child_present(pcib, busno, s, f) == -1 && + pci_find_dbsf(domain, busno, s, f) == NULL) + PCI_ADD_CHILD(dev, domain, busno, s, f); + } } -#undef REG } #ifdef PCI_IOV @@ -3623,6 +3622,31 @@ } +static device_t +pci_add_child_method(device_t dev, uint32_t d, uint8_t b, uint8_t s, uint8_t f) +{ + + return pci_add_child_size(dev, d, b, s, f, sizeof(struct pci_devinfo)); +} + +device_t +pci_add_child_size(device_t dev, uint32_t d, uint8_t b, uint8_t s, uint8_t f, + size_t dinfo_size) +{ + device_t pcib; + struct pci_devinfo *dinfo; + + pcib = device_get_parent(dev); + + dinfo = pci_read_device(pcib, d, b, s, f, dinfo_size); + if (dinfo == NULL) + return NULL; + + pci_add_child(dev, dinfo); + + return dinfo->cfg.dev; +} + static int pci_probe(device_t dev) { @@ -3686,7 +3710,7 @@ static int pci_attach(device_t dev) { - int busno, domain, error; + int error; error = pci_attach_common(dev); if (error) @@ -3698,9 +3722,7 @@ * the unit number to decide which bus we are probing. We ask * the parent pcib what our domain and bus numbers are. */ - domain = pcib_get_domain(dev); - busno = pcib_get_bus(dev); - pci_add_children(dev, domain, busno, sizeof(struct pci_devinfo)); + pci_add_children(dev); return (bus_generic_attach(dev)); } @@ -4821,7 +4843,7 @@ if (error) return (error); - /* Disable decoding for device ROMs. */ + /* Disable decoding for device ROMs. */ if (device_get_parent(child) == dev) { dinfo = device_get_ivars(child); if (type == SYS_RES_MEMORY && PCIR_IS_BIOS(&dinfo->cfg, rid)) @@ -5330,3 +5352,25 @@ return (PCIB_GET_RID(device_get_parent(dev), child)); } + +static int +pci_child_present(device_t pcib, uint8_t b, uint8_t s, uint8_t f) +{ + + if (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVVENDOR, 4) != 0xfffffffful) + return -1; /* present */ + + return 0; +} + +static int +pci_bus_child_present(device_t dev, device_t child) +{ + uint8_t b, s, f; + + b = pci_get_bus(child); + s = pci_get_slot(child); + f = pci_get_function(child); + + return pci_child_present(device_get_parent(dev), b, s, f); +} ==== //depot/projects/pciehotplug/sys/dev/pci/pci_if.m#3 (text+ko) ==== @@ -202,6 +202,20 @@ device_t child; }; + +# +# Add a new child at slot/function. It is expected that the device is known +# to be present, but a NULL device_t handle may be returned if there was an +# issue adding the device. +# +METHOD device_t add_child { + device_t dev; + uint32_t domain; + uint8_t bus; + uint8_t slot; + uint8_t func; +}; + METHOD int iov_attach { device_t dev; device_t child; ==== //depot/projects/pciehotplug/sys/dev/pci/pci_pci.c#3 (text+ko) ==== @@ -2125,4 +2125,3 @@ return (0); } - ==== //depot/projects/pciehotplug/sys/dev/pci/pci_private.h#4 (text+ko) ==== @@ -48,9 +48,10 @@ extern int pci_do_power_resume; extern int pci_do_power_suspend; -void pci_add_children(device_t dev, int domain, int busno, - size_t dinfo_size); +void pci_add_children(device_t dev); void pci_add_child(device_t bus, struct pci_devinfo *dinfo); +device_t pci_add_child_size(device_t dev, uint32_t d, uint8_t b, + uint8_t s, uint8_t f, size_t dinfo_size); device_t pci_add_iov_child(device_t bus, device_t pf, size_t dinfo_size, uint16_t rid, uint16_t vid, uint16_t did); void pci_add_resources(device_t bus, device_t dev, int force, @@ -114,8 +115,7 @@ void pci_delete_resource(device_t dev, device_t child, int type, int rid); struct resource_list *pci_get_resource_list (device_t dev, device_t child); -struct pci_devinfo *pci_read_device(device_t pcib, int d, int b, int s, int f, - size_t size); +struct pci_devinfo *pci_read_device(device_t pcib, uint32_t d, uint8_t b, uint8_t s, uint8_t f, size_t size); void pci_print_verbose(struct pci_devinfo *dinfo); int pci_freecfg(struct pci_devinfo *dinfo); void pci_child_detached(device_t dev, device_t child); ==== //depot/projects/pciehotplug/sys/dev/pci/pcib_if.m#3 (text+ko) ==== @@ -206,4 +206,3 @@ int *slot; int *func; } DEFAULT pcib_decode_rid; - ==== //depot/projects/pciehotplug/sys/dev/pci/pcie_hp.c#4 (text+ko) ==== @@ -275,15 +275,11 @@ rescan_bus(void *arg) { device_t dev; - int busno, domain; dev = arg; SDT_PROBE(pci, pciehp, task, add_children, 0, 0, 0, 0, 0); - domain = pcib_get_domain(dev); - busno = pcib_get_bus(dev); - pci_add_children(dev, domain, busno, - sizeof(struct pci_devinfo) + 32 /* XXX - hack, room for acpi vars */); + pci_add_children(dev); (void)bus_generic_attach(dev); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503071921.t27JLTcu095821>
