summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorHanjun Guo <hanjun.guo@linaro.org>2017-03-07 13:40:06 +0100
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2017-03-30 11:20:01 +0200
commitd4f54a186667ffd19eac8e3f48c51d940a9b9784 (patch)
tree7a657d47ea2179269dd97bdebb03ec62e92b0a47 /drivers/acpi
parentACPI: platform-msi: retrieve devid from IORT (diff)
downloadlinux-d4f54a186667ffd19eac8e3f48c51d940a9b9784.tar.xz
linux-d4f54a186667ffd19eac8e3f48c51d940a9b9784.zip
ACPI: platform: setup MSI domain for ACPI based platform device
By allowing platform MSI domain to be created on ACPI platforms, a platform device MSI domain can be set-up when it is probed. In order to do that, the MSI domain the platform device connects to should be retrieved, so the iort_get_platform_device_domain() is introduced to retrieve the domain from the IORT kernel layer. With the domain retrieved, we need a proper way to set the domain to platform device. Given that some platform devices (irqchips) require the MSI irqdomain to be their interrupt parent domain, the MSI irqdomain should be determined before platform device is probed but after the platform device is allocated which means that the code setting up the MSI irqdomain, ie acpi_configure_pmsi_domain() should be called in acpi_platform_notify() (that is triggered after adding a device but before the respective driver is probed) for the platform MSI domain code set-up path to work properly. Acked-by: Rafael J. Wysocki <rafael@kernel.org> [for glue.c] Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> [lorenzo.pieralisi@arm.com: rewrote commit log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Tested-by: Ming Lei <ming.lei@canonical.com> Tested-by: Wei Xu <xuwei5@hisilicon.com> Tested-by: Sinan Kaya <okaya@codeaurora.org> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Cc: Tomasz Nowicki <tn@semihalf.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/arm64/iort.c50
-rw-r--r--drivers/acpi/glue.c6
2 files changed, 56 insertions, 0 deletions
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index fb95ceb3840d..22e08d272db7 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -548,6 +548,56 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
}
+/**
+ * iort_get_platform_device_domain() - Find MSI domain related to a
+ * platform device
+ * @dev: the dev pointer associated with the platform device
+ *
+ * Returns: the MSI domain for this device, NULL otherwise
+ */
+static struct irq_domain *iort_get_platform_device_domain(struct device *dev)
+{
+ struct acpi_iort_node *node, *msi_parent;
+ struct fwnode_handle *iort_fwnode;
+ struct acpi_iort_its_group *its;
+ int i;
+
+ /* find its associated iort node */
+ node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
+ iort_match_node_callback, dev);
+ if (!node)
+ return NULL;
+
+ /* then find its msi parent node */
+ for (i = 0; i < node->mapping_count; i++) {
+ msi_parent = iort_node_map_platform_id(node, NULL,
+ IORT_MSI_TYPE, i);
+ if (msi_parent)
+ break;
+ }
+
+ if (!msi_parent)
+ return NULL;
+
+ /* 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 NULL;
+
+ return irq_find_matching_fwnode(iort_fwnode, DOMAIN_BUS_PLATFORM_MSI);
+}
+
+void acpi_configure_pmsi_domain(struct device *dev)
+{
+ struct irq_domain *msi_domain;
+
+ msi_domain = iort_get_platform_device_domain(dev);
+ if (msi_domain)
+ dev_set_msi_domain(dev, msi_domain);
+}
+
static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
{
u32 *rid = data;
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index fb19e1cdb641..ec31b439b4c8 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -6,6 +6,8 @@
*
* This file is released under the GPLv2.
*/
+
+#include <linux/acpi_iort.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/list.h>
@@ -14,6 +16,7 @@
#include <linux/rwsem.h>
#include <linux/acpi.h>
#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
#include "internal.h"
@@ -322,6 +325,9 @@ static int acpi_platform_notify(struct device *dev)
if (!adev)
goto out;
+ if (dev->bus == &platform_bus_type)
+ acpi_configure_pmsi_domain(dev);
+
if (type && type->setup)
type->setup(dev);
else if (adev->handler && adev->handler->bind)