linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: hanjun.guo@linaro.org (Hanjun Guo)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 3/4] ACPI: IORT: Skip SMMUv3 device ID map for two steps mappings
Date: Wed, 27 Sep 2017 09:20:14 +0800	[thread overview]
Message-ID: <1506475215-2731-4-git-send-email-hanjun.guo@linaro.org> (raw)
In-Reply-To: <1506475215-2731-1-git-send-email-hanjun.guo@linaro.org>

IORT revision C introduced SMMUv3 MSI support which adding a
device ID mapping index in SMMUv3 sub table, to get the SMMUv3
device ID mapping for the output ID (dev ID for ITS) and the
link to which ITS.

So if a platform supports SMMUv3 MSI for control interrupt,
there will be a additional single map entry under SMMU, this
will not introduce any difference for devices just use one
step map to get its output ID and parent (ITS or SMMU), such
as PCI/NC/PMCG ---> ITS or PCI/NC ---> SMMU, but we need to
do the special handling for two steps map case such as
PCI/NC--->SMMUv3--->ITS.

Take a PCI hostbridge for example,

|----------------------|
|  Root Complex Node   |
|----------------------|
|    map entry[x]      |
|----------------------|
|       id value       |
| output_reference     |
|---|------------------|
    |
    |   |----------------------|
    |-->|        SMMUv3        |
        |----------------------|
        |     SMMU dev ID      |
        |     mapping index 0  |
        |----------------------|
        |      map entry[0]    |
        |----------------------|
        |       id value       |
        | output_reference-----------> ITS 1 (SMMU MSI domain)
        |----------------------|
        |      map entry[1]    |
        |----------------------|
        |       id value       |
        | output_reference-----------> ITS 2 (PCI MSI domain)
        |----------------------|

When the SMMU dev ID mapping index is 0, there is entry[0]
to map to a ITS, we need to skip that map entry for PCI
or NC (named component), or we may get the wrong ITS parent.

Introduce iort_get_id_mapping_index() to get the index then
skip the map entry in iort_node_map_id(), also to get the
dev ID directly for iort_pmsi_get_dev_id() for ITS platform
MSI preparation.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/arm64/iort.c | 64 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 59 insertions(+), 5 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index db71d7f..1c1160e 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -357,7 +357,8 @@ 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;
 		}
@@ -366,6 +367,40 @@ struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
 	return NULL;
 }
 
+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 introdueced 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;
+	}
+}
+
 static struct acpi_iort_node *iort_node_map_id(struct acpi_iort_node *node,
 					       u32 id_in, u32 *id_out,
 					       u8 type_mask)
@@ -375,7 +410,7 @@ static struct acpi_iort_node *iort_node_map_id(struct acpi_iort_node *node,
 	/* Parse the ID mapping tree to find specified node type */
 	while (node) {
 		struct acpi_iort_id_mapping *map;
-		int i;
+		int i, index;
 
 		if (IORT_TYPE_MASK(node->type) & type_mask) {
 			if (id_out)
@@ -396,8 +431,19 @@ static struct acpi_iort_node *iort_node_map_id(struct acpi_iort_node *node,
 			goto fail_map;
 		}
 
+		/*
+		 * we need to get SMMUv3 dev ID mapping index and skip its
+		 * associated ID map for single mapping cases, error value
+		 * returned for index will be an invalid value in practical.
+		 */
+		index = iort_get_id_mapping_index(node);
+
 		/* Do the ID translation */
 		for (i = 0; i < node->mapping_count; i++, map++) {
+			/* if it's a SMMUv3 device id mapping index, skip it */
+			if (i == index)
+				continue;
+
 			if (!iort_id_map(map, node->type, id, &id))
 				break;
 		}
@@ -507,16 +553,24 @@ u32 iort_msi_map_rid(struct device *dev, u32 req_id)
  */
 int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
 {
-	int i;
+	int i, index;
 	struct acpi_iort_node *node;
 
 	node = iort_find_dev_node(dev);
 	if (!node)
 		return -ENODEV;
 
-	for (i = 0; i < node->mapping_count; i++) {
-		if (iort_node_map_platform_id(node, dev_id, IORT_MSI_TYPE, i))
+	index = iort_get_id_mapping_index(node);
+	/* if there is a valid index, go get the dev_id directly */
+	if (index >= 0) {
+		if (iort_node_get_id(node, dev_id, index))
 			return 0;
+	} else {
+		for (i = 0; i < node->mapping_count; i++) {
+			if (iort_node_map_platform_id(node, dev_id,
+						      IORT_MSI_TYPE, i))
+				return 0;
+		}
 	}
 
 	return -ENODEV;
-- 
1.9.1

  parent reply	other threads:[~2017-09-27  1:20 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-27  1:20 [PATCH 0/4] IORT SMMUv3 MSI support Hanjun Guo
2017-09-27  1:20 ` [PATCH 1/4] ACPICA: Add SMMUv3 device ID mapping index support Hanjun Guo
2017-09-27  1:20 ` [PATCH 2/4] ACPI: IORT: lookup iort node via fwnode Hanjun Guo
2017-09-27  1:20 ` Hanjun Guo [this message]
2017-09-27 13:54   ` [PATCH 3/4] ACPI: IORT: Skip SMMUv3 device ID map for two steps mappings Lorenzo Pieralisi
2017-10-10  6:47     ` Hanjun Guo
2017-10-10  9:20       ` Lorenzo Pieralisi
2017-10-11  5:26         ` Hanjun Guo
2017-10-11 10:24           ` Lorenzo Pieralisi
2017-10-12  7:30             ` Hanjun Guo
2017-10-12  9:50               ` Lorenzo Pieralisi
2017-09-27  1:20 ` [PATCH 4/4] ACPI: IORT: SMMUv3 nodes MSI support Hanjun Guo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1506475215-2731-4-git-send-email-hanjun.guo@linaro.org \
    --to=hanjun.guo@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).