diff options
author | Xianglong Du <Xianglong.Du@csr.com> | 2013-09-11 17:24:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-11 18:58:57 -0400 |
commit | 28984c7d94c27b993d09d4f2a1a2c36bfd26fd23 (patch) | |
tree | e7d40524c7634317e7f2e8e76acdb8721901931d /drivers/rtc | |
parent | 0ebbf4397664d66f3e35503f2f3778a5e6377cbf (diff) |
drivers/rtc/rtc-sirfsoc.c: fix kernel warning during wakeup
enable_irq_wake() might fail, if so, we will see kernel warning in resume
entries due to it always calls disable_irq_wake().
WARNING: at kernel/irq/manage.c:529 irq_set_irq_wake+0xc4/0xf0()
Unbalanced IRQ 52 wake disable
Modules linked in: ipv6 libcomposite configfs
CPU: 0 PID: 1591 Comm: ash Tainted: G W 3.10.0-00854-gdbd86d4-dirty #100
(unwind_backtrace+0x0/0xf8) from (show_stack+0x10/0x14)
(show_stack+0x10/0x14) from (warn_slowpath_common+0x54/0x68)
(warn_slowpath_common+0x54/0x68) from (warn_slowpath_fmt+0x30/0x40)
(warn_slowpath_fmt+0x30/0x40) from (irq_set_irq_wake+0xc4/0xf0)
(irq_set_irq_wake+0xc4/0xf0) from (sirfsoc_rtc_restore+0x30/0x38)
(sirfsoc_rtc_restore+0x30/0x38) from (platform_pm_restore+0x2c/0x50)
(platform_pm_restore+0x2c/0x50) from (dpm_run_callback.clone.6+0x30/0xb0)
(dpm_run_callback.clone.6+0x30/0xb0) from (device_resume+0x88/0x134)
(device_resume+0x88/0x134) from (dpm_resume+0x114/0x230)
(dpm_resume+0x114/0x230) from (hibernation_snapshot+0x178/0x1d0)
(hibernation_snapshot+0x178/0x1d0) from (hibernate+0x130/0x1dc)
(hibernate+0x130/0x1dc) from (state_store+0xb4/0xc0)
(state_store+0xb4/0xc0) from (kobj_attr_store+0x14/0x20)
(kobj_attr_store+0x14/0x20) from (sysfs_write_file+0xfc/0x17c)
(sysfs_write_file+0xfc/0x17c) from (vfs_write+0xc8/0x194)
(vfs_write+0xc8/0x194) from (SyS_write+0x40/0x6c)
(SyS_write+0x40/0x6c) from (ret_fast_syscall+0x0/0x30)
To avoid unbalanced "IRQ wake disable", ensure that disable_irq_wake() is
called only when enable_irq_wake() have been successfully enabled.
Signed-off-by: Xianglong Du <Xianglong.Du@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-sirfsoc.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c index aa7ed4b5f7f0..63460cf80f1b 100644 --- a/drivers/rtc/rtc-sirfsoc.c +++ b/drivers/rtc/rtc-sirfsoc.c | |||
@@ -44,6 +44,7 @@ struct sirfsoc_rtc_drv { | |||
44 | struct rtc_device *rtc; | 44 | struct rtc_device *rtc; |
45 | u32 rtc_base; | 45 | u32 rtc_base; |
46 | u32 irq; | 46 | u32 irq; |
47 | unsigned irq_wake; | ||
47 | /* Overflow for every 8 years extra time */ | 48 | /* Overflow for every 8 years extra time */ |
48 | u32 overflow_rtc; | 49 | u32 overflow_rtc; |
49 | #ifdef CONFIG_PM | 50 | #ifdef CONFIG_PM |
@@ -355,8 +356,8 @@ static int sirfsoc_rtc_suspend(struct device *dev) | |||
355 | rtcdrv->saved_counter = | 356 | rtcdrv->saved_counter = |
356 | sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN); | 357 | sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN); |
357 | rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc; | 358 | rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc; |
358 | if (device_may_wakeup(&pdev->dev)) | 359 | if (device_may_wakeup(&pdev->dev) && !enable_irq_wake(rtcdrv->irq)) |
359 | enable_irq_wake(rtcdrv->irq); | 360 | rtcdrv->irq_wake = 1; |
360 | 361 | ||
361 | return 0; | 362 | return 0; |
362 | } | 363 | } |
@@ -423,8 +424,10 @@ static int sirfsoc_rtc_resume(struct device *dev) | |||
423 | struct platform_device *pdev = to_platform_device(dev); | 424 | struct platform_device *pdev = to_platform_device(dev); |
424 | struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev); | 425 | struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev); |
425 | sirfsoc_rtc_thaw(dev); | 426 | sirfsoc_rtc_thaw(dev); |
426 | if (device_may_wakeup(&pdev->dev)) | 427 | if (device_may_wakeup(&pdev->dev) && rtcdrv->irq_wake) { |
427 | disable_irq_wake(rtcdrv->irq); | 428 | disable_irq_wake(rtcdrv->irq); |
429 | rtcdrv->irq_wake = 0; | ||
430 | } | ||
428 | 431 | ||
429 | return 0; | 432 | return 0; |
430 | } | 433 | } |
@@ -434,8 +437,10 @@ static int sirfsoc_rtc_restore(struct device *dev) | |||
434 | struct platform_device *pdev = to_platform_device(dev); | 437 | struct platform_device *pdev = to_platform_device(dev); |
435 | struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev); | 438 | struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev); |
436 | 439 | ||
437 | if (device_may_wakeup(&pdev->dev)) | 440 | if (device_may_wakeup(&pdev->dev) && rtcdrv->irq_wake) { |
438 | disable_irq_wake(rtcdrv->irq); | 441 | disable_irq_wake(rtcdrv->irq); |
442 | rtcdrv->irq_wake = 0; | ||
443 | } | ||
439 | return 0; | 444 | return 0; |
440 | } | 445 | } |
441 | 446 | ||