diff options
| author | Wei Yang <weiyang@linux.vnet.ibm.com> | 2015-03-25 04:23:44 -0400 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2015-03-30 22:02:35 -0400 |
| commit | 0e6c9122a6ec96d19f1db61e9750287d86b6829c (patch) | |
| tree | 8bcf0dad431a260735d35172fd336c09185a74f3 /drivers/pci | |
| parent | e88ae01d2c43be3c3a6f340bfa7bab8b87127f57 (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.c | 39 | ||||
| -rw-r--r-- | drivers/pci/pci.h | 1 |
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 | ||
| 60 | resource_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 | |||
| 60 | static int virtfn_add(struct pci_dev *dev, int id, int reset) | 68 | static 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 | ||
| 312 | static int sriov_init(struct pci_dev *dev, int pos) | 319 | static 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 | */ |
| 511 | resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno) | 519 | resource_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 |
