]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/pci/pci.c
Merge tag '5.6-rc-small-smb3-fix-for-stable' of git://git.samba.org/sfrench/cifs-2.6
[linux.git] / drivers / pci / pci.c
index df21e3227b57e711fbb0e33c4624fc1401ce9496..3c30e72e79ecdb678ddf36e6c5c2b17f4916c098 100644 (file)
@@ -1372,8 +1372,11 @@ int pci_save_state(struct pci_dev *dev)
 {
        int i;
        /* XXX: 100% dword access ok here? */
-       for (i = 0; i < 16; i++)
+       for (i = 0; i < 16; i++) {
                pci_read_config_dword(dev, i * 4, &dev->saved_config_space[i]);
+               pci_dbg(dev, "saving config space at offset %#x (reading %#x)\n",
+                       i * 4, dev->saved_config_space[i]);
+       }
        dev->state_saved = true;
 
        i = pci_save_pcie_state(dev);
@@ -5998,7 +6001,8 @@ EXPORT_SYMBOL_GPL(pci_pr3_present);
 /**
  * pci_add_dma_alias - Add a DMA devfn alias for a device
  * @dev: the PCI device for which alias is added
- * @devfn: alias slot and function
+ * @devfn_from: alias slot and function
+ * @nr_devfns: number of subsequent devfns to alias
  *
  * This helper encodes an 8-bit devfn as a bit number in dma_alias_mask
  * which is used to program permissible bus-devfn source addresses for DMA
@@ -6014,18 +6018,29 @@ EXPORT_SYMBOL_GPL(pci_pr3_present);
  * cannot be left as a userspace activity).  DMA aliases should therefore
  * be configured via quirks, such as the PCI fixup header quirk.
  */
-void pci_add_dma_alias(struct pci_dev *dev, u8 devfn)
+void pci_add_dma_alias(struct pci_dev *dev, u8 devfn_from, unsigned nr_devfns)
 {
+       int devfn_to;
+
+       nr_devfns = min(nr_devfns, (unsigned) MAX_NR_DEVFNS - devfn_from);
+       devfn_to = devfn_from + nr_devfns - 1;
+
        if (!dev->dma_alias_mask)
-               dev->dma_alias_mask = bitmap_zalloc(U8_MAX, GFP_KERNEL);
+               dev->dma_alias_mask = bitmap_zalloc(MAX_NR_DEVFNS, GFP_KERNEL);
        if (!dev->dma_alias_mask) {
                pci_warn(dev, "Unable to allocate DMA alias mask\n");
                return;
        }
 
-       set_bit(devfn, dev->dma_alias_mask);
-       pci_info(dev, "Enabling fixed DMA alias to %02x.%d\n",
-                PCI_SLOT(devfn), PCI_FUNC(devfn));
+       bitmap_set(dev->dma_alias_mask, devfn_from, nr_devfns);
+
+       if (nr_devfns == 1)
+               pci_info(dev, "Enabling fixed DMA alias to %02x.%d\n",
+                               PCI_SLOT(devfn_from), PCI_FUNC(devfn_from));
+       else if (nr_devfns > 1)
+               pci_info(dev, "Enabling fixed DMA alias for devfn range from %02x.%d to %02x.%d\n",
+                               PCI_SLOT(devfn_from), PCI_FUNC(devfn_from),
+                               PCI_SLOT(devfn_to), PCI_FUNC(devfn_to));
 }
 
 bool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2)
@@ -6033,7 +6048,9 @@ bool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2)
        return (dev1->dma_alias_mask &&
                test_bit(dev2->devfn, dev1->dma_alias_mask)) ||
               (dev2->dma_alias_mask &&
-               test_bit(dev1->devfn, dev2->dma_alias_mask));
+               test_bit(dev1->devfn, dev2->dma_alias_mask)) ||
+              pci_real_dma_dev(dev1) == dev2 ||
+              pci_real_dma_dev(dev2) == dev1;
 }
 
 bool pci_device_is_present(struct pci_dev *pdev)
@@ -6057,6 +6074,21 @@ void pci_ignore_hotplug(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_ignore_hotplug);
 
+/**
+ * pci_real_dma_dev - Get PCI DMA device for PCI device
+ * @dev: the PCI device that may have a PCI DMA alias
+ *
+ * Permits the platform to provide architecture-specific functionality to
+ * devices needing to alias DMA to another PCI device on another PCI bus. If
+ * the PCI device is on the same bus, it is recommended to use
+ * pci_add_dma_alias(). This is the default implementation. Architecture
+ * implementations can override this.
+ */
+struct pci_dev __weak *pci_real_dma_dev(struct pci_dev *dev)
+{
+       return dev;
+}
+
 resource_size_t __weak pcibios_default_alignment(void)
 {
        return 0;