aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Nowicki <tn@semihalf.com>2016-09-12 14:32:25 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2016-09-12 15:32:42 -0400
commit3f010cf197324b6c1e87f472e64b87c5f909735e (patch)
tree83aedbd4e6ae60a8477ea75ff792deecec60de3a
parentdb40f0a7aea5e03ef044ef5dbc51a364e1ff7991 (diff)
irqchip/gicv3-its: Probe ITS in the ACPI way
ITS is prepared for being initialized different than DT, therefore we can initialize it in ACPI way. We collect register base address from MADT table and pass mandatory info to firmware-agnostic ITS init call. Use here IORT lib to register ITS domain which then can be found and used on to build another PCI MSI domain in hierarchical stack domain. NOTE: Waiting for proper ITS and NUMA node relation description in IORT table, we pass around NUMA_NO_NODE to the its_probe_one init call. This means that Cavium ThunderX erratum 23144 (pass1.1 only) is not supported for ACPI boot method yet. Signed-off-by: Tomasz Nowicki <tn@semihalf.com> Acked-by: Marc Zyngier <marc.zyngier@arm.com> Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--drivers/irqchip/Kconfig1
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c61
2 files changed, 61 insertions, 1 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 7f8728984f44..9aeea1d8a579 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -39,6 +39,7 @@ config ARM_GIC_V3_ITS
39 bool 39 bool
40 depends on PCI 40 depends on PCI
41 depends on PCI_MSI 41 depends on PCI_MSI
42 select ACPI_IORT if ACPI
42 43
43config ARM_NVIC 44config ARM_NVIC
44 bool 45 bool
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index c7518c7b48bc..35c851c14e49 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -15,10 +15,13 @@
15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18#include <linux/acpi.h>
18#include <linux/bitmap.h> 19#include <linux/bitmap.h>
19#include <linux/cpu.h> 20#include <linux/cpu.h>
20#include <linux/delay.h> 21#include <linux/delay.h>
21#include <linux/interrupt.h> 22#include <linux/interrupt.h>
23#include <linux/irqdomain.h>
24#include <linux/acpi_iort.h>
22#include <linux/log2.h> 25#include <linux/log2.h>
23#include <linux/mm.h> 26#include <linux/mm.h>
24#include <linux/msi.h> 27#include <linux/msi.h>
@@ -1438,6 +1441,11 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
1438 fwspec.param[0] = GIC_IRQ_TYPE_LPI; 1441 fwspec.param[0] = GIC_IRQ_TYPE_LPI;
1439 fwspec.param[1] = hwirq; 1442 fwspec.param[1] = hwirq;
1440 fwspec.param[2] = IRQ_TYPE_EDGE_RISING; 1443 fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
1444 } else if (is_fwnode_irqchip(domain->parent->fwnode)) {
1445 fwspec.fwnode = domain->parent->fwnode;
1446 fwspec.param_count = 2;
1447 fwspec.param[0] = hwirq;
1448 fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
1441 } else { 1449 } else {
1442 return -EINVAL; 1450 return -EINVAL;
1443 } 1451 }
@@ -1797,6 +1805,57 @@ static int __init its_of_probe(struct device_node *node)
1797 return 0; 1805 return 0;
1798} 1806}
1799 1807
1808#ifdef CONFIG_ACPI
1809
1810#define ACPI_GICV3_ITS_MEM_SIZE (SZ_128K)
1811
1812static int __init gic_acpi_parse_madt_its(struct acpi_subtable_header *header,
1813 const unsigned long end)
1814{
1815 struct acpi_madt_generic_translator *its_entry;
1816 struct fwnode_handle *dom_handle;
1817 struct resource res;
1818 int err;
1819
1820 its_entry = (struct acpi_madt_generic_translator *)header;
1821 memset(&res, 0, sizeof(res));
1822 res.start = its_entry->base_address;
1823 res.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1;
1824 res.flags = IORESOURCE_MEM;
1825
1826 dom_handle = irq_domain_alloc_fwnode((void *)its_entry->base_address);
1827 if (!dom_handle) {
1828 pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n",
1829 &res.start);
1830 return -ENOMEM;
1831 }
1832
1833 err = iort_register_domain_token(its_entry->translation_id, dom_handle);
1834 if (err) {
1835 pr_err("ITS@%pa: Unable to register GICv3 ITS domain token (ITS ID %d) to IORT\n",
1836 &res.start, its_entry->translation_id);
1837 goto dom_err;
1838 }
1839
1840 err = its_probe_one(&res, dom_handle, NUMA_NO_NODE);
1841 if (!err)
1842 return 0;
1843
1844 iort_deregister_domain_token(its_entry->translation_id);
1845dom_err:
1846 irq_domain_free_fwnode(dom_handle);
1847 return err;
1848}
1849
1850static void __init its_acpi_probe(void)
1851{
1852 acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
1853 gic_acpi_parse_madt_its, 0);
1854}
1855#else
1856static void __init its_acpi_probe(void) { }
1857#endif
1858
1800int __init its_init(struct fwnode_handle *handle, struct rdists *rdists, 1859int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
1801 struct irq_domain *parent_domain) 1860 struct irq_domain *parent_domain)
1802{ 1861{
@@ -1807,7 +1866,7 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
1807 if (of_node) 1866 if (of_node)
1808 its_of_probe(of_node); 1867 its_of_probe(of_node);
1809 else 1868 else
1810 return -ENODEV; 1869 its_acpi_probe();
1811 1870
1812 if (list_empty(&its_nodes)) { 1871 if (list_empty(&its_nodes)) {
1813 pr_warn("ITS: No ITS available, not enabling LPIs\n"); 1872 pr_warn("ITS: No ITS available, not enabling LPIs\n");