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