]> xenbits.xensource.com Git - people/julieng/linux-arm.git/commitdiff
arm64, acpi: Implement new "GIC version" field of MADT GIC entry.
authorTomasz Nowicki <tomasz.nowicki@linaro.org>
Thu, 8 Jan 2015 11:36:33 +0000 (12:36 +0100)
committerJulien Grall <julien.grall@citrix.com>
Mon, 28 Sep 2015 11:05:19 +0000 (12:05 +0100)
There is no need to probe GICv2 and GICv3 sequentially. From now on,
we know GIC version in advance. Note this patch does not break backward
compatibility for machines which are compliant with ACPI spec. 5.1.

Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Vadim Lomovtsev <Vadim.Lomovtsev@caviumnetworks.com>
arch/arm64/include/asm/acpi.h
arch/arm64/kernel/acpi.c
include/acpi/actbl1.h

index 406485ed110af9fb12ce8040815355442d088444..a80f3afcf9e7bf0175a70e6d78309766c128c105 100644 (file)
@@ -47,6 +47,7 @@ typedef u64 phys_cpuid_t;
 extern int acpi_disabled;
 extern int acpi_noirq;
 extern int acpi_pci_disabled;
+extern int acpi_gic_ver;
 
 static inline void disable_acpi(void)
 {
@@ -85,6 +86,7 @@ static inline void arch_fix_phys_package_id(int num, u32 slot) { }
 void __init acpi_init_cpus(void);
 
 #else
+#define acpi_gic_ver   0
 static inline void acpi_init_cpus(void) { }
 #endif /* CONFIG_ACPI */
 
index 19de7537e7d32f407f3f75d5f295ab5f3c7c4291..26928c48f8030056d5467a823add694753d02611 100644 (file)
@@ -36,6 +36,8 @@ EXPORT_SYMBOL(acpi_disabled);
 int acpi_pci_disabled = 1;     /* skip ACPI PCI scan and IRQ initialization */
 EXPORT_SYMBOL(acpi_pci_disabled);
 
+int acpi_gic_ver;
+
 static bool param_acpi_off __initdata;
 static bool param_acpi_force __initdata;
 
@@ -206,12 +208,27 @@ void __init acpi_boot_table_init(void)
        }
 }
 
+static int __init
+gic_acpi_find_ver(struct acpi_subtable_header *header,
+                               const unsigned long end)
+{
+       struct acpi_madt_generic_distributor *dist;
+
+       dist = (struct acpi_madt_generic_distributor *)header;
+
+       if (BAD_MADT_ENTRY(dist, end))
+               return -EINVAL;
+
+       acpi_gic_ver = dist->gic_version;
+       return 0;
+}
+
 void __init acpi_gic_init(void)
 {
        struct acpi_table_header *table;
        acpi_status status;
        acpi_size tbl_size;
-       int err;
+       int err, count;;
 
        if (acpi_disabled)
                return;
@@ -224,7 +241,17 @@ void __init acpi_gic_init(void)
                return;
        }
 
-       err = gic_v2_acpi_init(table);
+       count = acpi_parse_entries(ACPI_SIG_MADT,
+                                  sizeof(struct acpi_table_madt),
+                                  gic_acpi_find_ver, table,
+                                  ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
+       if (count <= 0) {
+               pr_info("Error during GICD entries parsing, assuming GICv2\n");
+               acpi_gic_ver = ACPI_MADT_GIC_VER_V2;
+       }
+
+       err = acpi_gic_ver < ACPI_MADT_GIC_VER_V3 ?
+                       gic_v2_acpi_init(table) : -ENXIO;
        if (err)
                pr_err("Failed to initialize GIC IRQ controller");
 
index fcd570999f354247c9dbba73163797ff38cbd1a6..606f6578a717e924d89291e76853c80e2e6aae58 100644 (file)
@@ -823,6 +823,16 @@ struct acpi_madt_generic_interrupt {
 #define ACPI_MADT_PERFORMANCE_IRQ_MODE  (1<<1) /* 01: Performance Interrupt Mode */
 #define ACPI_MADT_VGIC_IRQ_MODE         (1<<2) /* 02: VGIC Maintenance Interrupt mode */
 
+enum acpi_madt_gic_ver_type
+{
+    ACPI_MADT_GIC_VER_UNKNOWN       = 0,
+    ACPI_MADT_GIC_VER_V2            = 1,
+    ACPI_MADT_GIC_VER_V2m           = 2,
+    ACPI_MADT_GIC_VER_V3            = 3,
+    ACPI_MADT_GIC_VER_V4            = 4,
+    ACPI_MADT_GIC_VER_RESERVED      = 5     /* 15 and greater are reserved */
+};
+
 /* 12: Generic Distributor (ACPI 5.0 + ACPI 6.0 changes) */
 
 struct acpi_madt_generic_distributor {
@@ -831,7 +841,7 @@ struct acpi_madt_generic_distributor {
        u32 gic_id;
        u64 base_address;
        u32 global_irq_base;
-       u8 version;
+       u8 gic_version;
        u8 reserved2[3];        /* reserved - must be zero */
 };