Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

irqchip / GIC: Convert the GIC driver to ACPI probing

Now that we have a basic infrastructure to register irqchips and
call them on discovery of a matching entry in MADT, convert the
GIC driver to this new probing method.

It ends up being a code deletion party, which is a rather good thing.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Marc Zyngier and committed by
Rafael J. Wysocki
f26527b1 46e589a3

+37 -98
-1
arch/arm64/include/asm/acpi.h
··· 12 12 #ifndef _ASM_ACPI_H 13 13 #define _ASM_ACPI_H 14 14 15 - #include <linux/irqchip/arm-gic-acpi.h> 16 15 #include <linux/mm.h> 17 16 #include <linux/psci.h> 18 17
-2
arch/arm64/include/asm/irq.h
··· 1 1 #ifndef __ASM_IRQ_H 2 2 #define __ASM_IRQ_H 3 3 4 - #include <linux/irqchip/arm-gic-acpi.h> 5 - 6 4 #include <asm-generic/irq.h> 7 5 8 6 struct pt_regs;
-25
arch/arm64/kernel/acpi.c
··· 205 205 disable_acpi(); 206 206 } 207 207 } 208 - 209 - void __init acpi_gic_init(void) 210 - { 211 - struct acpi_table_header *table; 212 - acpi_status status; 213 - acpi_size tbl_size; 214 - int err; 215 - 216 - if (acpi_disabled) 217 - return; 218 - 219 - status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size); 220 - if (ACPI_FAILURE(status)) { 221 - const char *msg = acpi_format_exception(status); 222 - 223 - pr_err("Failed to get MADT table, %s\n", msg); 224 - return; 225 - } 226 - 227 - err = gic_v2_acpi_init(table); 228 - if (err) 229 - pr_err("Failed to initialize GIC IRQ controller"); 230 - 231 - early_acpi_os_unmap_memory((char *)table, tbl_size); 232 - }
+37 -36
drivers/irqchip/irq-gic.c
··· 41 41 #include <linux/irqchip.h> 42 42 #include <linux/irqchip/chained_irq.h> 43 43 #include <linux/irqchip/arm-gic.h> 44 - #include <linux/irqchip/arm-gic-acpi.h> 45 44 46 45 #include <asm/cputype.h> 47 46 #include <asm/irq.h> ··· 1194 1195 #endif 1195 1196 1196 1197 #ifdef CONFIG_ACPI 1197 - static phys_addr_t dist_phy_base, cpu_phy_base __initdata; 1198 + static phys_addr_t cpu_phy_base __initdata; 1198 1199 1199 1200 static int __init 1200 1201 gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, ··· 1222 1223 return 0; 1223 1224 } 1224 1225 1225 - static int __init 1226 - gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header, 1227 - const unsigned long end) 1226 + /* The things you have to do to just *count* something... */ 1227 + static int __init acpi_dummy_func(struct acpi_subtable_header *header, 1228 + const unsigned long end) 1228 1229 { 1229 - struct acpi_madt_generic_distributor *dist; 1230 - 1231 - dist = (struct acpi_madt_generic_distributor *)header; 1232 - 1233 - if (BAD_MADT_ENTRY(dist, end)) 1234 - return -EINVAL; 1235 - 1236 - dist_phy_base = dist->base_address; 1237 1230 return 0; 1238 1231 } 1239 1232 1240 - int __init 1241 - gic_v2_acpi_init(struct acpi_table_header *table) 1233 + static bool __init acpi_gic_redist_is_present(void) 1242 1234 { 1235 + return acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, 1236 + acpi_dummy_func, 0) > 0; 1237 + } 1238 + 1239 + static bool __init gic_validate_dist(struct acpi_subtable_header *header, 1240 + struct acpi_probe_entry *ape) 1241 + { 1242 + struct acpi_madt_generic_distributor *dist; 1243 + dist = (struct acpi_madt_generic_distributor *)header; 1244 + 1245 + return (dist->version == ape->driver_data && 1246 + (dist->version != ACPI_MADT_GIC_VERSION_NONE || 1247 + !acpi_gic_redist_is_present())); 1248 + } 1249 + 1250 + #define ACPI_GICV2_DIST_MEM_SIZE (SZ_4K) 1251 + #define ACPI_GIC_CPU_IF_MEM_SIZE (SZ_8K) 1252 + 1253 + static int __init gic_v2_acpi_init(struct acpi_subtable_header *header, 1254 + const unsigned long end) 1255 + { 1256 + struct acpi_madt_generic_distributor *dist; 1243 1257 void __iomem *cpu_base, *dist_base; 1244 1258 int count; 1245 1259 1246 1260 /* Collect CPU base addresses */ 1247 - count = acpi_parse_entries(ACPI_SIG_MADT, 1248 - sizeof(struct acpi_table_madt), 1249 - gic_acpi_parse_madt_cpu, table, 1250 - ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0); 1261 + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, 1262 + gic_acpi_parse_madt_cpu, 0); 1251 1263 if (count <= 0) { 1252 1264 pr_err("No valid GICC entries exist\n"); 1253 - return -EINVAL; 1254 - } 1255 - 1256 - /* 1257 - * Find distributor base address. We expect one distributor entry since 1258 - * ACPI 5.1 spec neither support multi-GIC instances nor GIC cascade. 1259 - */ 1260 - count = acpi_parse_entries(ACPI_SIG_MADT, 1261 - sizeof(struct acpi_table_madt), 1262 - gic_acpi_parse_madt_distributor, table, 1263 - ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0); 1264 - if (count <= 0) { 1265 - pr_err("No valid GICD entries exist\n"); 1266 - return -EINVAL; 1267 - } else if (count > 1) { 1268 - pr_err("More than one GICD entry detected\n"); 1269 1265 return -EINVAL; 1270 1266 } 1271 1267 ··· 1270 1276 return -ENOMEM; 1271 1277 } 1272 1278 1273 - dist_base = ioremap(dist_phy_base, ACPI_GICV2_DIST_MEM_SIZE); 1279 + dist = (struct acpi_madt_generic_distributor *)header; 1280 + dist_base = ioremap(dist->base_address, ACPI_GICV2_DIST_MEM_SIZE); 1274 1281 if (!dist_base) { 1275 1282 pr_err("Unable to map GICD registers\n"); 1276 1283 iounmap(cpu_base); ··· 1297 1302 acpi_irq_model = ACPI_IRQ_MODEL_GIC; 1298 1303 return 0; 1299 1304 } 1305 + IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 1306 + gic_validate_dist, ACPI_MADT_GIC_VERSION_V2, 1307 + gic_v2_acpi_init); 1308 + IRQCHIP_ACPI_DECLARE(gic_v2_maybe, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 1309 + gic_validate_dist, ACPI_MADT_GIC_VERSION_NONE, 1310 + gic_v2_acpi_init); 1300 1311 #endif
-3
drivers/irqchip/irqchip.c
··· 27 27 void __init irqchip_init(void) 28 28 { 29 29 of_irq_init(__irqchip_of_table); 30 - #if defined(CONFIG_ARM64) && defined(CONFIG_ACPI) 31 - acpi_gic_init(); /* Temporary hack */ 32 - #endif 33 30 acpi_probe_device_table(irqchip); 34 31 }
-31
include/linux/irqchip/arm-gic-acpi.h
··· 1 - /* 2 - * Copyright (C) 2014, Linaro Ltd. 3 - * Author: Tomasz Nowicki <tomasz.nowicki@linaro.org> 4 - * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License version 2 as 7 - * published by the Free Software Foundation. 8 - */ 9 - 10 - #ifndef ARM_GIC_ACPI_H_ 11 - #define ARM_GIC_ACPI_H_ 12 - 13 - #ifdef CONFIG_ACPI 14 - 15 - /* 16 - * Hard code here, we can not get memory size from MADT (but FDT does), 17 - * Actually no need to do that, because this size can be inferred 18 - * from GIC spec. 19 - */ 20 - #define ACPI_GICV2_DIST_MEM_SIZE (SZ_4K) 21 - #define ACPI_GIC_CPU_IF_MEM_SIZE (SZ_8K) 22 - 23 - struct acpi_table_header; 24 - 25 - int gic_v2_acpi_init(struct acpi_table_header *table); 26 - void acpi_gic_init(void); 27 - #else 28 - static inline void acpi_gic_init(void) { } 29 - #endif 30 - 31 - #endif /* ARM_GIC_ACPI_H_ */