
From: Yu Liao <liaoyu15@huawei.com> hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBV6W4 -------------------------------- When the RTC_SET_TIME and RTC_RD_TIME threads run in parallel, there is no guarantee that uie_rtctimer.enabled is equal to the previously read uie when executing rtc->ops->set_time. Fix this by keeping reading uie state, disabling uie, setting rtc time and enabling uie in critical sections. Fixes: 7e7c005b4b1f ("rtc: disable uie before setting time and enable after") Signed-off-by: Yu Liao <liaoyu15@huawei.com> Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com> --- drivers/rtc/interface.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index f5ff99ca1088..c0eee8c2602e 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -139,21 +139,19 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) rtc_subtract_offset(rtc, tm); -#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL - uie = rtc->uie_rtctimer.enabled || rtc->uie_irq_active; -#else + err = mutex_lock_interruptible(&rtc->ops_lock); + if (err) + return err; + uie = rtc->uie_rtctimer.enabled; -#endif if (uie) { - err = rtc_update_irq_enable(rtc, 0); - if (err) + err = __rtc_update_irq_enable(rtc, 0); + if (err) { + mutex_unlock(&rtc->ops_lock); return err; + } } - err = mutex_lock_interruptible(&rtc->ops_lock); - if (err) - return err; - if (!rtc->ops) err = -ENODEV; else if (rtc->ops->set_time) @@ -169,16 +167,14 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) err = -EINVAL; pm_stay_awake(rtc->dev.parent); + + if (uie) + err = __rtc_update_irq_enable(rtc, 1); + mutex_unlock(&rtc->ops_lock); /* A timer might have just expired */ schedule_work(&rtc->irqwork); - if (uie) { - err = rtc_update_irq_enable(rtc, 1); - if (err) - return err; - } - trace_rtc_set_time(rtc_tm_to_time64(tm), err); return err; } -- 2.20.1