PCI: Separate VF BAR updates from standard BAR updates
authorBjorn Helgaas <bhelgaas@google.com>
Mon, 28 Nov 2016 15:15:52 +0000 (09:15 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 30 Nov 2016 00:05:09 +0000 (18:05 -0600)
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>
drivers/pci/iov.c
drivers/pci/pci.h
drivers/pci/setup-res.c

index d41ec29..aa49954 100644 (file)
@@ -571,6 +571,56 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno)
                4 * (resno - PCI_IOV_RESOURCES);
 }
 
                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)
 {
 resource_size_t __weak pcibios_iov_resource_alignment(struct pci_dev *dev,
                                                      int resno)
 {
index 4518562..5bfcb92 100644 (file)
@@ -290,6 +290,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);
 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);
 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 53bc063..5ddeb67 100644 (file)
@@ -25,8 +25,7 @@
 #include <linux/slab.h>
 #include "pci.h"
 
 #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;
 {
        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);
 }
 
                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];
 int pci_claim_resource(struct pci_dev *dev, int resource)
 {
        struct resource *res = &dev->resource[resource];