diff options
Diffstat (limited to 'drivers')
-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 |