PERFORCE change 1206967 for review
John-Mark Gurney
jmg at FreeBSD.org
Sat Mar 7 19:21:30 UTC 2015
http://p4web.freebsd.org/@@1206967?ac=10
Change 1206967 by jmg at 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);
}
More information about the p4-projects
mailing list