git: 56b822a17cde - main - pci: Only add special VF handling for direct children in bus methods

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Wed, 05 Jun 2024 16:50:49 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=56b822a17cde5940909633c50623d463191a7852

commit 56b822a17cde5940909633c50623d463191a7852
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2024-06-05 16:50:05 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-06-05 16:50:05 +0000

    pci: Only add special VF handling for direct children in bus methods
    
    For activate/deactivate resource, use a more standard check at the
    start of the function since the addition of the PCI_IOV code made this
    more complex.  For the three recently added methods, just add the
    typical check at the beginning that I missed.
    
    This wasn't always fatal as if your system only had PCI device_t's as
    children of PCI bus devices it would happen to work ok, but if you
    have a non-PCI child device (e.g. an ATA channel) then dereferencing
    ivars for non-direct-children could fault.
    
    Reported by:    Cirrus-CI (via emaste)
    Reviewed by:    emaste
    Fixes:          871b33ad65ba pci: Consistently use pci_vf_* for suballocated VF memory resources
    Differential Revision:  https://reviews.freebsd.org/D45499
---
 sys/dev/pci/pci.c | 55 +++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 35 insertions(+), 20 deletions(-)

diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 2093d6a8b5ef..9661cfd19db7 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -5695,6 +5695,9 @@ pci_activate_resource(device_t dev, device_t child, struct resource *r)
 	struct pci_devinfo *dinfo;
 	int error, rid, type;
 
+	if (device_get_parent(child) != dev)
+		return (bus_generic_activate_resource(dev, child, r));
+
 	dinfo = device_get_ivars(child);
 #ifdef PCI_IOV
 	if (dinfo->cfg.flags & PCICFG_VF) {
@@ -5716,20 +5719,20 @@ pci_activate_resource(device_t dev, device_t child, struct resource *r)
 	if (error)
 		return (error);
 
+	rid = rman_get_rid(r);
+	type = rman_get_type(r);
+
+	/* Device ROMs need their decoding explicitly enabled. */
+	if (type == SYS_RES_MEMORY && PCIR_IS_BIOS(&dinfo->cfg, rid))
+		pci_write_bar(child, pci_find_bar(child, rid),
+		    rman_get_start(r) | PCIM_BIOS_ENABLE);
+
 	/* Enable decoding in the command register when activating BARs. */
-	if (device_get_parent(child) == dev) {
-		/* Device ROMs need their decoding explicitly enabled. */
-		rid = rman_get_rid(r);
-		type = rman_get_type(r);
-		if (type == SYS_RES_MEMORY && PCIR_IS_BIOS(&dinfo->cfg, rid))
-			pci_write_bar(child, pci_find_bar(child, rid),
-			    rman_get_start(r) | PCIM_BIOS_ENABLE);
-		switch (type) {
-		case SYS_RES_IOPORT:
-		case SYS_RES_MEMORY:
-			error = PCI_ENABLE_IO(dev, child, type);
-			break;
-		}
+	switch (type) {
+	case SYS_RES_IOPORT:
+	case SYS_RES_MEMORY:
+		error = PCI_ENABLE_IO(dev, child, type);
+		break;
 	}
 	return (error);
 }
@@ -5740,6 +5743,9 @@ pci_deactivate_resource(device_t dev, device_t child, struct resource *r)
 	struct pci_devinfo *dinfo;
 	int error, rid, type;
 
+	if (device_get_parent(child) != dev)
+		return (bus_generic_deactivate_resource(dev, child, r));
+
 	dinfo = device_get_ivars(child);
 #ifdef PCI_IOV
 	if (dinfo->cfg.flags & PCICFG_VF) {
@@ -5762,13 +5768,11 @@ pci_deactivate_resource(device_t dev, device_t child, struct resource *r)
 		return (error);
 
 	/* Disable decoding for device ROMs. */
-	if (device_get_parent(child) == dev) {
-		rid = rman_get_rid(r);
-		type = rman_get_type(r);
-		if (type == SYS_RES_MEMORY && PCIR_IS_BIOS(&dinfo->cfg, rid))
-			pci_write_bar(child, pci_find_bar(child, rid),
-			    rman_get_start(r));
-	}
+	rid = rman_get_rid(r);
+	type = rman_get_type(r);
+	if (type == SYS_RES_MEMORY && PCIR_IS_BIOS(&dinfo->cfg, rid))
+		pci_write_bar(child, pci_find_bar(child, rid),
+		    rman_get_start(r));
 	return (0);
 }
 
@@ -5779,6 +5783,10 @@ pci_adjust_resource(device_t dev, device_t child, struct resource *r,
 {
 	struct pci_devinfo *dinfo;
 
+	if (device_get_parent(child) != dev)
+		return (bus_generic_adjust_resource(dev, child, r, start,
+		    end));
+
 	dinfo = device_get_ivars(child);
 	if (dinfo->cfg.flags & PCICFG_VF) {
 		switch (rman_get_type(r)) {
@@ -5802,6 +5810,10 @@ pci_map_resource(device_t dev, device_t child, struct resource *r,
 {
 	struct pci_devinfo *dinfo;
 
+	if (device_get_parent(child) != dev)
+		return (bus_generic_map_resource(dev, child, r, argsp,
+		    map));
+
 	dinfo = device_get_ivars(child);
 	if (dinfo->cfg.flags & PCICFG_VF) {
 		switch (rman_get_type(r)) {
@@ -5825,6 +5837,9 @@ pci_unmap_resource(device_t dev, device_t child, struct resource *r,
 {
 	struct pci_devinfo *dinfo;
 
+	if (device_get_parent(child) != dev)
+		return (bus_generic_unmap_resource(dev, child, r, map));
+
 	dinfo = device_get_ivars(child);
 	if (dinfo->cfg.flags & PCICFG_VF) {
 		switch (rman_get_type(r)) {