hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9J08D
--------------------------------
Previous commit 083577ae9d72 ("PCI/IOV: Add pci_sriov_numvfs_lock to support enable pci sriov concurrently") reduce performance of creating VFs belongs to different PFs. Fix it by checking whether a new bus will be created.
Fixes: 083577ae9d72 ("PCI/IOV: Add pci_sriov_numvfs_lock to support enable pci sriov concurrently") Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- drivers/pci/iov.c | 40 +++++++++++++++++++++++++++++++++------- include/linux/pci.h | 8 ++++++++ 2 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 7006413aa0a3..2190a6977c4e 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -240,6 +240,16 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id) return rc; }
+int pci_iov_add_virtfn_locked(struct pci_dev *dev, int id) +{ + int rc; + + mutex_lock(&pci_sriov_numvfs_lock); + rc = pci_iov_add_virtfn(dev, id); + mutex_unlock(&pci_sriov_numvfs_lock); + return rc; +} + void pci_iov_remove_virtfn(struct pci_dev *dev, int id) { char buf[VIRTFN_ID_LEN]; @@ -269,6 +279,13 @@ void pci_iov_remove_virtfn(struct pci_dev *dev, int id) pci_dev_put(dev); }
+void pci_iov_remove_virtfn_locked(struct pci_dev *dev, int id) +{ + mutex_lock(&pci_sriov_numvfs_lock); + pci_iov_remove_virtfn(dev, id); + mutex_unlock(&pci_sriov_numvfs_lock); +} + static ssize_t sriov_totalvfs_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -315,7 +332,6 @@ static ssize_t sriov_numvfs_store(struct device *dev, if (num_vfs > pci_sriov_get_totalvfs(pdev)) return -ERANGE;
- mutex_lock(&pci_sriov_numvfs_lock); device_lock(&pdev->dev);
if (num_vfs == pdev->sriov->num_VFs) @@ -352,7 +368,6 @@ static ssize_t sriov_numvfs_store(struct device *dev,
exit: device_unlock(&pdev->dev); - mutex_unlock(&pci_sriov_numvfs_lock);
if (ret < 0) return ret; @@ -463,14 +478,21 @@ static int sriov_add_vfs(struct pci_dev *dev, u16 num_vfs) return 0;
for (i = 0; i < num_vfs; i++) { - rc = pci_iov_add_virtfn(dev, i); + if (dev->bus->number != pci_iov_virtfn_bus(dev, i)) + rc = pci_iov_add_virtfn_locked(dev, i); + else + rc = pci_iov_add_virtfn(dev, i); if (rc) goto failed; } return 0; failed: - while (i--) - pci_iov_remove_virtfn(dev, i); + while (i--) { + if (dev->bus->number != pci_iov_virtfn_bus(dev, i)) + pci_iov_remove_virtfn_locked(dev, i); + else + pci_iov_remove_virtfn(dev, i); + }
return rc; } @@ -590,8 +612,12 @@ static void sriov_del_vfs(struct pci_dev *dev) struct pci_sriov *iov = dev->sriov; int i;
- for (i = 0; i < iov->num_VFs; i++) - pci_iov_remove_virtfn(dev, i); + for (i = 0; i < iov->num_VFs; i++) { + if (dev->bus->number != pci_iov_virtfn_bus(dev, i)) + pci_iov_remove_virtfn_locked(dev, i); + else + pci_iov_remove_virtfn(dev, i); + } }
static void sriov_disable(struct pci_dev *dev) diff --git a/include/linux/pci.h b/include/linux/pci.h index 0c116b6383ef..1638ac9a557c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2125,7 +2125,9 @@ void pci_disable_sriov(struct pci_dev *dev);
int pci_iov_sysfs_link(struct pci_dev *dev, struct pci_dev *virtfn, int id); int pci_iov_add_virtfn(struct pci_dev *dev, int id); +int pci_iov_add_virtfn_locked(struct pci_dev *dev, int id); void pci_iov_remove_virtfn(struct pci_dev *dev, int id); +void pci_iov_remove_virtfn_locked(struct pci_dev *dev, int id); int pci_num_vf(struct pci_dev *dev); int pci_vfs_assigned(struct pci_dev *dev); int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs); @@ -2165,8 +2167,14 @@ static inline int pci_iov_add_virtfn(struct pci_dev *dev, int id) { return -ENOSYS; } +static inline int pci_iov_add_virtfn_locked(struct pci_dev *dev, int id) +{ + return -ENOSYS; +} static inline void pci_iov_remove_virtfn(struct pci_dev *dev, int id) { } +static inline void pci_iov_remove_virtfn_locked(struct pci_dev *dev, + int id) { } static inline void pci_disable_sriov(struct pci_dev *dev) { } static inline int pci_num_vf(struct pci_dev *dev) { return 0; } static inline int pci_vfs_assigned(struct pci_dev *dev)