summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRam Pai <linuxram@us.ibm.com>2011-11-06 10:33:10 +0800
committerJesse Barnes <jbarnes@virtuousgeek.org>2011-12-05 10:30:22 -0800
commitbbef98ab0f019f1b0c25c1acdf1683c68933d41b (patch)
tree07123873f64c4a61fef7c98a4744d4cad852c345 /drivers
parent8e8da023f5af71662867729db5547dc54786093c (diff)
downloadlinux-3.10-bbef98ab0f019f1b0c25c1acdf1683c68933d41b.tar.gz
linux-3.10-bbef98ab0f019f1b0c25c1acdf1683c68933d41b.tar.bz2
linux-3.10-bbef98ab0f019f1b0c25c1acdf1683c68933d41b.zip
PCI: defer enablement of SRIOV BARS
All the PCI BARs of a device are enabled when the device is enabled using pci_enable_device(). This unnecessarily enables SRIOV BARs of the device. On some platforms, which do not support SRIOV as yet, the pci_enable_device() fails to enable the device if its SRIOV BARs are not allocated resources correctly. The following patch fixes the above problem. The SRIOV BARs are now enabled when IOV capability of the device is enabled in sriov_enable(). NOTE: Note, there is subtle change in the pci_enable_device() API. Any driver that depends on SRIOV BARS to be enabled in pci_enable_device() can fail. The patch has been touch tested on power and x86 platform. Tested-by: Michael Wang <wangyun@linux.vnet.ibm.com> Signed-off-by: Ram Pai <linuxram@us.ibm.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/iov.c7
-rw-r--r--drivers/pci/pci.c2
2 files changed, 8 insertions, 1 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index b82c155d7b3..1969a3ee305 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -283,6 +283,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
struct resource *res;
struct pci_dev *pdev;
struct pci_sriov *iov = dev->sriov;
+ int bars = 0;
if (!nr_virtfn)
return 0;
@@ -307,6 +308,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
+ bars |= (1 << (i + PCI_IOV_RESOURCES));
res = dev->resource + PCI_IOV_RESOURCES + i;
if (res->parent)
nres++;
@@ -324,6 +326,11 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
return -ENOMEM;
}
+ if (pci_enable_resources(dev, bars)) {
+ dev_err(&dev->dev, "SR-IOV: IOV BARS not allocated\n");
+ return -ENOMEM;
+ }
+
if (iov->link != dev->devfn) {
pdev = pci_get_slot(dev->bus, iov->link);
if (!pdev)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6f45a73c6e9..4788413f43d 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1126,7 +1126,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
if (atomic_add_return(1, &dev->enable_cnt) > 1)
return 0; /* already enabled */
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ for (i = 0; i < PCI_ROM_RESOURCE; i++)
if (dev->resource[i].flags & flags)
bars |= (1 << i);