mfd: rk808: add rk808-clkout mfd cell for rk805
[firefly-linux-kernel-4.4.55.git] / drivers / pci / iov.c
index 31f31d460fc9de789d28d72365122224fa3b2551..3575277125393350d5eb0324388b1d1d6795e792 100644 (file)
@@ -303,13 +303,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
                        return rc;
        }
 
-       pci_iov_set_numvfs(dev, nr_virtfn);
-       iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
-       pci_cfg_access_lock(dev);
-       pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
-       msleep(100);
-       pci_cfg_access_unlock(dev);
-
        iov->initial_VFs = initial;
        if (nr_virtfn < initial)
                initial = nr_virtfn;
@@ -320,6 +313,13 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
                goto err_pcibios;
        }
 
+       pci_iov_set_numvfs(dev, nr_virtfn);
+       iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
+       pci_cfg_access_lock(dev);
+       pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
+       msleep(100);
+       pci_cfg_access_unlock(dev);
+
        for (i = 0; i < initial; i++) {
                rc = virtfn_add(dev, i, 0);
                if (rc)
@@ -555,21 +555,61 @@ void pci_iov_release(struct pci_dev *dev)
 }
 
 /**
- * pci_iov_resource_bar - get position of the SR-IOV BAR
+ * pci_iov_update_resource - update a VF BAR
  * @dev: the PCI device
  * @resno: the resource number
  *
- * Returns position of the BAR encapsulated in the SR-IOV capability.
+ * Update a VF BAR in the SR-IOV capability of a PF.
  */
-int pci_iov_resource_bar(struct pci_dev *dev, int resno)
+void pci_iov_update_resource(struct pci_dev *dev, int resno)
 {
-       if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END)
-               return 0;
+       struct pci_sriov *iov = dev->is_physfn ? dev->sriov : NULL;
+       struct resource *res = dev->resource + resno;
+       int vf_bar = resno - PCI_IOV_RESOURCES;
+       struct pci_bus_region region;
+       u16 cmd;
+       u32 new;
+       int reg;
+
+       /*
+        * The generic pci_restore_bars() path calls this for all devices,
+        * including VFs and non-SR-IOV devices.  If this is not a PF, we
+        * have nothing to do.
+        */
+       if (!iov)
+               return;
+
+       pci_read_config_word(dev, iov->pos + PCI_SRIOV_CTRL, &cmd);
+       if ((cmd & PCI_SRIOV_CTRL_VFE) && (cmd & PCI_SRIOV_CTRL_MSE)) {
+               dev_WARN(&dev->dev, "can't update enabled VF BAR%d %pR\n",
+                        vf_bar, res);
+               return;
+       }
+
+       /*
+        * Ignore unimplemented BARs, unused resource slots for 64-bit
+        * BARs, and non-movable resources, e.g., those described via
+        * Enhanced Allocation.
+        */
+       if (!res->flags)
+               return;
+
+       if (res->flags & IORESOURCE_UNSET)
+               return;
+
+       if (res->flags & IORESOURCE_PCI_FIXED)
+               return;
 
-       BUG_ON(!dev->is_physfn);
+       pcibios_resource_to_bus(dev->bus, &region, res);
+       new = region.start;
+       new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
 
-       return dev->sriov->pos + PCI_SRIOV_BAR +
-               4 * (resno - PCI_IOV_RESOURCES);
+       reg = iov->pos + PCI_SRIOV_BAR + 4 * vf_bar;
+       pci_write_config_dword(dev, reg, new);
+       if (res->flags & IORESOURCE_MEM_64) {
+               new = region.start >> 16 >> 16;
+               pci_write_config_dword(dev, reg + 4, new);
+       }
 }
 
 resource_size_t __weak pcibios_iov_resource_alignment(struct pci_dev *dev,