130 lines
4.0 KiB
Diff
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,
|