Message ID | 1436525114-14425-3-git-send-email-hanjun.guo@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote: > +void __init acpi_irqchip_init(void) > +{ > + struct acpi_table_id *id; > + > + if (acpi_disabled) > + return; > + > + if (acpi_gic_version_init()) > + return; > + > + /* scan the irqchip table to match the GIC version and its driver */ > + for (id = __irqchip_acpi_table; id->id[0]; id++) { > + if (gic_version == (u8)id->driver_data) > + acpi_table_parse(id->id, > + (acpi_tbl_table_handler)id->handler); > + } Should we display an error message if we don't find a matching table? That can happen if the ACPI tables shows a GIC version number that is not listed in __irqchip_acpi_table[]?
On 07/18/2015 07:15 AM, Timur Tabi wrote: > On Fri, Jul 10, 2015 at 5:45 AM, Hanjun Guo <hanjun.guo@linaro.org> wrote: > >> +void __init acpi_irqchip_init(void) >> +{ >> + struct acpi_table_id *id; >> + >> + if (acpi_disabled) >> + return; >> + >> + if (acpi_gic_version_init()) >> + return; >> + >> + /* scan the irqchip table to match the GIC version and its driver */ >> + for (id = __irqchip_acpi_table; id->id[0]; id++) { >> + if (gic_version == (u8)id->driver_data) >> + acpi_table_parse(id->id, >> + (acpi_tbl_table_handler)id->handler); >> + } > > Should we display an error message if we don't find a matching table? > That can happen if the ACPI tables shows a GIC version number that is > not listed in __irqchip_acpi_table[]? Hmm, did you get the error message like: "Invalid GIC version 5 in MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if the later one, it will show everything is fine, but failed to probe the GIC. I agree with you that we need to print some error message here, I will update my patch. Thanks Hanjun
Hanjun Guo wrote: >> Should we display an error message if we don't find a matching table? >> That can happen if the ACPI tables shows a GIC version number that is >> not listed in __irqchip_acpi_table[]? > > Hmm, did you get the error message like: "Invalid GIC version 5 in > MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if > the later one, it will show everything is fine, but failed to probe > the GIC. We had a bug in our ACPI tables that listed the GIC version as 1, and it failed to probe and then the kernel panicked. It took me a while to figure out what was wrong, so I think it should print an error message that says that version X is unsupported.
On 07/20/2015 08:12 PM, Timur Tabi wrote: > Hanjun Guo wrote: >>> Should we display an error message if we don't find a matching table? >>> That can happen if the ACPI tables shows a GIC version number that is >>> not listed in __irqchip_acpi_table[]? >> >> Hmm, did you get the error message like: "Invalid GIC version 5 in >> MADT"? or just use ACPI_MADT_GIC_VERSION_V1 as the gic_version? if >> the later one, it will show everything is fine, but failed to probe >> the GIC. > > We had a bug in our ACPI tables that listed the GIC version as 1, and it > failed to probe and then the kernel panicked. It took me a while to > figure out what was wrong, so I think it should print an error message > that says that version X is unsupported. OK, will do in next version, thanks for testing those patches! Hanjun
diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c index 6537b43..e003a89 100644 --- a/drivers/irqchip/irq-gic-acpi.c +++ b/drivers/irqchip/irq-gic-acpi.c @@ -107,3 +107,32 @@ static int __init acpi_gic_version_init(void) return 0; } + +/* + * This special acpi_table_id is the sentinel at the end of the + * acpi_table_id[] array of all irqchips. It is automatically placed at + * the end of the array by the linker, thanks to being part of a + * special section. + */ +static const struct acpi_table_id +irqchip_acpi_match_end __used __section(__irqchip_acpi_table_end); + +extern struct acpi_table_id __irqchip_acpi_table[]; + +void __init acpi_irqchip_init(void) +{ + struct acpi_table_id *id; + + if (acpi_disabled) + return; + + if (acpi_gic_version_init()) + return; + + /* scan the irqchip table to match the GIC version and its driver */ + for (id = __irqchip_acpi_table; id->id[0]; id++) { + if (gic_version == (u8)id->driver_data) + acpi_table_parse(id->id, + (acpi_tbl_table_handler)id->handler); + } +} diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 8bd374d..625776c 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -181,6 +181,18 @@ #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method) #define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon) +#ifdef CONFIG_ACPI +#define ACPI_TABLE(name) \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__##name##_acpi_table) = .; \ + *(__##name##_acpi_table) \ + *(__##name##_acpi_table_end) + +#define IRQCHIP_ACPI_MATCH_TABLE() ACPI_TABLE(irqchip) +#else +#define IRQCHIP_ACPI_MATCH_TABLE() +#endif + #define KERNEL_DTB() \ STRUCT_ALIGN(); \ VMLINUX_SYMBOL(__dtb_start) = .; \ @@ -516,6 +528,7 @@ CPUIDLE_METHOD_OF_TABLES() \ KERNEL_DTB() \ IRQCHIP_OF_MATCH_TABLE() \ + IRQCHIP_ACPI_MATCH_TABLE() \ EARLYCON_TABLE() \ EARLYCON_OF_TABLES() diff --git a/include/linux/acpi.h b/include/linux/acpi.h index c471dfc..7b058f0 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -811,4 +811,20 @@ static inline struct acpi_device *acpi_get_next_child(struct device *dev, #endif +#ifdef CONFIG_ACPI +#define ACPI_DECLARE(table, name, table_id, data, fn) \ + static const struct acpi_table_id __acpi_table_##name \ + __used __section(__##table##_acpi_table) \ + = { .id = table_id, \ + .handler = (void *)fn, \ + .driver_data = data } +#else +#define ACPI_DECLARE(table, name, table_id, data, fn) \ + static const struct acpi_table_id __acpi_table_##name \ + __attribute__((unused)) \ + = { .id = table_id, \ + .handler = (void *)fn, \ + .driver_data = data } +#endif + #endif /*_LINUX_ACPI_H*/ diff --git a/include/linux/irqchip.h b/include/linux/irqchip.h index 6388873..6b66d3e 100644 --- a/include/linux/irqchip.h +++ b/include/linux/irqchip.h @@ -11,6 +11,7 @@ #ifndef _LINUX_IRQCHIP_H #define _LINUX_IRQCHIP_H +#include <linux/acpi.h> #include <linux/of.h> /* @@ -25,6 +26,18 @@ */ #define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn) +/* + * This macro must be used by the different ARM GIC drivers to declare + * the association between their version and their initialization function. + * + * @name: name that must be unique accross all IRQCHIP_ACPI_DECLARE of the + * same file. + * @gic_version: version of GIC + * @fn: initialization function + */ +#define IRQCHIP_ACPI_DECLARE(name, gic_version, fn) \ + ACPI_DECLARE(irqchip, name, ACPI_SIG_MADT, gic_version, fn) + #ifdef CONFIG_IRQCHIP void irqchip_init(void); #else diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 8183d66..c74855f 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -191,6 +191,14 @@ struct acpi_device_id { kernel_ulong_t driver_data; }; +#define ACPI_TABLE_ID_LEN 5 + +struct acpi_table_id { + __u8 id[ACPI_TABLE_ID_LEN]; + const void *handler; + kernel_ulong_t driver_data; +}; + #define PNP_ID_LEN 8 #define PNP_MAX_DEVICES 8