Re: [patch 2.6.27-rc6] cope with PNPACPI tables missing an RTCentry

From: Andrew Morton
Date: Thu Sep 18 2008 - 13:50:44 EST


(cc's added)

On Thu, 18 Sep 2008 10:42:46 -0700 David Brownell <david-b@xxxxxxxxxxx> wrote:

> 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.
>
> Signed-off-by: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx>
> Reported-by: Rik Theys <rik.theys@xxxxxxxxxxxxxxxx>
> ---
> 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.
>
> 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 | 5 +++++
> include/linux/pnp.h | 1 +
> 6 files changed, 43 insertions(+), 4 deletions(-)
>
> --- a/arch/x86/kernel/rtc.c
> +++ b/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 */
> --- a/drivers/acpi/glue.c
> +++ b/drivers/acpi/glue.c
> @@ -338,7 +338,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)
> --- a/drivers/pnp/core.c
> +++ b/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;
> --- a/drivers/rtc/rtc-cmos.c
> +++ b/drivers/rtc/rtc-cmos.c
> @@ -1137,7 +1137,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,
> @@ -1152,7 +1152,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);
> --- a/include/asm-x86/mc146818rtc.h
> +++ b/include/asm-x86/mc146818rtc.h
> @@ -101,4 +101,9 @@ extern unsigned long mach_get_cmos_time(
>
> #define RTC_IRQ 8
>
> +#ifdef CONFIG_PNP
> +#define ARCH_PNP_RTC_WORKAROUND
> +extern struct device *add_nonpnp_rtc_cmos(void);
> +#endif
> +
> #endif /* _ASM_MC146818RTC_H */
> --- a/include/linux/pnp.h
> +++ b/include/linux/pnp.h
> @@ -420,6 +420,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-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/