hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9J08D
--------------------------------
Previous commit 700a05bd8dba ("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: 700a05bd8dba ("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 +++++++++++++++++++++++++++++++++++----- drivers/pci/pci-sysfs.c | 4 ---- include/linux/pci.h | 8 ++++++++ 3 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index c5f3cd4ed766..8d1f1e436d1a 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -18,6 +18,8 @@
#define VIRTFN_ID_LEN 16
+static DEFINE_MUTEX(pci_sriov_numvfs_lock); + int pci_iov_virtfn_bus(struct pci_dev *dev, int vf_id) { if (!dev->is_physfn) @@ -212,6 +214,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]; @@ -241,6 +253,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); +} + int __weak pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs) { return 0; @@ -337,7 +356,10 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) pci_cfg_access_unlock(dev);
for (i = 0; i < initial; 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; } @@ -348,8 +370,12 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) 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); + }
err_pcibios: iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); @@ -375,8 +401,12 @@ static void sriov_disable(struct pci_dev *dev) if (!iov->num_VFs) return;
- 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); + }
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); pci_cfg_access_lock(dev); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index e35c2f0ee28c..48c56cb08652 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -31,8 +31,6 @@
static int sysfs_initialized; /* = 0 */
-static DEFINE_MUTEX(pci_sriov_numvfs_lock); - /* show configuration fields */ #define pci_config_attr(field, format_string) \ static ssize_t \ @@ -606,7 +604,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) @@ -643,7 +640,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; diff --git a/include/linux/pci.h b/include/linux/pci.h index bc49349fcc53..f4bc2a7122f4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2046,7 +2046,9 @@ int pci_iov_virtfn_devfn(struct pci_dev *dev, int id); int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); void pci_disable_sriov(struct pci_dev *dev); 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); @@ -2074,8 +2076,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)