提交 74c4633d 编写于 作者: R Rafael J. Wysocki 提交者: Linus Torvalds

rtc-cmos: wake again from S5

Update rtc-cmos shutdown handling to leave RTC alarms active, resolving
http://bugzilla.kernel.org/show_bug.cgi?id=11411 on several boards.  There
are still some systems where the ACPI event handling doesn't cooperate.
(Possibly related to bugid 11312, reporting the spontaneous disabling of
RTC events.)

Bug 11411 reported that changes to work around some ACPI event issues
broke wake-from-S5 handling, as used for DVR applications.  (They like to
power off, then wake later to record programs.)

[yakui.zhao@intel.com: add shutdown for PNP devices]
[dbrownell@users.sourceforge.net: update comments]
Signed-off-by: NRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: NZhao Yakui <yakui.zhao@intel.com>
Signed-off-by: NZhang Rui <rui.zhang@intel.com>
Signed-off-by: NDavid Brownell <dbrownell@users.sourceforge.net>
Cc: Stefan Bauer <stefan.bauer@cs.tu-chemnitz.de>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 8b3a8944
...@@ -800,7 +800,6 @@ static void __exit cmos_do_remove(struct device *dev) ...@@ -800,7 +800,6 @@ static void __exit cmos_do_remove(struct device *dev)
static int cmos_suspend(struct device *dev, pm_message_t mesg) static int cmos_suspend(struct device *dev, pm_message_t mesg)
{ {
struct cmos_rtc *cmos = dev_get_drvdata(dev); struct cmos_rtc *cmos = dev_get_drvdata(dev);
int do_wake = device_may_wakeup(dev);
unsigned char tmp; unsigned char tmp;
/* only the alarm might be a wakeup event source */ /* only the alarm might be a wakeup event source */
...@@ -809,7 +808,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) ...@@ -809,7 +808,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
unsigned char mask; unsigned char mask;
if (do_wake) if (device_may_wakeup(dev))
mask = RTC_IRQMASK & ~RTC_AIE; mask = RTC_IRQMASK & ~RTC_AIE;
else else
mask = RTC_IRQMASK; mask = RTC_IRQMASK;
...@@ -837,6 +836,17 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) ...@@ -837,6 +836,17 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
return 0; return 0;
} }
/* We want RTC alarms to wake us from e.g. ACPI G2/S5 "soft off", even
* after a detour through G3 "mechanical off", although the ACPI spec
* says wakeup should only work from G1/S4 "hibernate". To most users,
* distinctions between S4 and S5 are pointless. So when the hardware
* allows, don't draw that distinction.
*/
static inline int cmos_poweroff(struct device *dev)
{
return cmos_suspend(dev, PMSG_HIBERNATE);
}
static int cmos_resume(struct device *dev) static int cmos_resume(struct device *dev)
{ {
struct cmos_rtc *cmos = dev_get_drvdata(dev); struct cmos_rtc *cmos = dev_get_drvdata(dev);
...@@ -884,6 +894,12 @@ static int cmos_resume(struct device *dev) ...@@ -884,6 +894,12 @@ static int cmos_resume(struct device *dev)
#else #else
#define cmos_suspend NULL #define cmos_suspend NULL
#define cmos_resume NULL #define cmos_resume NULL
static inline int cmos_poweroff(struct device *dev)
{
return -ENOSYS;
}
#endif #endif
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
...@@ -903,10 +919,6 @@ static int cmos_resume(struct device *dev) ...@@ -903,10 +919,6 @@ static int cmos_resume(struct device *dev)
static int __devinit static int __devinit
cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
{ {
/* REVISIT paranoia argues for a shutdown notifier, since PNP
* drivers can't provide shutdown() methods to disable IRQs.
* Or better yet, fix PNP to allow those methods...
*/
if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0)) if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0))
/* Some machines contain a PNP entry for the RTC, but /* Some machines contain a PNP entry for the RTC, but
* don't define the IRQ. It should always be safe to * don't define the IRQ. It should always be safe to
...@@ -942,6 +954,13 @@ static int cmos_pnp_resume(struct pnp_dev *pnp) ...@@ -942,6 +954,13 @@ static int cmos_pnp_resume(struct pnp_dev *pnp)
#define cmos_pnp_resume NULL #define cmos_pnp_resume NULL
#endif #endif
static void cmos_pnp_shutdown(struct device *pdev)
{
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev))
return;
cmos_do_shutdown();
}
static const struct pnp_device_id rtc_ids[] = { static const struct pnp_device_id rtc_ids[] = {
{ .id = "PNP0b00", }, { .id = "PNP0b00", },
...@@ -961,6 +980,10 @@ static struct pnp_driver cmos_pnp_driver = { ...@@ -961,6 +980,10 @@ static struct pnp_driver cmos_pnp_driver = {
.flags = PNP_DRIVER_RES_DO_NOT_CHANGE, .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
.suspend = cmos_pnp_suspend, .suspend = cmos_pnp_suspend,
.resume = cmos_pnp_resume, .resume = cmos_pnp_resume,
.driver = {
.name = (char *)driver_name,
.shutdown = cmos_pnp_shutdown,
}
}; };
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
...@@ -986,6 +1009,9 @@ static int __exit cmos_platform_remove(struct platform_device *pdev) ...@@ -986,6 +1009,9 @@ static int __exit cmos_platform_remove(struct platform_device *pdev)
static void cmos_platform_shutdown(struct platform_device *pdev) static void cmos_platform_shutdown(struct platform_device *pdev)
{ {
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pdev->dev))
return;
cmos_do_shutdown(); cmos_do_shutdown();
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册