rtc: s3c: balance state changes of wakeup flag

This change resolves a problem about unbalanced calls of
enable_irq_wakeup() and disable_irq_wakeup() for alarm interrupt.

Bug reproduction:

root@eb600:~# echo 0 > /sys/class/rtc/rtc0/wakealarm

WARNING: at kernel/irq/manage.c:361 set_irq_wake+0x7c/0xe4()
Unbalanced IRQ 46 wake disable
Modules linked in:
[<c0025708>] (unwind_backtrace+0x0/0xd8) from [<c003358c>] (warn_slowpath_common+0x44/0x5c)
[<c003358c>] (warn_slowpath_common+0x44/0x5c) from [<c00335dc>] (warn_slowpath_fmt+0x24/0x30)
[<c00335dc>] (warn_slowpath_fmt+0x24/0x30) from [<c0058c20>] (set_irq_wake+0x7c/0xe4)
[<c0058c20>] (set_irq_wake+0x7c/0xe4) from [<c01b5e80>] (s3c_rtc_setalarm+0xa8/0xb8)
[<c01b5e80>] (s3c_rtc_setalarm+0xa8/0xb8) from [<c01b47a0>] (rtc_set_alarm+0x60/0x74)
[<c01b47a0>] (rtc_set_alarm+0x60/0x74) from [<c01b5a98>] (rtc_sysfs_set_wakealarm+0xc8/0xd8)
[<c01b5a98>] (rtc_sysfs_set_wakealarm+0xc8/0xd8) from [<c01891ec>] (dev_attr_store+0x20/0x24)
[<c01891ec>] (dev_attr_store+0x20/0x24) from [<c00be934>] (sysfs_write_file+0x104/0x13c)
[<c00be934>] (sysfs_write_file+0x104/0x13c) from [<c0080e7c>] (vfs_write+0xb0/0x158)
[<c0080e7c>] (vfs_write+0xb0/0x158) from [<c0080fcc>] (sys_write+0x3c/0x68)
[<c0080fcc>] (sys_write+0x3c/0x68) from [<c0020ec0>] (ret_fast_syscall+0x0/0x28)

Signed-off-by: Vladimir Zapolskiy <vzapolskiy@gmail.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Ben Dooks <ben@fluff.org.uk>
Cc: Atul Dahiya <atul.dahiya@samsung.com>
Cc: Taekgyun Ko <taeggyun.ko@samsung.com>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Vladimir Zapolskiy and committed by Linus Torvalds f501ed52 2aeadc30

+8 -5
+8 -5
drivers/rtc/rtc-s3c.c
··· 310 311 s3c_rtc_setaie(alrm->enabled); 312 313 - if (alrm->enabled) 314 - enable_irq_wake(s3c_rtc_alarmno); 315 - else 316 - disable_irq_wake(s3c_rtc_alarmno); 317 - 318 return 0; 319 } 320 ··· 582 ticnt_en_save &= S3C64XX_RTCCON_TICEN; 583 } 584 s3c_rtc_enable(pdev, 0); 585 return 0; 586 } 587 ··· 599 tmp = readb(s3c_rtc_base + S3C2410_RTCCON); 600 writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); 601 } 602 return 0; 603 } 604 #else
··· 310 311 s3c_rtc_setaie(alrm->enabled); 312 313 return 0; 314 } 315 ··· 587 ticnt_en_save &= S3C64XX_RTCCON_TICEN; 588 } 589 s3c_rtc_enable(pdev, 0); 590 + 591 + if (device_may_wakeup(&pdev->dev)) 592 + enable_irq_wake(s3c_rtc_alarmno); 593 + 594 return 0; 595 } 596 ··· 600 tmp = readb(s3c_rtc_base + S3C2410_RTCCON); 601 writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); 602 } 603 + 604 + if (device_may_wakeup(&pdev->dev)) 605 + disable_irq_wake(s3c_rtc_alarmno); 606 + 607 return 0; 608 } 609 #else