Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1523610

[PATCH v8 09/16] drivers: acpi: iort: add support for ARM SMMU platform devices creation

From Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Newsgroups linux.kernel
Subject [PATCH v8 09/16] drivers: acpi: iort: add support for ARM SMMU platform devices creation
Date 2016-11-16 16:40 +0100
Message-ID <sEatA-4HA-31@gated-at.bofh.it> (permalink)
References <sEajT-4Eo-3@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


In ARM ACPI systems, IOMMU components are specified through static
IORT table entries. In order to create platform devices for the
corresponding ARM SMMU components, IORT kernel code should be made
able to parse IORT table entries and create platform devices
dynamically.

This patch adds the generic IORT infrastructure required to create
platform devices for ARM SMMUs.

ARM SMMU versions have different resources requirement therefore this
patch also introduces an IORT specific structure (ie iort_iommu_config)
that contains hooks (to be defined when the corresponding ARM SMMU
driver support is added to the kernel) to be used to define the
platform devices names, init the IOMMUs, count their resources and
finally initialize them.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Tomasz Nowicki <tn@semihalf.com>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/arm64/iort.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 4bb6acb..ddf83b5 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -19,9 +19,11 @@
 #define pr_fmt(fmt)	"ACPI: IORT: " fmt
 
 #include <linux/acpi_iort.h>
+#include <linux/iommu.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 
 struct iort_its_msi_chip {
@@ -457,6 +459,153 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+struct iort_iommu_config {
+	const char *name;
+	int (*iommu_init)(struct acpi_iort_node *node);
+	bool (*iommu_is_coherent)(struct acpi_iort_node *node);
+	int (*iommu_count_resources)(struct acpi_iort_node *node);
+	void (*iommu_init_resources)(struct resource *res,
+				     struct acpi_iort_node *node);
+};
+
+static __init
+const struct iort_iommu_config *iort_get_iommu_cfg(struct acpi_iort_node *node)
+{
+	return NULL;
+}
+
+/**
+ * iort_add_smmu_platform_device() - Allocate a platform device for SMMU
+ * @node: Pointer to SMMU ACPI IORT node
+ *
+ * Returns: 0 on success, <0 failure
+ */
+static int __init iort_add_smmu_platform_device(struct acpi_iort_node *node)
+{
+	struct fwnode_handle *fwnode;
+	struct platform_device *pdev;
+	struct resource *r;
+	enum dev_dma_attr attr;
+	int ret, count;
+	const struct iort_iommu_config *ops = iort_get_iommu_cfg(node);
+
+	if (!ops)
+		return -ENODEV;
+
+	pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO);
+	if (!pdev)
+		return PTR_ERR(pdev);
+
+	count = ops->iommu_count_resources(node);
+
+	r = kcalloc(count, sizeof(*r), GFP_KERNEL);
+	if (!r) {
+		ret = -ENOMEM;
+		goto dev_put;
+	}
+
+	ops->iommu_init_resources(r, node);
+
+	ret = platform_device_add_resources(pdev, r, count);
+	/*
+	 * Resources are duplicated in platform_device_add_resources,
+	 * free their allocated memory
+	 */
+	kfree(r);
+
+	if (ret)
+		goto dev_put;
+
+	/*
+	 * Add a copy of IORT node pointer to platform_data to
+	 * be used to retrieve IORT data information.
+	 */
+	ret = platform_device_add_data(pdev, &node, sizeof(node));
+	if (ret)
+		goto dev_put;
+
+	/*
+	 * We expect the dma masks to be equivalent for
+	 * all SMMUs set-ups
+	 */
+	pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+	fwnode = iort_get_fwnode(node);
+
+	if (!fwnode) {
+		ret = -ENODEV;
+		goto dev_put;
+	}
+
+	pdev->dev.fwnode = fwnode;
+
+	attr = ops->iommu_is_coherent(node) ?
+			     DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT;
+
+	/* Configure DMA for the page table walker */
+	acpi_dma_configure(&pdev->dev, attr);
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto dma_deconfigure;
+
+	return 0;
+
+dma_deconfigure:
+	acpi_dma_deconfigure(&pdev->dev);
+dev_put:
+	platform_device_put(pdev);
+
+	return ret;
+}
+
+static void __init iort_init_platform_devices(void)
+{
+	struct acpi_iort_node *iort_node, *iort_end;
+	struct acpi_table_iort *iort;
+	struct fwnode_handle *fwnode;
+	int i, ret;
+
+	/*
+	 * iort_table and iort both point to the start of IORT table, but
+	 * have different struct types
+	 */
+	iort = (struct acpi_table_iort *)iort_table;
+
+	/* Get the first IORT node */
+	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+				 iort->node_offset);
+	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+				iort_table->length);
+
+	for (i = 0; i < iort->node_count; i++) {
+		if (iort_node >= iort_end) {
+			pr_err("iort node pointer overflows, bad table\n");
+			return;
+		}
+
+		if ((iort_node->type == ACPI_IORT_NODE_SMMU) ||
+			(iort_node->type == ACPI_IORT_NODE_SMMU_V3)) {
+
+			fwnode = acpi_alloc_fwnode_static();
+			if (!fwnode)
+				return;
+
+			iort_set_fwnode(iort_node, fwnode);
+
+			ret = iort_add_smmu_platform_device(iort_node);
+			if (ret) {
+				iort_delete_fwnode(iort_node);
+				acpi_free_fwnode_static(fwnode);
+				return;
+			}
+		}
+
+		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+					 iort_node->length);
+	}
+}
+
 void __init acpi_iort_init(void)
 {
 	acpi_status status;
@@ -472,5 +621,7 @@ void __init acpi_iort_init(void)
 		return;
 	}
 
