[PATCH openEuler-1.0-LTS 0/2] Fix race when disable/enable UIE in rtc_set_time()

Yu Liao (2): rtc: Cleanup for UIE timer/polling emulation support rtc: Fix race when disable/enable UIE in rtc_set_time() drivers/rtc/interface.c | 58 +++++++++++++++++++++++------------------ include/linux/rtc.h | 1 + 2 files changed, 33 insertions(+), 26 deletions(-) -- 2.20.1

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/15598 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/6CG... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/15598 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/6CG...

From: Yu Liao <liaoyu15@huawei.com> Offering: HULK hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBV69J -------------------------------- Split out a function that does not acquire ops_lock from rtc_update_irq_enable, in preparation for fixing RTC_RD_TIME and RTC_UIE_ON race problem. Signed-off-by: Yu Liao <liaoyu15@huawei.com> Conflicts: drivers/rtc/interface.c [wxf: Backport from OLK-5.10. Fix context conflicts] Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com> --- drivers/rtc/interface.c | 30 ++++++++++++++++++++---------- include/linux/rtc.h | 1 + 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 1ab619fb978a..f5ff99ca1088 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -554,18 +554,10 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) } EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable); -int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) +int __rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) { - int err = mutex_lock_interruptible(&rtc->ops_lock); - if (err) - return err; + int err = 0; -#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL - if (enabled == 0 && rtc->uie_irq_active) { - mutex_unlock(&rtc->ops_lock); - return rtc_dev_update_irq_enable_emul(rtc, 0); - } -#endif /* make sure we're changing state */ if (rtc->uie_rtctimer.enabled == enabled) goto out; @@ -589,6 +581,24 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) rtc_timer_remove(rtc, &rtc->uie_rtctimer); out: + return err; + +} + +int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) +{ + int err = mutex_lock_interruptible(&rtc->ops_lock); + if (err) + return err; + +#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL + if (enabled == 0 && rtc->uie_irq_active) { + mutex_unlock(&rtc->ops_lock); + return rtc_dev_update_irq_enable_emul(rtc, 0); + } +#endif + + err = __rtc_update_irq_enable(rtc, enabled); mutex_unlock(&rtc->ops_lock); #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL /* diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 5a34f59941fb..54a63198e3cb 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -200,6 +200,7 @@ extern void rtc_class_close(struct rtc_device *rtc); extern int rtc_irq_set_state(struct rtc_device *rtc, int enabled); extern int rtc_irq_set_freq(struct rtc_device *rtc, int freq); extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); +extern int __rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled); extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled); -- 2.20.1

From: Yu Liao <liaoyu15@huawei.com> Offering: HULK hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBV69J -------------------------------- 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> --- 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
participants (2)
-
patchwork bot
-
Xiongfeng Wang