lkml.org 
[lkml]   [2015]   [Oct]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH 1/5] iov: Update virtfn_max_buses to validate offset and stride
From
Date
This patch pulls the validation of offset and stride into virtfn_max_buses.
The general idea is to validate offset and stride for each possible value
of numvfs in addition to still determining the maximum bus value for the
VFs.

I also reversed the loop as the most likely maximum will be when numvfs is
set to total_VFs. In addition this makes it so that we loop down to a
value of 0 for numvfs which should be the resting state for the register.

Fixes: 8e20e89658f2 ("PCI: Set SR-IOV NumVFs to zero after enumeration")
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
drivers/pci/iov.c | 42 ++++++++++++++++++++++++------------------
1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index f8bfc1d39845..099050d78a39 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -54,24 +54,33 @@ static inline void pci_iov_set_numvfs(struct pci_dev *dev, int nr_virtfn)
* The PF consumes one bus number. NumVFs, First VF Offset, and VF Stride
* determine how many additional bus numbers will be consumed by VFs.
*
- * Iterate over all valid NumVFs and calculate the maximum number of bus
- * numbers that could ever be required.
+ * Iterate over all valid NumVFs, validate offset and stride, and calculate
+ * the maximum number of bus numbers that could ever be required.
*/
-static inline u8 virtfn_max_buses(struct pci_dev *dev)
+static int virtfn_max_buses(struct pci_dev *dev)
{
struct pci_sriov *iov = dev->sriov;
- int nr_virtfn;
- u8 max = 0;
+ int nr_virtfn = iov->total_VFs;
int busnr;

- for (nr_virtfn = 1; nr_virtfn <= iov->total_VFs; nr_virtfn++) {
- pci_iov_set_numvfs(dev, nr_virtfn);
+ pci_iov_set_numvfs(dev, nr_virtfn);
+
+ while (nr_virtfn--) {
+ if (!iov->offset || !iov->stride)
+ goto err;
+
busnr = pci_iov_virtfn_bus(dev, nr_virtfn - 1);
- if (busnr > max)
- max = busnr;
+ if (busnr > iov->max_VF_buses)
+ iov->max_VF_buses = busnr;
+
+ pci_iov_set_numvfs(dev, nr_virtfn);
}

- return max;
+ return 0;
+err:
+ pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0);
+
+ return -EIO;
}

static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
@@ -467,22 +476,19 @@ found:

dev->sriov = iov;
dev->is_physfn = 1;
- iov->max_VF_buses = virtfn_max_buses(dev);
- pci_iov_set_numvfs(dev, 0);
- if (!iov->offset || (total > 1 && !iov->stride)) {
- rc = -EIO;
- goto failed;
- }

- return 0;
+ rc = virtfn_max_buses(dev);
+ if (!rc)
+ return 0;

+ dev->sriov = NULL;
+ dev->is_physfn = 0;
failed:
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &dev->resource[i + PCI_IOV_RESOURCES];
res->flags = 0;
}

- dev->sriov = NULL;
kfree(iov);
return rc;
}


\
 
 \ /
  Last update: 2015-10-27 22:01    [W:0.172 / U:0.064 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site