+	iort_init_platform_devices();
+
 	acpi_probe_device_table(iort);
 }
-- 
2.10.0

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH v8 00/16] ACPI IORT ARM SMMU support Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:30 +0100
  [PATCH v8 11/16] drivers: iommu: arm-smmu-v3: add IORT configuration Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:30 +0100
    Re: [PATCH v8 11/16] drivers: iommu: arm-smmu-v3: add IORT  configuration Will Deacon <will.deacon@arm.com> - 2016-11-18 17:00 +0100
  [PATCH v8 07/16] drivers: acpi: implement acpi_dma_configure Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:30 +0100
  [PATCH v8 08/16] drivers: acpi: iort: add node match function Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:30 +0100
  [PATCH v8 01/16] drivers: acpi: add FWNODE_ACPI_STATIC fwnode type Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:30 +0100
  [PATCH v8 06/16] drivers: iommu: arm-smmu-v3: convert struct device of_node to fwnode usage Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:30 +0100
    Re: [PATCH v8 06/16] drivers: iommu: arm-smmu-v3: convert struct  device of_node to fwnode usage Will Deacon <will.deacon@arm.com> - 2016-11-18 16:00 +0100
  [PATCH v8 14/16] drivers: acpi: iort: replace rid map type with type mask Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:30 +0100
  [PATCH v8 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:40 +0100
    Re: [PATCH v8 04/16] drivers: iommu: make of_iommu_set/get_ops() DT  agnostic Will Deacon <will.deacon@arm.com> - 2016-11-18 15:50 +0100
  [PATCH v8 03/16] drivers: acpi: iort: add support for IOMMU fwnode registration Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:40 +0100
  [PATCH v8 16/16] drivers: acpi: iort: introduce iort_iommu_configure Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:40 +0100
  [PATCH v8 09/16] drivers: acpi: iort: add support for ARM SMMU platform devices creation Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:40 +0100
  [PATCH v8 10/16] drivers: iommu: arm-smmu-v3: split probe functions into DT/generic portions Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:40 +0100
    Re: [PATCH v8 10/16] drivers: iommu: arm-smmu-v3: split probe  functions into DT/generic portions Will Deacon <will.deacon@arm.com> - 2016-11-18 16:50 +0100
  [PATCH v8 05/16] drivers: iommu: arm-smmu: convert struct device of_node to fwnode usage Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:40 +0100
    Re: [PATCH v8 05/16] drivers: iommu: arm-smmu: convert struct device  of_node to fwnode usage Will Deacon <will.deacon@arm.com> - 2016-11-18 16:00 +0100
  [PATCH v8 15/16] drivers: acpi: iort: add single mapping function Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2016-11-16 16:40 +0100

csiph-web