Commit 65637901 authored by Lorenzo Pieralisi's avatar Lorenzo Pieralisi

ACPI/IORT: Enable SMMUv3/PMCG IORT MSI domain set-up

ITS specific mappings for SMMUv3/PMCG components can be retrieved
through special index mapping entries introduced in IORT revision C.

Introduce a new API iort_set_device_domain() to set the MSI domain for
SMMUv3/PMCG nodes (extendable to any future IORT node requiring special
index ITS mapping entries) that represent MSI through special index
mappings in order to enable MSI support for the devices their nodes
represent.
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: default avatarHanjun Guo <hanjun.guo@linaro.org>
parent 86456a3f
...@@ -638,6 +638,49 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id) ...@@ -638,6 +638,49 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI); return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
} }
static void iort_set_device_domain(struct device *dev,
struct acpi_iort_node *node)
{
struct acpi_iort_its_group *its;
struct acpi_iort_node *msi_parent;
struct acpi_iort_id_mapping *map;
struct fwnode_handle *iort_fwnode;
struct irq_domain *domain;
int index;
index = iort_get_id_mapping_index(node);
if (index < 0)
return;
map = ACPI_ADD_PTR(struct acpi_iort_id_mapping, node,
node->mapping_offset + index * sizeof(*map));
/* Firmware bug! */
if (!map->output_reference ||
!(map->flags & ACPI_IORT_ID_SINGLE_MAPPING)) {
pr_err(FW_BUG "[node %p type %d] Invalid MSI mapping\n",
node, node->type);
return;
}
msi_parent = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
map->output_reference);
if (!msi_parent || msi_parent->type != ACPI_IORT_NODE_ITS_GROUP)
return;
/* Move to ITS specific data */
its = (struct acpi_iort_its_group *)msi_parent->node_data;
iort_fwnode = iort_find_domain_token(its->identifiers[0]);
if (!iort_fwnode)
return;
domain = irq_find_matching_fwnode(iort_fwnode, DOMAIN_BUS_PLATFORM_MSI);
if (domain)
dev_set_msi_domain(dev, domain);
}
/** /**
* iort_get_platform_device_domain() - Find MSI domain related to a * iort_get_platform_device_domain() - Find MSI domain related to a
* platform device * platform device
...@@ -1261,6 +1304,8 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node, ...@@ -1261,6 +1304,8 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
/* Configure DMA for the page table walker */ /* Configure DMA for the page table walker */
acpi_dma_configure(&pdev->dev, attr); acpi_dma_configure(&pdev->dev, attr);
iort_set_device_domain(&pdev->dev, node);
ret = platform_device_add(pdev); ret = platform_device_add(pdev);
if (ret) if (ret)
goto dma_deconfigure; goto dma_deconfigure;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment