diff options
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/pci_iov.c | 25 | ||||
-rw-r--r-- | 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]; |