From 1efd325fbadc02c1338e0ef676f0a6669b251c7a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 12 Oct 2008 11:30:08 -0700 Subject: Fix RTC wakealarm sysfs interface breakage. Commit ed458df4d2470adc02762a87a9ad665d0b1a2bd4 ("PnP: move pnpacpi/pnpbios_init to after PCI init") moved the PnP RTC discovery later, and now the ACPI RTC glue code doesn't find it any more, breaking the RTC wakealarm sysfs interfaces, as reported by Rafael. This really is fairly messy, and we have several annoying ordering constraints here - the PnP code that sets up the RTC resources wants to run after the PCI resources have to be registered, which in turn needs to run after ACPI has at least enumerated the root PCI buses etc. Our initcall ordering is not fine-grained enough to make this all painless. So this moves the ACPI RTC glue ("acpi_rtc_init()") down to a regular module call, which fixes the problem Rafael has. The reason this isn't wonderful is that we really should do acpi_rtc_init before we do the rtc_cmos init, and now those two are in the same module_init() section. Which happens to work, but only because drivers/rtc is linked after drivers/acpi. In other words, we still have a very subtle ordering issue here. Grr. Reported-and-tested-by: Rafael J. Wysocki Acked-by: David Brownell Signed-off-by: Linus Torvalds --- drivers/acpi/glue.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/acpi/glue.c') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 8dd3336efd7e..3c578ef78c48 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -369,7 +369,6 @@ static int __init acpi_rtc_init(void) DBG("RTC unavailable?\n"); return 0; } -/* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */ -fs_initcall(acpi_rtc_init); +module_init(acpi_rtc_init); #endif -- cgit v1.2.3 From a474aaedac99ba86e28ef6c912a7647c482db6dd Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 14 Oct 2008 13:50:21 -0600 Subject: rtc-cmos: move wake setup from ACPI glue into RTC driver Move rtc_wake_setup() from drivers/acpi/glue.c into the RTC driver in drivers/rtc/rtc-cmos.c. This removes the ordering constraint between the module_init(acpi_rtc_init) and the cmos_do_probe() code that depends on it. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki Signed-off-by: Linus Torvalds --- drivers/acpi/glue.c | 112 ------------------------------------------------- drivers/rtc/rtc-cmos.c | 89 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 112 deletions(-) (limited to 'drivers/acpi/glue.c') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 3c578ef78c48..24649ada08df 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -260,115 +260,3 @@ static int __init init_acpi_device_notify(void) } arch_initcall(init_acpi_device_notify); - - -#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) - -#ifdef CONFIG_PM -static u32 rtc_handler(void *context) -{ - acpi_clear_event(ACPI_EVENT_RTC); - acpi_disable_event(ACPI_EVENT_RTC, 0); - return ACPI_INTERRUPT_HANDLED; -} - -static inline void rtc_wake_setup(void) -{ - acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); - /* - * After the RTC handler is installed, the Fixed_RTC event should - * be disabled. Only when the RTC alarm is set will it be enabled. - */ - acpi_clear_event(ACPI_EVENT_RTC); - acpi_disable_event(ACPI_EVENT_RTC, 0); -} - -static void rtc_wake_on(struct device *dev) -{ - acpi_clear_event(ACPI_EVENT_RTC); - acpi_enable_event(ACPI_EVENT_RTC, 0); -} - -static void rtc_wake_off(struct device *dev) -{ - acpi_disable_event(ACPI_EVENT_RTC, 0); -} -#else -#define rtc_wake_setup() do{}while(0) -#define rtc_wake_on NULL -#define rtc_wake_off NULL -#endif - -/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find - * its device node and pass extra config data. This helps its driver use - * capabilities that the now-obsolete mc146818 didn't have, and informs it - * that this board's RTC is wakeup-capable (per ACPI spec). - */ -#include - -static struct cmos_rtc_board_info rtc_info; - - -/* PNP devices are registered in a subsys_initcall(); - * ACPI specifies the PNP IDs to use. - */ -#include - -static int __init pnp_match(struct device *dev, void *data) -{ - static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", }; - struct pnp_dev *pnp = to_pnp_dev(dev); - int i; - - for (i = 0; i < ARRAY_SIZE(ids); i++) { - if (compare_pnp_id(pnp->id, ids[i]) != 0) - return 1; - } - return 0; -} - -static struct device *__init get_rtc_dev(void) -{ - return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match); -} - -static int __init acpi_rtc_init(void) -{ - struct device *dev = get_rtc_dev(); - - if (acpi_disabled) - return 0; - - if (dev) { - rtc_wake_setup(); - rtc_info.wake_on = rtc_wake_on; - rtc_info.wake_off = rtc_wake_off; - - /* workaround bug in some ACPI tables */ - if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { - DBG("bogus FADT month_alarm\n"); - acpi_gbl_FADT.month_alarm = 0; - } - - rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; - rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; - rtc_info.rtc_century = acpi_gbl_FADT.century; - - /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */ - if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) - printk(PREFIX "RTC can wake from S4\n"); - - - dev->platform_data = &rtc_info; - - /* RTC always wakes from S1/S2/S3, and often S4/STD */ - device_init_wakeup(dev, 1); - - put_device(dev); - } else - DBG("RTC unavailable?\n"); - return 0; -} -module_init(acpi_rtc_init); - -#endif diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index b23af0c2a869..6778f82bad24 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -913,6 +913,92 @@ static inline int cmos_poweroff(struct device *dev) * predate even PNPBIOS should set up platform_bus devices. */ +#ifdef CONFIG_ACPI + +#include + +#ifdef CONFIG_PM +static u32 rtc_handler(void *context) +{ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_disable_event(ACPI_EVENT_RTC, 0); + return ACPI_INTERRUPT_HANDLED; +} + +static inline void rtc_wake_setup(void) +{ + acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); + /* + * After the RTC handler is installed, the Fixed_RTC event should + * be disabled. Only when the RTC alarm is set will it be enabled. + */ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_disable_event(ACPI_EVENT_RTC, 0); +} + +static void rtc_wake_on(struct device *dev) +{ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_enable_event(ACPI_EVENT_RTC, 0); +} + +static void rtc_wake_off(struct device *dev) +{ + acpi_disable_event(ACPI_EVENT_RTC, 0); +} +#else +#define rtc_wake_setup() do{}while(0) +#define rtc_wake_on NULL +#define rtc_wake_off NULL +#endif + +/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find + * its device node and pass extra config data. This helps its driver use + * capabilities that the now-obsolete mc146818 didn't have, and informs it + * that this board's RTC is wakeup-capable (per ACPI spec). + */ +static struct cmos_rtc_board_info acpi_rtc_info; + +static void __devinit +cmos_wake_setup(struct device *dev) +{ + if (acpi_disabled) + return; + + rtc_wake_setup(); + acpi_rtc_info.wake_on = rtc_wake_on; + acpi_rtc_info.wake_off = rtc_wake_off; + + /* workaround bug in some ACPI tables */ + if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { + dev_dbg(dev, "bogus FADT month_alarm (%d)\n", + acpi_gbl_FADT.month_alarm); + acpi_gbl_FADT.month_alarm = 0; + } + + acpi_rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; + acpi_rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; + acpi_rtc_info.rtc_century = acpi_gbl_FADT.century; + + /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */ + if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) + dev_info(dev, "RTC can wake from S4\n"); + + dev->platform_data = &acpi_rtc_info; + + /* RTC always wakes from S1/S2/S3, and often S4/STD */ + device_init_wakeup(dev, 1); +} + +#else + +static void __devinit +cmos_wake_setup(struct device *dev) +{ +} + +#endif + #ifdef CONFIG_PNP #include @@ -920,6 +1006,8 @@ static inline int cmos_poweroff(struct device *dev) static int __devinit cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) { + cmos_wake_setup(&pnp->dev); + if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0)) /* Some machines contain a PNP entry for the RTC, but * don't define the IRQ. It should always be safe to @@ -997,6 +1085,7 @@ static struct pnp_driver cmos_pnp_driver = { static int __init cmos_platform_probe(struct platform_device *pdev) { + cmos_wake_setup(&pdev->dev); return cmos_do_probe(&pdev->dev, platform_get_resource(pdev, IORESOURCE_IO, 0), platform_get_irq(pdev, 0)); -- cgit v1.2.3