[PATCH V11 04/17] PCI: Store VF BAR size in pci_sriov

Wei Yang weiyang at linux.vnet.ibm.com
Thu Jan 15 13:27:54 AEDT 2015


Currently we don't store the VF BAR size, and each time we calculate the
size by dividing the PF's IOV BAR size by total_VFs.

This patch stores the VF BAR size in pci_sriov and introduces a function to
retrieve it. Also, it adds a log message to show the total PF's IOV BAR
size.

Signed-off-by: Wei Yang <weiyang at linux.vnet.ibm.com>
---
 drivers/pci/iov.c   |   28 ++++++++++++++++++++--------
 drivers/pci/pci.h   |    2 ++
 include/linux/pci.h |    3 +++
 3 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 5f48201..b43628b 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -100,6 +100,14 @@ static void virtfn_remove_bus(struct pci_bus *physbus, struct pci_bus *virtbus)
 		pci_remove_bus(virtbus);
 }
 
+resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
+{
+	if (!dev->is_physfn)
+		return 0;
+
+	return dev->sriov->res[resno - PCI_IOV_RESOURCES];
+}
+
 static int virtfn_add(struct pci_dev *dev, int id, int reset)
 {
 	int i;
@@ -135,8 +143,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
 			continue;
 		virtfn->resource[i].name = pci_name(virtfn);
 		virtfn->resource[i].flags = res->flags;
-		size = resource_size(res);
-		do_div(size, iov->total_VFs);
+		size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
 		virtfn->resource[i].start = res->start + size * id;
 		virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
 		rc = request_resource(res, &virtfn->resource[i]);
@@ -419,6 +426,12 @@ found:
 	pgsz &= ~(pgsz - 1);
 	pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz);
 
+	iov = kzalloc(sizeof(*iov), GFP_KERNEL);
+	if (!iov) {
+		rc = -ENOMEM;
+		goto failed;
+	}
+
 	nres = 0;
 	for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
 		res = dev->resource + PCI_IOV_RESOURCES + i;
@@ -430,16 +443,15 @@ found:
 			rc = -EIO;
 			goto failed;
 		}
+		iov->res[res - dev->resource - PCI_IOV_RESOURCES] =
+			resource_size(res);
 		res->end = res->start + resource_size(res) * total - 1;
+		dev_info(&dev->dev, "VF BAR%d: %pR (for %d VFs)",
+				(int)(res - dev->resource - PCI_IOV_RESOURCES),
+				res, total);
 		nres++;
 	}
 
-	iov = kzalloc(sizeof(*iov), GFP_KERNEL);
-	if (!iov) {
-		rc = -ENOMEM;
-		goto failed;
-	}
-
 	iov->pos = pos;
 	iov->nres = nres;
 	iov->ctrl = ctrl;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 94faf97..b1c9fdd 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -241,6 +241,8 @@ struct pci_sriov {
 	struct pci_dev *dev;	/* lowest numbered PF */
 	struct pci_dev *self;	/* this PF */
 	struct mutex lock;	/* lock for VF bus */
+	resource_size_t res[PCI_SRIOV_NUM_BARS];
+				/* VF BAR size */
 };
 
 #ifdef CONFIG_PCI_ATS
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ae7a7ea..f0b5f87 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1670,6 +1670,7 @@ 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);
 int pci_sriov_get_totalvfs(struct pci_dev *dev);
+resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno);
 #else
 static inline int pci_iov_virtfn_bus(struct pci_dev *dev, int id)
 {
@@ -1689,6 +1690,8 @@ static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
 { return 0; }
 static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
 { return 0; }
+static inline resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
+{ return 0; }
 #endif
 
 #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
-- 
1.7.9.5



More information about the Linuxppc-dev mailing list