]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
PCI: Separate VF BAR updates from standard BAR updates
authorBjorn Helgaas <bhelgaas@google.com>
Fri, 13 Jan 2017 21:31:35 +0000 (14:31 -0700)
committerThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Thu, 26 Jan 2017 16:36:54 +0000 (14:36 -0200)
BugLink: http://bugs.launchpad.net/bugs/1625318
Previously pci_update_resource() used the same code path for updating
standard BARs and VF BARs in SR-IOV capabilities.

Split the VF BAR update into a new pci_iov_update_resource() internal
interface, which makes it simpler to compute the BAR address (we can get
rid of pci_resource_bar() and pci_iov_resource_bar()).

This patch:

  - Renames pci_update_resource() to pci_std_update_resource(),
  - Adds pci_iov_update_resource(),
  - Makes pci_update_resource() a wrapper that calls the appropriate one,

No functional change intended.

Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
(cherry picked from commit 6ffa2489c51da77564a0881a73765ea2169f955d)
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Acked-by: Seth Forshee <seth.forshee@canonical.com>
Acked-by: Brad Figg <brad.figg@canonical.com>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
drivers/pci/iov.c
drivers/pci/pci.h
drivers/pci/setup-res.c

index 5845d9b474c0c9e4382a0efa508b9d719c9e0b5d..6becbb67747825f4a179eb1f2ca7fc46eaa1fe94 100644 (file)
@@ -572,6 +572,56 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno)
                4 * (resno - PCI_IOV_RESOURCES);
 }
 
+/**
+ * pci_iov_update_resource - update a VF BAR
+ * @dev: the PCI device
+ * @resno: the resource number
+ *
+ * Update a VF BAR in the SR-IOV capability of a PF.
+ */
+void pci_iov_update_resource(struct pci_dev *dev, int resno)
+{
+       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;
+       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;
+
+       /*
+        * 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;
+
+       pcibios_resource_to_bus(dev->bus, &region, res);
+       new = region.start;
+       new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
+
+       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,
                                                      int resno)
 {
index d390fc1475eccf9f77491b5b401a823067b2995b..eda77d1baec1157ca7fc87820e65a7d30e38fd7b 100644 (file)
@@ -277,6 +277,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev)
 int pci_iov_init(struct pci_dev *dev);
 void pci_iov_release(struct pci_dev *dev);
 int pci_iov_resource_bar(struct pci_dev *dev, int resno);
+void pci_iov_update_resource(struct pci_dev *dev, int resno);
 resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
 void pci_restore_iov_state(struct pci_dev *dev);
 int pci_iov_bus_range(struct pci_bus *bus);
index 98c17b468fb2f8a42b63c7c762a4e5e2debea478..2d0243eb5e712235e217117ffb26f53de6d6e5cf 100644 (file)
@@ -25,8 +25,7 @@
 #include <linux/slab.h>
 #include "pci.h"
 
-
-void pci_update_resource(struct pci_dev *dev, int resno)
+static void pci_std_update_resource(struct pci_dev *dev, int resno)
 {
        struct pci_bus_region region;
        bool disable;
@@ -114,6 +113,16 @@ void pci_update_resource(struct pci_dev *dev, int resno)
                pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
+void pci_update_resource(struct pci_dev *dev, int resno)
+{
+       if (resno <= PCI_ROM_RESOURCE)
+               pci_std_update_resource(dev, resno);
+#ifdef CONFIG_PCI_IOV
+       else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
+               pci_iov_update_resource(dev, resno);
+#endif
+}
+
 int pci_claim_resource(struct pci_dev *dev, int resource)
 {
        struct resource *res = &dev->resource[resource];