The branch main has been updated by jhb:

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

commit f7951799877c16cb901be1acc8d6643f0693cec4
Author:     Chandrakanth Patil <chandrakanth.pa...@broadcom.com>
AuthorDate: 2025-07-29 00:28:51 +0000
Commit:     John Baldwin <j...@freebsd.org>
CommitDate: 2025-07-29 19:09:53 +0000

    pci_iov: Support dynamic subordinate bus growth during VF creation
    
    Certain SR-IOV devices enumerate Virtual Functions (VFs) on a different
    PCIe bus than their parent Physical Function (PF).  In such cases, the
    default subordinate bus range assigned by BIOS may be insufficient to cover
    all VFs.
    
    This patch dynamically expands the subordinate bus range by:
    - Allocating additional bus numbers using bus_alloc_resource() when VFs are
      initialized
    - Releasing the reserved bus range during VF deletion via
      bus_release_resource()
    
    Reviewed by:    jhb
---
 sys/dev/pci/pci_iov.c         | 25 +++++++++++++++++++++----
 sys/dev/pci/pci_iov_private.h |  2 ++
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c
index 1f72391fb6b4..0efcfeac9eff 100644
--- a/sys/dev/pci/pci_iov.c
+++ b/sys/dev/pci/pci_iov.c
@@ -734,11 +734,18 @@ pci_iov_config(struct cdev *cdev, struct pci_iov_arg *arg)
        first_rid = pci_get_rid(dev) + rid_off;
        last_rid = first_rid + (num_vfs - 1) * rid_stride;
 
-       /* We don't yet support allocating extra bus numbers for VFs. */
        if (pci_get_bus(dev) != PCI_RID2BUS(last_rid)) {
-               device_printf(dev, "not enough PCIe bus numbers for VFs\n");
-               error = ENOSPC;
-               goto out;
+               int rid = 0;
+               uint16_t last_rid_bus = PCI_RID2BUS(last_rid);
+
+               iov->iov_bus_res = bus_alloc_resource(bus, PCI_RES_BUS, &rid,
+                   last_rid_bus, last_rid_bus, 1, RF_ACTIVE);
+               if (iov->iov_bus_res == NULL) {
+                       device_printf(dev,
+                           "failed to allocate PCIe bus number for VFs\n");
+                       error = ENOSPC;
+                       goto out;
+               }
        }
 
        if (!ari_enabled && PCI_RID2SLOT(last_rid) != 0) {
@@ -786,6 +793,11 @@ out:
                }
        }
 
+       if (iov->iov_bus_res != NULL) {
+               bus_release_resource(bus, iov->iov_bus_res);
+               iov->iov_bus_res = NULL;
+       }
+
        if (iov->iov_flags & IOV_RMAN_INITED) {
                rman_fini(&iov->rman);
                iov->iov_flags &= ~IOV_RMAN_INITED;
@@ -896,6 +908,11 @@ pci_iov_delete_iov_children(struct pci_devinfo *dinfo)
                }
        }
 
+       if (iov->iov_bus_res != NULL) {
+               bus_release_resource(bus, iov->iov_bus_res);
+               iov->iov_bus_res = NULL;
+       }
+
        if (iov->iov_flags & IOV_RMAN_INITED) {
                rman_fini(&iov->rman);
                iov->iov_flags &= ~IOV_RMAN_INITED;
diff --git a/sys/dev/pci/pci_iov_private.h b/sys/dev/pci/pci_iov_private.h
index 7ae2219b936d..ecf0a9b21be5 100644
--- a/sys/dev/pci/pci_iov_private.h
+++ b/sys/dev/pci/pci_iov_private.h
@@ -39,6 +39,8 @@ struct pcicfg_iov {
        struct cdev *iov_cdev;
        nvlist_t *iov_schema;
 
+       struct resource *iov_bus_res;
+
        struct pci_iov_bar iov_bar[PCIR_MAX_BAR_0 + 1];
        struct rman rman;
        char rman_name[64];

Reply via email to