]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
UBUNTU: SAUCE: ACPI: platform: setup MSI domain for ACPI based platform device
authorHanjun Guo <hanjun.guo@linaro.org>
Wed, 18 Jan 2017 12:55:01 +0000 (20:55 +0800)
committerTim Gardner <tim.gardner@canonical.com>
Thu, 2 Mar 2017 12:38:22 +0000 (05:38 -0700)
With the platform msi domain created, we can set up the msi domain
for a platform device when it's probed.

In order to do that, we need to get the domain that the platform
device connecting to, so the iort_get_platform_device_domain() is
introduced to retrieve the domain from iort.

After the domain is retrieved, we need a proper way to set the
domain to paltform device, as some platform devices such as an
irqchip needs the msi irqdomain to be the interrupt parent domain,
we need to get irqdomain before platform device is probed but after
the platform device is allocated (the time slot of setting the
msi domain also works for other cases). So simply call
acpi_configure_pmsi_domain() in acpi_platform_notify() for
platform devices will work.

Acked-by: Rafael J. Wysocki <rafael@kernel.org> [for glue.c]
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
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>
[v8 submission from:
 https://www.spinics.net/lists/arm-kernel/msg555559.html ]
BugLink: http://bugs.launchpad.net/bugs/1669061
Signed-off-by: dann frazier <dann.frazier@canonical.com>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
drivers/acpi/arm64/iort.c
drivers/acpi/glue.c
include/linux/acpi_iort.h

index 9aebb14c23a1b67cd6915f767c5bf921b6989b42..95d64a327db071ac0b1a60db287e75024b717211 100644 (file)
@@ -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;
index fb19e1cdb6415ac8d1913e7017106911dcb7a7dd..ec31b439b4c8849310ea40a8b342432945021cf0 100644 (file)
@@ -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)
index d074c778618a2e4b8477547b18082fa7051b55b9..06b182e57ab98d6fc58196a350c9bfdf10ff179f 100644 (file)
@@ -34,6 +34,7 @@ void acpi_iort_init(void);
 bool iort_node_match(u8 type);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+void acpi_configure_pmsi_domain(struct device *dev);
 int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 /* IOMMU interface */
 void iort_set_dma_mask(struct device *dev);
@@ -47,6 +48,8 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev,
                                                        u32 req_id)
 { return NULL; }
 
+static inline void acpi_configure_pmsi_domain(struct device *dev) { }
+
 static inline int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
 { return -ENODEV; }