aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/iov.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/iov.c')
-rw-r--r--drivers/pci/iov.c70
1 files changed, 55 insertions, 15 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index e30f05c8517f..47227820406d 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -306,13 +306,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
306 return rc; 306 return rc;
307 } 307 }
308 308
309 pci_iov_set_numvfs(dev, nr_virtfn);
310 iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
311 pci_cfg_access_lock(dev);
312 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
313 msleep(100);
314 pci_cfg_access_unlock(dev);
315
316 iov->initial_VFs = initial; 309 iov->initial_VFs = initial;
317 if (nr_virtfn < initial) 310 if (nr_virtfn < initial)
318 initial = nr_virtfn; 311 initial = nr_virtfn;
@@ -323,6 +316,13 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
323 goto err_pcibios; 316 goto err_pcibios;
324 } 317 }
325 318
319 pci_iov_set_numvfs(dev, nr_virtfn);
320 iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
321 pci_cfg_access_lock(dev);
322 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
323 msleep(100);
324 pci_cfg_access_unlock(dev);
325
326 for (i = 0; i < initial; i++) { 326 for (i = 0; i < initial; i++) {
327 rc = pci_iov_add_virtfn(dev, i, 0); 327 rc = pci_iov_add_virtfn(dev, i, 0);
328 if (rc) 328 if (rc)
@@ -554,21 +554,61 @@ void pci_iov_release(struct pci_dev *dev)
554} 554}
555 555
556/** 556/**
557 * pci_iov_resource_bar - get position of the SR-IOV BAR 557 * pci_iov_update_resource - update a VF BAR
558 * @dev: the PCI device 558 * @dev: the PCI device
559 * @resno: the resource number 559 * @resno: the resource number
560 * 560 *
561 * Returns position of the BAR encapsulated in the SR-IOV capability. 561 * Update a VF BAR in the SR-IOV capability of a PF.
562 */ 562 */
563int pci_iov_resource_bar(struct pci_dev *dev, int resno) 563void pci_iov_update_resource(struct pci_dev *dev, int resno)
564{ 564{
565 if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END) 565 struct pci_sriov *iov = dev->is_physfn ? dev->sriov : NULL;
566 return 0; 566 struct resource *res = dev->resource + resno;
567 int vf_bar = resno - PCI_IOV_RESOURCES;
568 struct pci_bus_region region;
569 u16 cmd;
570 u32 new;
571 int reg;
572
573 /*
574 * The generic pci_restore_bars() path calls this for all devices,
575 * including VFs and non-SR-IOV devices. If this is not a PF, we
576 * have nothing to do.
577 */
578 if (!iov)
579 return;
580
581 pci_read_config_word(dev, iov->pos + PCI_SRIOV_CTRL, &cmd);
582 if ((cmd & PCI_SRIOV_CTRL_VFE) && (cmd & PCI_SRIOV_CTRL_MSE)) {
583 dev_WARN(&dev->dev, "can't update enabled VF BAR%d %pR\n",
584 vf_bar, res);
585 return;
586 }
587
588 /*
589 * Ignore unimplemented BARs, unused resource slots for 64-bit
590 * BARs, and non-movable resources, e.g., those described via
591 * Enhanced Allocation.
592 */
593 if (!res->flags)
594 return;
595
596 if (res->flags & IORESOURCE_UNSET)
597 return;
598
599 if (res->flags & IORESOURCE_PCI_FIXED)
600 return;
567 601
568 BUG_ON(!dev->is_physfn); 602 pcibios_resource_to_bus(dev->bus, &region, res);
603 new = region.start;
604 new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
569 605
570 return dev->sriov->pos + PCI_SRIOV_BAR + 606 reg = iov->pos + PCI_SRIOV_BAR + 4 * vf_bar;
571 4 * (resno - PCI_IOV_RESOURCES); 607 pci_write_config_dword(dev, reg, new);
608 if (res->flags & IORESOURCE_MEM_64) {
609 new = region.start >> 16 >> 16;
610 pci_write_config_dword(dev, reg + 4, new);
611 }
572} 612}
573 613
574resource_size_t __weak pcibios_iov_resource_alignment(struct pci_dev *dev, 614resource_size_t __weak pcibios_iov_resource_alignment(struct pci_dev *dev,