diff options
Diffstat (limited to 'drivers/rtc/interface.c')
| -rw-r--r-- | drivers/rtc/interface.c | 30 | 
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 72c5cdbe079..5813fa52c3d 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -72,6 +72,7 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)  	} else  		err = -EINVAL; +	pm_stay_awake(rtc->dev.parent);  	mutex_unlock(&rtc->ops_lock);  	/* A timer might have just expired */  	schedule_work(&rtc->irqwork); @@ -113,6 +114,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)  		err = -EINVAL;  	} +	pm_stay_awake(rtc->dev.parent);  	mutex_unlock(&rtc->ops_lock);  	/* A timer might have just expired */  	schedule_work(&rtc->irqwork); @@ -290,7 +292,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");  		do {  			alarm->time.tm_year++; -		} while (rtc_valid_tm(&alarm->time) != 0); +		} while (!is_leap_year(alarm->time.tm_year + 1900) +			&& rtc_valid_tm(&alarm->time) != 0);  		break;  	default: @@ -298,7 +301,16 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  	}  done: -	return 0; +	err = rtc_valid_tm(&alarm->time); + +	if (err) { +		dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n", +			alarm->time.tm_year + 1900, alarm->time.tm_mon + 1, +			alarm->time.tm_mday, alarm->time.tm_hour, alarm->time.tm_min, +			alarm->time.tm_sec); +	} + +	return err;  }  int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) @@ -582,6 +594,9 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer)  void rtc_update_irq(struct rtc_device *rtc,  		unsigned long num, unsigned long events)  { +	if (unlikely(IS_ERR_OR_NULL(rtc))) +		return; +  	pm_stay_awake(rtc->dev.parent);  	schedule_work(&rtc->irqwork);  } @@ -771,9 +786,10 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)  		alarm.time = rtc_ktime_to_tm(timer->node.expires);  		alarm.enabled = 1;  		err = __rtc_set_alarm(rtc, &alarm); -		if (err == -ETIME) +		if (err == -ETIME) { +			pm_stay_awake(rtc->dev.parent);  			schedule_work(&rtc->irqwork); -		else if (err) { +		} else if (err) {  			timerqueue_del(&rtc->timerqueue, &timer->node);  			timer->enabled = 0;  			return err; @@ -818,8 +834,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)  		alarm.time = rtc_ktime_to_tm(next->expires);  		alarm.enabled = 1;  		err = __rtc_set_alarm(rtc, &alarm); -		if (err == -ETIME) +		if (err == -ETIME) { +			pm_stay_awake(rtc->dev.parent);  			schedule_work(&rtc->irqwork); +		}  	}  } @@ -845,7 +863,6 @@ void rtc_timer_do_work(struct work_struct *work)  	mutex_lock(&rtc->ops_lock);  again: -	pm_relax(rtc->dev.parent);  	__rtc_read_time(rtc, &tm);  	now = rtc_tm_to_ktime(tm);  	while ((next = timerqueue_getnext(&rtc->timerqueue))) { @@ -880,6 +897,7 @@ again:  	} else  		rtc_alarm_disable(rtc); +	pm_relax(rtc->dev.parent);  	mutex_unlock(&rtc->ops_lock);  }  | 
