linux/debian/patches/bugfix/x86/nonpnp-rtc-device.patch

130 lines
4.0 KiB
Diff

From: David Brownell <dbrownell@users.sourceforge.net>
A bugzilla entry (http://bugzilla.kernel.org/show_bug.cgi?id=11580)
reports that PNPACPI tables in some HP servers don't list RTC devices.
Work around that on x86 (ignore 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@users.sourceforge.net>
---
arch/x86/kernel/rtc.c | 13 ++++++++++++-
drivers/acpi/glue.c | 14 +++++++++++++-
drivers/pnp/core.c | 7 +++++++
drivers/rtc/rtc-cmos.c | 4 ++--
include/asm-x86/mc146818rtc.h | 5 +++++
include/linux/pnp.h | 1 +
6 files changed, 40 insertions(+), 4 deletions(-)
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -220,10 +220,21 @@ 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
- if (!pnp_platform_devices)
+ /* sometimes pnpacpi=off */
+ if (!pnp_platform_devices && !rtc_device.dev.bus)
platform_device_register(&rtc_device);
#else
platform_device_register(&rtc_device);
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -338,7 +338,19 @@ 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; seen on some HP DL3x0 servers */
+ 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,17 @@ 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 critical devices, assigning them to grab-bag
+ * nodes and forcing drivers to use a platform_device node or (yeech!) use
+ * poke-at-the-hardware algorithms for device discovery.
*/
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,