alarm: port from 2818, fix shutdown bug
author黄涛 <huangtao@rock-chips.com>
Tue, 26 Apr 2011 12:49:01 +0000 (20:49 +0800)
committer黄涛 <huangtao@rock-chips.com>
Tue, 26 Apr 2011 13:00:38 +0000 (21:00 +0800)
try to fix this bug:
Unable to handle kernel paging request at virtual address 0fff1004
pgd = ce794000
[0fff1004] *pgd=00000000
Internal error: Oops: 5 [#1] PREEMPT
last sysfs file: /sys/power/wake_lock
Modules linked in:
CPU: 0    Not tainted  (2.6.32.27 #1)
PC is at rb_erase+0xf4/0x344
LR is at __remove_hrtimer+0xa4/0xb0
pc : [<c054d030>]    lr : [<c0463bec>]    psr: 20000193
sp : ccc1dda8  ip : c0876af8  fp : 00000000
r10: 00000000  r9 : ccc1c000  r8 : c04290c4
r7 : 00000001  r6 : 00000000  r5 : c0876b00  r4 : 0fff0ffc
r3 : 00000000  r2 : 00000000  r1 : 00000001  r0 : c124fae8
Flags: nzCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 10c5387d  Table: 6e794019  DAC: 00000015

[<c054d030>] (rb_erase+0xf4/0x344) from [<c0463bec>] (__remove_hrtimer+0xa4/0xb0)
[<c0463bec>] (__remove_hrtimer+0xa4/0xb0) from [<c0463c5c>] (hrtimer_try_to_cancel+0x64/0xac)
[<c0463c5c>] (hrtimer_try_to_cancel+0x64/0xac) from [<c0463cb4>] (hrtimer_cancel+0x10/0x20)
[<c0463cb4>] (hrtimer_cancel+0x10/0x20) from [<c060e25c>] (alarm_shutdown+0x7c/0x270)
[<c060e25c>] (alarm_shutdown+0x7c/0x270) from [<c0581fe0>] (platform_drv_shutdown+0x18/0x1c)
[<c0581fe0>] (platform_drv_shutdown+0x18/0x1c) from [<c057df90>] (device_shutdown+0x58/0xa0)
[<c057df90>] (device_shutdown+0x58/0xa0) from [<c045b75c>] (kernel_power_off+0xc/0x3c)
[<c045b75c>] (kernel_power_off+0xc/0x3c) from [<c045ba50>] (sys_reboot+0x14c/0x22c)
[<c045ba50>] (sys_reboot+0x14c/0x22c) from [<c0428f40>] (ret_fast_syscall+0x0/0x2c)

drivers/rtc/alarm.c

index 7232a538d3991a6ce77e6fdc690209975e522c9c..a6c07075a70907437249b0cec1032bd00c198196 100644 (file)
@@ -419,6 +419,7 @@ static int alarm_suspend(struct platform_device *pdev, pm_message_t state)
                if (rtc_current_time + 1 >= rtc_alarm_time) {
                        pr_alarm(SUSPEND, "alarm about to go off\n");
                        memset(&rtc_alarm, 0, sizeof(rtc_alarm));
+                       rtc_time_to_tm(0, &rtc_alarm.time);
                        rtc_alarm.enabled = 0;
                        rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
 
@@ -444,6 +445,7 @@ static int alarm_resume(struct platform_device *pdev)
        pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev);
 
        memset(&alarm, 0, sizeof(alarm));
+       rtc_time_to_tm(0, &alarm.time);
        alarm.enabled = 0;
        rtc_set_alarm(alarm_rtc_dev, &alarm);
 
@@ -457,6 +459,18 @@ static int alarm_resume(struct platform_device *pdev)
        return 0;
 }
 
+static void alarm_shutdown(struct platform_device *pdev)
+{
+       struct rtc_wkalrm alarm;
+
+       pr_alarm(FLOW, "alarm_shutdown(%p)\n", pdev);
+
+       memset(&alarm, 0, sizeof(alarm));
+       rtc_time_to_tm(0, &alarm.time);
+       alarm.enabled = 0;
+       rtc_set_alarm(alarm_rtc_dev, &alarm);
+}
+
 static struct rtc_task alarm_rtc_task = {
        .func = alarm_triggered_func
 };
@@ -516,6 +530,7 @@ static struct class_interface rtc_alarm_interface = {
 static struct platform_driver alarm_driver = {
        .suspend = alarm_suspend,
        .resume = alarm_resume,
+       .shutdown = alarm_shutdown,
        .driver = {
                .name = "alarm"
        }