Unverified Commit 8a7a3996 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!15604 v3 rtc: Fix race when disable/enable UIE in rtc_set_time()

Merge Pull Request from: @ci-robot 
 
PR sync from: Xiongfeng Wang <wangxiongfeng2@huawei.com>
https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/DQNHMNIYTZNJMT24BD4XEPVU7RQMLSPK/ 
Yu Liao (2):
  rtc: Cleanup for UIE timer/polling emulation support
  rtc: Fix race when disable/enable UIE in rtc_set_time()

 
https://gitee.com/src-openeuler/kernel/issues/IBV6W4 
 
Link:https://gitee.com/openeuler/kernel/pulls/15604

 

Reviewed-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: default avatarWang ShaoBo <bobo.shaobowang@huawei.com>
Reviewed-by: default avatarYuan Can <yuancan@huawei.com>
Signed-off-by: default avatarYuan Can <yuancan@huawei.com>
parents db5f05c2 a0211af5
Loading
Loading
Loading
Loading
+32 −26
Original line number Diff line number Diff line
@@ -139,20 +139,18 @@ 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
	uie = rtc->uie_rtctimer.enabled;
#endif
	if (uie) {
		err = rtc_update_irq_enable(rtc, 0);
	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
		return err;
	}

	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
	uie = rtc->uie_rtctimer.enabled;
	if (uie) {
		err = __rtc_update_irq_enable(rtc, 0);
		if (err) {
			mutex_unlock(&rtc->ops_lock);
			return err;
		}
	}

	if (!rtc->ops)
		err = -ENODEV;
@@ -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;
}
@@ -554,18 +550,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 +577,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
	/*
+1 −0
Original line number Diff line number Diff line
@@ -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);