aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorWei Yang <weiyang@linux.vnet.ibm.com>2015-03-25 04:23:44 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2015-03-30 22:02:35 -0400
commit0e6c9122a6ec96d19f1db61e9750287d86b6829c (patch)
tree8bcf0dad431a260735d35172fd336c09185a74f3 /drivers/pci
parente88ae01d2c43be3c3a6f340bfa7bab8b87127f57 (diff)
PCI: Keep individual VF BAR size in struct pci_sriov
Currently we don't store the individual VF BAR size. We calculate it when needed by dividing the PF's IOV resource size (which contains space for *all* the VFs) by total_VFs or by reading the BAR in the SR-IOV capability again. Keep the individual VF BAR size in struct pci_sriov.barsz[], add pci_iov_resource_size() to retrieve it, and use that instead of doing the division or reading the SR-IOV capability BAR. [bhelgaas: rename to "barsz[]", simplify barsz[] index computation, remove SR-IOV capability BAR sizing] Signed-off-by: Wei Yang <weiyang@linux.vnet.ibm.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/iov.c39
-rw-r--r--drivers/pci/pci.h1
2 files changed, 21 insertions, 19 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 05f9d97e4175..5bca0e1a2799 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -57,6 +57,14 @@ static void virtfn_remove_bus(struct pci_bus *physbus, struct pci_bus *virtbus)
57 pci_remove_bus(virtbus); 57 pci_remove_bus(virtbus);
58} 58}
59 59
60resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
61{
62 if (!dev->is_physfn)
63 return 0;
64
65 return dev->sriov->barsz[resno - PCI_IOV_RESOURCES];
66}
67
60static int virtfn_add(struct pci_dev *dev, int id, int reset) 68static int virtfn_add(struct pci_dev *dev, int id, int reset)
61{ 69{
62 int i; 70 int i;
@@ -92,8 +100,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
92 continue; 100 continue;
93 virtfn->resource[i].name = pci_name(virtfn); 101 virtfn->resource[i].name = pci_name(virtfn);
94 virtfn->resource[i].flags = res->flags; 102 virtfn->resource[i].flags = res->flags;
95 size = resource_size(res); 103 size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
96 do_div(size, iov->total_VFs);
97 virtfn->resource[i].start = res->start + size * id; 104 virtfn->resource[i].start = res->start + size * id;
98 virtfn->resource[i].end = virtfn->resource[i].start + size - 1; 105 virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
99 rc = request_resource(res, &virtfn->resource[i]); 106 rc = request_resource(res, &virtfn->resource[i]);
@@ -311,7 +318,7 @@ static void sriov_disable(struct pci_dev *dev)
311 318
312static int sriov_init(struct pci_dev *dev, int pos) 319static int sriov_init(struct pci_dev *dev, int pos)
313{ 320{
314 int i; 321 int i, bar64;
315 int rc; 322 int rc;
316 int nres; 323 int nres;
317 u32 pgsz; 324 u32 pgsz;
@@ -360,29 +367,29 @@ found:
360 pgsz &= ~(pgsz - 1); 367 pgsz &= ~(pgsz - 1);
361 pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz); 368 pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz);
362 369
370 iov = kzalloc(sizeof(*iov), GFP_KERNEL);
371 if (!iov)
372 return -ENOMEM;
373
363 nres = 0; 374 nres = 0;
364 for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { 375 for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
365 res = dev->resource + PCI_IOV_RESOURCES + i; 376 res = dev->resource + PCI_IOV_RESOURCES + i;
366 i += __pci_read_base(dev, pci_bar_unknown, res, 377 bar64 = __pci_read_base(dev, pci_bar_unknown, res,
367 pos + PCI_SRIOV_BAR + i * 4); 378 pos + PCI_SRIOV_BAR + i * 4);
368 if (!res->flags) 379 if (!res->flags)
369 continue; 380 continue;
370 if (resource_size(res) & (PAGE_SIZE - 1)) { 381 if (resource_size(res) & (PAGE_SIZE - 1)) {
371 rc = -EIO; 382 rc = -EIO;
372 goto failed; 383 goto failed;
373 } 384 }
385 iov->barsz[i] = resource_size(res);
374 res->end = res->start + resource_size(res) * total - 1; 386 res->end = res->start + resource_size(res) * total - 1;
375 dev_info(&dev->dev, "VF(n) BAR%d space: %pR (contains BAR%d for %d VFs)\n", 387 dev_info(&dev->dev, "VF(n) BAR%d space: %pR (contains BAR%d for %d VFs)\n",
376 i, res, i, total); 388 i, res, i, total);
389 i += bar64;
377 nres++; 390 nres++;
378 } 391 }
379 392
380 iov = kzalloc(sizeof(*iov), GFP_KERNEL);
381 if (!iov) {
382 rc = -ENOMEM;
383 goto failed;
384 }
385
386 iov->pos = pos; 393 iov->pos = pos;
387 iov->nres = nres; 394 iov->nres = nres;
388 iov->ctrl = ctrl; 395 iov->ctrl = ctrl;
@@ -414,6 +421,7 @@ failed:
414 res->flags = 0; 421 res->flags = 0;
415 } 422 }
416 423
424 kfree(iov);
417 return rc; 425 return rc;
418} 426}
419 427
@@ -510,14 +518,7 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno)
510 */ 518 */
511resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno) 519resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
512{ 520{
513 struct resource tmp; 521 return pci_iov_resource_size(dev, resno);
514 int reg = pci_iov_resource_bar(dev, resno);
515
516 if (!reg)
517 return 0;
518
519 __pci_read_base(dev, pci_bar_unknown, &tmp, reg);
520 return resource_alignment(&tmp);
521} 522}
522 523
523/** 524/**
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4091f82239cd..57329645dd01 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -247,6 +247,7 @@ struct pci_sriov {
247 struct pci_dev *dev; /* lowest numbered PF */ 247 struct pci_dev *dev; /* lowest numbered PF */
248 struct pci_dev *self; /* this PF */ 248 struct pci_dev *self; /* this PF */
249 struct mutex lock; /* lock for VF bus */ 249 struct mutex lock; /* lock for VF bus */
250 resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
250}; 251};
251 252
252#ifdef CONFIG_PCI_ATS 253#ifdef CONFIG_PCI_ATS