| From foo@baz Mon Mar 20 11:41:01 CET 2017 |
| From: alexander.levin@verizon.com |
| Date: Fri, 17 Mar 2017 00:48:25 +0000 |
| Subject: PCI: Do any VF BAR updates before enabling the BARs |
| To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org> |
| Cc: "stable@vger.kernel.org" <stable@vger.kernel.org> |
| Message-ID: <20170317004812.26960-18-alexander.levin@verizon.com> |
| |
| From: Gavin Shan <gwshan@linux.vnet.ibm.com> |
| |
| [ Upstream commit f40ec3c748c6912f6266c56a7f7992de61b255ed ] |
| |
| Previously we enabled VFs and enable their memory space before calling |
| pcibios_sriov_enable(). But pcibios_sriov_enable() may update the VF BARs: |
| for example, on PPC PowerNV we may change them to manage the association of |
| VFs to PEs. |
| |
| Because 64-bit BARs cannot be updated atomically, it's unsafe to update |
| them while they're enabled. The half-updated state may conflict with other |
| devices in the system. |
| |
| Call pcibios_sriov_enable() before enabling the VFs so any BAR updates |
| happen while the VF BARs are disabled. |
| |
| [bhelgaas: changelog] |
| Tested-by: Carol Soto <clsoto@us.ibm.com> |
| Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/pci/iov.c | 14 +++++++------- |
| 1 file changed, 7 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/pci/iov.c |
| +++ b/drivers/pci/iov.c |
| @@ -306,13 +306,6 @@ static int sriov_enable(struct pci_dev * |
| return rc; |
| } |
| |
| - pci_iov_set_numvfs(dev, nr_virtfn); |
| - iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE; |
| - pci_cfg_access_lock(dev); |
| - pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); |
| - msleep(100); |
| - pci_cfg_access_unlock(dev); |
| - |
| iov->initial_VFs = initial; |
| if (nr_virtfn < initial) |
| initial = nr_virtfn; |
| @@ -323,6 +316,13 @@ static int sriov_enable(struct pci_dev * |
| goto err_pcibios; |
| } |
| |
| + pci_iov_set_numvfs(dev, nr_virtfn); |
| + iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE; |
| + pci_cfg_access_lock(dev); |
| + pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); |
| + msleep(100); |
| + pci_cfg_access_unlock(dev); |
| + |
| for (i = 0; i < initial; i++) { |
| rc = pci_iov_add_virtfn(dev, i, 0); |
| if (rc) |