summaryrefslogtreecommitdiff
path: root/drivers/acpi/arm64
diff options
context:
space:
mode:
authorHanjun Guo <hanjun.guo@linaro.org>2017-10-13 15:09:49 +0800
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2017-10-16 14:30:05 +0100
commit86456a3f19c505049341eeb51cf9bb874d3b4752 (patch)
treed8a7ab1653fbba1dd617d93f3ae197a2d5773908 /drivers/acpi/arm64
parent8c8df8dcd69ea65cedb4d0b19c34a38c9fb68466 (diff)
ACPI/IORT: Add SMMUv3 specific special index mapping handling
IORT revision C introduced a mapping entry binding to describe ITS device ID mapping for SMMUv3 MSI interrupts. Enable the single mapping flag (ie that is used by SMMUv3 component for its special index mappings) for the SMMUv3 node in the IORT mapping API and add IORT code to handle special index mapping entry for the SMMUv3 IORT nodes to enable their MSI interrupts. In case the ACPICA for SMMUv3 device ID mapping is not ready, use the ACPICA version as a guard for function iort_get_id_mapping_index(). Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> [lorenzo.pieralisi@arm.com: patch split, typos fixing, rewrote the log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Diffstat (limited to 'drivers/acpi/arm64')
-rw-r--r--drivers/acpi/arm64/iort.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 55fbf645a777..3d7e3cd2eae8 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -356,7 +356,8 @@ static struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
if (map->flags & ACPI_IORT_ID_SINGLE_MAPPING) {
if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
- node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) {
+ node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX ||
+ node->type == ACPI_IORT_NODE_SMMU_V3) {
*id_out = map->output_base;
return parent;
}
@@ -365,10 +366,46 @@ static struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
return NULL;
}
+#if (ACPI_CA_VERSION > 0x20170929)
+static int iort_get_id_mapping_index(struct acpi_iort_node *node)
+{
+ struct acpi_iort_smmu_v3 *smmu;
+
+ switch (node->type) {
+ case ACPI_IORT_NODE_SMMU_V3:
+ /*
+ * SMMUv3 dev ID mapping index was introduced in revision 1
+ * table, not available in revision 0
+ */
+ if (node->revision < 1)
+ return -EINVAL;
+
+ smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+ /*
+ * ID mapping index is only ignored if all interrupts are
+ * GSIV based
+ */
+ if (smmu->event_gsiv && smmu->pri_gsiv && smmu->gerr_gsiv
+ && smmu->sync_gsiv)
+ return -EINVAL;
+
+ if (smmu->id_mapping_index >= node->mapping_count) {
+ pr_err(FW_BUG "[node %p type %d] ID mapping index overflows valid mappings\n",
+ node, node->type);
+ return -EINVAL;
+ }
+
+ return smmu->id_mapping_index;
+ default:
+ return -EINVAL;
+ }
+}
+#else
static inline int iort_get_id_mapping_index(struct acpi_iort_node *node)
{
return -EINVAL;
}
+#endif
static struct acpi_iort_node *iort_node_map_id(struct acpi_iort_node *node,
u32 id_in, u32 *id_out,