acpi: cope with PNPACPI tables missing an RTC entry
Subsystems (4)
PATCH 2/2 acpi: cope with PNPACPI tables missing an RTC entry
From: David Brownell <[email protected]>
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.
[[email protected]: forward-declare struct device]
Signed-off-by David Brownell <[email protected]>
Reported-by Rik Theys <[email protected]>
Cc Adam Belay <[email protected]>
Cc Chuck Ebbert <[email protected]>
Cc Len Brown <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Acked-by Alessandro Zummo <[email protected]>
Cc <[email protected]>
Signed-off-by Andrew Morton <[email protected]>
---
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(-)
arch/x86/kernel/rtc.c renamed from arch/x86/kernel/rtc.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +12 -1
@@ -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 */
drivers/acpi/glue.c renamed from drivers/acpi/glue.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +15 -1
@@ -366,7 +366,21 @@ static int __init pnp_match(struct devicstatic 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 )
drivers/pnp/core.c renamed from drivers/pnp/core.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +8 -0
@@ -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;
drivers/rtc/rtc-cmos.c renamed from drivers/rtc/rtc-cmos.c~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +2 -2
@@ -1032,7 +1032,7 @@ static struct platform_driver cmos_platfstatic 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);
include/asm-x86/mc146818rtc.h renamed from include/asm-x86/mc146818rtc.h~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +7 -0
@@ -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 ...
include/linux/pnp.h renamed from include/linux/pnp.h~acpi-cope-with-pnpacpi-tables-missing-an-rtc-entry +1 -0
@@ -427,6 +427,7 @@ int pnp_device_attach(struct pnp_dev *pnvoid 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,
_