From: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx> A bugzilla entry (http://bugzilla.kernel.org/show_bug.cgi?id=11580) reports that some PNPACPI tables don't list RTC devices; they are instead glommed into a generic "system resources" entry. Address that on x86 (while ignoring ia64, the other user of ACPI) by having ACPI glue check for that case, and if necessary then setting up a platform device and having rtc_cmos use it. Seems like a candidate for 2.6.27-final and for backporting. There's a Fedora kernel report for this too. Workaround is simple (see the bug report) but less functional. [akpm@xxxxxxxxxxxxxxxxxxxx: forward-declare struct device] Signed-off-by: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx> Reported-by: Rik Theys <rik.theys@xxxxxxxxxxxxxxxx> Cc: Adam Belay <abelay@xxxxxxxxxx> Cc: Chuck Ebbert <cebbert@xxxxxxxxxx> Cc: Len Brown <lenb@xxxxxxxxxx> Cc: Bjorn Helgaas <bjorn.helgaas@xxxxxx> Cc: Ingo Molnar <mingo@xxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Acked-by: Alessandro Zummo <a.zummo@xxxxxxxxxxxx> Cc: <stable@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- arch/x86/kernel/rtc.c | 13 ++++++++++++- drivers/acpi/glue.c | 16 +++++++++++++++- drivers/pnp/core.c | 8 ++++++++ drivers/rtc/rtc-cmos.c | 4 ++-- include/asm-x86/mc146818rtc.h | 7 +++++++ include/linux/pnp.h | 1 + 6 files changed, 45 insertions(+), 4 deletions(-) diff -puN arch/x86/kernel/rtc.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry arch/x86/kernel/rtc.c --- a/arch/x86/kernel/rtc.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +++ a/arch/x86/kernel/rtc.c @@ -220,11 +220,22 @@ static struct platform_device rtc_device .num_resources = ARRAY_SIZE(rtc_resources), }; +#ifdef CONFIG_PNP +/* PNPACPI tables sometimes omit the RTC, or are ignored */ +struct device *__init add_nonpnp_rtc_cmos(void) +{ + if (!rtc_device.dev.bus) + platform_device_register(&rtc_device); + return &rtc_device.dev; +} +#endif + static __init int add_rtc_cmos(void) { #ifdef CONFIG_PNP + /* in case of pnpacpi=off */ if (!pnp_platform_devices) - platform_device_register(&rtc_device); + add_nonpnp_rtc_cmos(); #else platform_device_register(&rtc_device); #endif /* CONFIG_PNP */ diff -puN drivers/acpi/glue.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry drivers/acpi/glue.c --- a/drivers/acpi/glue.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +++ a/drivers/acpi/glue.c @@ -366,7 +366,21 @@ static int __init pnp_match(struct devic static struct device *__init get_rtc_dev(void) { - return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match); + struct device *rtc; + + /* return RTC from PNPACPI tables */ + rtc = bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match); + +#ifdef ARCH_PNP_RTC_WORKAROUND + /* cope with buggy PNPACPI tables (like the HP DL3x0 servers + * which have no RTC device listed), and with pnpacpi=off + */ + if (!rtc) { + pnp_rtc_missing = true; + rtc = add_nonpnp_rtc_cmos(); + } +#endif + return rtc; } static int __init acpi_rtc_init(void) diff -puN drivers/pnp/core.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry drivers/pnp/core.c --- a/drivers/pnp/core.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +++ a/drivers/pnp/core.c @@ -25,10 +25,18 @@ DEFINE_SPINLOCK(pnp_lock); * ACPI or PNPBIOS should tell us about all platform devices, so we can * skip some blind probes. ISAPNP typically enumerates only plug-in ISA * devices, not built-in things like COM ports. + * + * Sometimes ACPI tables omit devices like RTCs, which can be critical. + * To avoid legacy poke-the-hardware-and-guess drivers (unfriendly to + * the driver model), something else creates a (platform) device node; + * and drivers must know to kick-in their non-PNP (non-PC) bus glue. */ int pnp_platform_devices; EXPORT_SYMBOL(pnp_platform_devices); +bool pnp_rtc_missing; +EXPORT_SYMBOL(pnp_rtc_missing); + void *pnp_alloc(long size) { void *result; diff -puN drivers/rtc/rtc-cmos.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry drivers/rtc/rtc-cmos.c --- a/drivers/rtc/rtc-cmos.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +++ a/drivers/rtc/rtc-cmos.c @@ -1032,7 +1032,7 @@ static struct platform_driver cmos_platf static int __init cmos_init(void) { #ifdef CONFIG_PNP - if (pnp_platform_devices) + if (pnp_platform_devices && !pnp_rtc_missing) return pnp_register_driver(&cmos_pnp_driver); else return platform_driver_probe(&cmos_platform_driver, @@ -1047,7 +1047,7 @@ module_init(cmos_init); static void __exit cmos_exit(void) { #ifdef CONFIG_PNP - if (pnp_platform_devices) + if (pnp_platform_devices && !pnp_rtc_missing) pnp_unregister_driver(&cmos_pnp_driver); else platform_driver_unregister(&cmos_platform_driver); diff -puN include/asm-x86/mc146818rtc.h~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry include/asm-x86/mc146818rtc.h --- a/include/asm-x86/mc146818rtc.h~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +++ a/include/asm-x86/mc146818rtc.h @@ -9,6 +9,8 @@ #include <asm/processor.h> #include <linux/mc146818rtc.h> +struct device; + #ifndef RTC_PORT #define RTC_PORT(x) (0x70 + (x)) #define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ @@ -87,6 +89,11 @@ static inline unsigned char current_lock #define current_lock_cmos_reg() 0 #endif +#ifdef CONFIG_PNP +#define ARCH_PNP_RTC_WORKAROUND +extern struct device *add_nonpnp_rtc_cmos(void); +#endif + /* * The yet supported machines all access the RTC index register via * an ISA port access but the way to access the date register differs ... diff -puN include/linux/pnp.h~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry include/linux/pnp.h --- a/include/linux/pnp.h~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +++ a/include/linux/pnp.h @@ -427,6 +427,7 @@ int pnp_device_attach(struct pnp_dev *pn void pnp_device_detach(struct pnp_dev *pnp_dev); extern struct list_head pnp_global; extern int pnp_platform_devices; +extern bool pnp_rtc_missing; /* multidevice card support */ struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, _ -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html