diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2020-12-18 03:46:50 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2020-12-18 03:46:50 +0000 |
| commit | 94f5c1cc7186ae555b962d2450cc17e06fd4fda0 (patch) | |
| tree | c3e4673c529090a891274ccf1e1e5aa12156d9ef | |
| parent | 2bb4be0f86501ec0565dba3d37ce0f7d7fc9c464 (diff) | |
Notes
| -rw-r--r-- | sys/dev/pci/pci_iov.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c index f5063d62ffc7..6db2cf445843 100644 --- a/sys/dev/pci/pci_iov.c +++ b/sys/dev/pci/pci_iov.c @@ -95,6 +95,7 @@ static void pci_iov_build_pf_schema(nvlist_t *schema, nvlist_t **driver_schema); static void pci_iov_build_vf_schema(nvlist_t *schema, nvlist_t **driver_schema); +static int pci_iov_delete_iov_children(struct pci_devinfo *dinfo); static nvlist_t *pci_iov_get_pf_subsystem_schema(void); static nvlist_t *pci_iov_get_vf_subsystem_schema(void); @@ -191,6 +192,7 @@ pci_iov_detach_method(device_t bus, device_t dev) { struct pci_devinfo *dinfo; struct pcicfg_iov *iov; + int error; mtx_lock(&Giant); dinfo = device_get_ivars(dev); @@ -201,11 +203,17 @@ pci_iov_detach_method(device_t bus, device_t dev) return (0); } - if (iov->iov_num_vfs != 0 || iov->iov_flags & IOV_BUSY) { + if ((iov->iov_flags & IOV_BUSY) != 0) { mtx_unlock(&Giant); return (EBUSY); } + error = pci_iov_delete_iov_children(dinfo); + if (error != 0) { + mtx_unlock(&Giant); + return (error); + } + dinfo->cfg.iov = NULL; if (iov->iov_cdev) { @@ -823,31 +831,20 @@ pci_iov_is_child_vf(struct pcicfg_iov *pf, device_t child) } static int -pci_iov_delete(struct cdev *cdev) +pci_iov_delete_iov_children(struct pci_devinfo *dinfo) { device_t bus, dev, vf, *devlist; - struct pci_devinfo *dinfo; struct pcicfg_iov *iov; int i, error, devcount; uint32_t iov_ctl; - mtx_lock(&Giant); - dinfo = cdev->si_drv1; + mtx_assert(&Giant, MA_OWNED); + iov = dinfo->cfg.iov; dev = dinfo->cfg.dev; bus = device_get_parent(dev); devlist = NULL; - if (iov->iov_flags & IOV_BUSY) { - mtx_unlock(&Giant); - return (EBUSY); - } - - if (iov->iov_num_vfs == 0) { - mtx_unlock(&Giant); - return (ECHILD); - } - iov->iov_flags |= IOV_BUSY; error = device_get_children(bus, &devlist, &devcount); @@ -905,6 +902,32 @@ pci_iov_delete(struct cdev *cdev) out: free(devlist, M_TEMP); iov->iov_flags &= ~IOV_BUSY; + return (error); +} + +static int +pci_iov_delete(struct cdev *cdev) +{ + struct pci_devinfo *dinfo; + struct pcicfg_iov *iov; + int error; + + mtx_lock(&Giant); + dinfo = cdev->si_drv1; + iov = dinfo->cfg.iov; + + if ((iov->iov_flags & IOV_BUSY) != 0) { + error = EBUSY; + goto out; + } + if (iov->iov_num_vfs == 0) { + error = ECHILD; + goto out; + } + + error = pci_iov_delete_iov_children(dinfo); + +out: mtx_unlock(&Giant); return (error); } |
