|
@@ -16,6 +16,8 @@
|
|
|
#include <linux/pm_runtime.h>
|
|
|
#include <linux/suspend.h>
|
|
|
#include <linux/kexec.h>
|
|
|
+#include <linux/of_device.h>
|
|
|
+#include <linux/acpi.h>
|
|
|
#include "pci.h"
|
|
|
#include "pcie/portdrv.h"
|
|
|
|
|
@@ -1577,6 +1579,35 @@ static int pci_bus_num_vf(struct device *dev)
|
|
|
return pci_num_vf(to_pci_dev(dev));
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * pci_dma_configure - Setup DMA configuration
|
|
|
+ * @dev: ptr to dev structure
|
|
|
+ *
|
|
|
+ * Function to update PCI devices's DMA configuration using the same
|
|
|
+ * info from the OF node or ACPI node of host bridge's parent (if any).
|
|
|
+ */
|
|
|
+static int pci_dma_configure(struct device *dev)
|
|
|
+{
|
|
|
+ struct device *bridge;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ bridge = pci_get_host_bridge_device(to_pci_dev(dev));
|
|
|
+
|
|
|
+ if (IS_ENABLED(CONFIG_OF) && bridge->parent &&
|
|
|
+ bridge->parent->of_node) {
|
|
|
+ ret = of_dma_configure(dev, bridge->parent->of_node);
|
|
|
+ } else if (has_acpi_companion(bridge)) {
|
|
|
+ struct acpi_device *adev = to_acpi_device_node(bridge->fwnode);
|
|
|
+ enum dev_dma_attr attr = acpi_get_dma_attr(adev);
|
|
|
+
|
|
|
+ if (attr != DEV_DMA_NOT_SUPPORTED)
|
|
|
+ ret = acpi_dma_configure(dev, attr);
|
|
|
+ }
|
|
|
+
|
|
|
+ pci_put_host_bridge_device(bridge);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
struct bus_type pci_bus_type = {
|
|
|
.name = "pci",
|
|
|
.match = pci_bus_match,
|
|
@@ -1589,6 +1620,7 @@ struct bus_type pci_bus_type = {
|
|
|
.drv_groups = pci_drv_groups,
|
|
|
.pm = PCI_PM_OPS_PTR,
|
|
|
.num_vf = pci_bus_num_vf,
|
|
|
+ .dma_configure = pci_dma_configure,
|
|
|
.force_dma = true,
|
|
|
};
|
|
|
EXPORT_SYMBOL(pci_bus_type);
|