aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorXianglong Du <Xianglong.Du@csr.com>2013-09-11 17:24:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:58:57 -0400
commit28984c7d94c27b993d09d4f2a1a2c36bfd26fd23 (patch)
treee7d40524c7634317e7f2e8e76acdb8721901931d /drivers/rtc
parent0ebbf4397664d66f3e35503f2f3778a5e6377cbf (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.c13
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