[Arm-dev] [PATCH v1 84/87] pci, acpi, dma: Unify coherency checking logic for PCI devices.

Thu Aug 13 13:19:21 UTC 2015
Vadim Lomovtsev <Vadim.Lomovtsev at caviumnetworks.com>

From: Tomasz Nowicki <tn at semihalf.com>

ACPI spec5.1 states that the value of _CCA is inherited by all
descendants of bus master devices, root PCI bridge in this case.
So this patch is checking if PCI device's root bridge has coherency
flag set and then mounts DMA ops (in similar way as DT does).

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
Signed-off-by: Vadim Lomovtsev <Vadim.Lomovtsev at caviumnetworks.com>
---
 drivers/pci/pci-acpi.c   | 13 +++++++++++++
 drivers/pci/pci.c        | 10 ++++++++++
 drivers/pci/probe.c      |  2 +-
 include/linux/pci-acpi.h |  2 ++
 include/linux/pci.h      |  2 ++
 5 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 314a625..9ba685c 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -291,6 +291,19 @@ int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp)
 }
 EXPORT_SYMBOL_GPL(pci_get_hp_params);
 
+
+void pci_acpi_dma_configure(struct pci_dev *dev)
+{
+	struct device *bridge = pci_get_host_bridge_device(dev);
+	bool coherent;
+
+	if (acpi_check_dma(ACPI_COMPANION(bridge), &coherent))
+		arch_setup_dma_ops(&dev->dev, 0, 0, NULL, coherent);
+
+	pci_put_host_bridge_device(bridge);
+}
+EXPORT_SYMBOL_GPL(pci_acpi_dma_configure);
+
 /**
  * pci_acpi_wake_bus - Root bus wakeup notification fork function.
  * @work: Work item to handle.
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0eec993..79c34d4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -13,6 +13,7 @@
 #include <linux/of.h>
 #include <linux/of_pci.h>
 #include <linux/pci.h>
+#include <linux/pci-acpi.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -4539,6 +4540,15 @@ out:
 #endif
 #endif
 
+void pci_dma_configure(struct pci_dev *dev)
+{
+	if (acpi_disabled)
+		of_pci_dma_configure(dev);
+	else
+		pci_acpi_dma_configure(dev);
+}
+EXPORT_SYMBOL(pci_dma_configure);
+
 /**
  * pci_ext_cfg_avail - can we access extended PCI config space?
  *
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 11ec2e7..9fad896 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1557,7 +1557,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 	dev->dev.dma_mask = &dev->dma_mask;
 	dev->dev.dma_parms = &dev->dma_parms;
 	dev->dev.coherent_dma_mask = 0xffffffffull;
-	of_pci_dma_configure(dev);
+	pci_dma_configure(dev);
 
 	pci_set_dma_max_seg_size(dev, 65536);
 	pci_set_dma_seg_boundary(dev, 0xffffffff);
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index a965efa..786d929 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -54,6 +54,7 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
 
 void acpi_pci_add_bus(struct pci_bus *bus);
 void acpi_pci_remove_bus(struct pci_bus *bus);
+void pci_acpi_dma_configure(struct pci_dev *dev);
 
 #ifdef	CONFIG_ACPI_PCI_SLOT
 void acpi_pci_slot_init(void);
@@ -85,6 +86,7 @@ extern const u8 pci_acpi_dsm_uuid[];
 #else	/* CONFIG_ACPI */
 static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
+static inline void pci_acpi_dma_configure(struct pci_dev *dev) { }
 #endif	/* CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI_APEI
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7474225..3732cad 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1336,6 +1336,7 @@ static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
 typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
 		      unsigned int command_bits, u32 flags);
 void pci_register_set_vga_state(arch_set_vga_state_t func);
+void pci_dma_configure(struct pci_dev *dev);
 
 #else /* CONFIG_PCI is not enabled */
 
@@ -1439,6 +1440,7 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
 static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
 static inline struct pci_dev *pci_dev_get(struct pci_dev *dev) { return NULL; }
 static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
+static inline void pci_dma_configure(struct pci_dev *dev) { }
 
 #define dev_is_pci(d) (false)
 #define dev_is_pf(d) (false)
-- 
2.4.3