From patchwork Sat Sep 24 01:32:42 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 4309 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 6F77A23F56 for ; Sat, 24 Sep 2011 01:33:19 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id 64EE5A18411 for ; Sat, 24 Sep 2011 01:33:19 +0000 (UTC) Received: by mail-fx0-f52.google.com with SMTP id 23so6092605fxe.11 for ; Fri, 23 Sep 2011 18:33:19 -0700 (PDT) Received: by 10.223.94.134 with SMTP id z6mr6043665fam.8.1316827999288; Fri, 23 Sep 2011 18:33:19 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.18.198 with SMTP id y6cs9232lad; Fri, 23 Sep 2011 18:33:19 -0700 (PDT) Received: by 10.150.163.7 with SMTP id l7mr3908859ybe.369.1316827996785; Fri, 23 Sep 2011 18:33:16 -0700 (PDT) Received: from e8.ny.us.ibm.com (e8.ny.us.ibm.com. [32.97.182.138]) by mx.google.com with ESMTPS id h11si6977839ybd.92.2011.09.23.18.33.16 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 23 Sep 2011 18:33:16 -0700 (PDT) Received-SPF: pass (google.com: domain of jstultz@us.ibm.com designates 32.97.182.138 as permitted sender) client-ip=32.97.182.138; Authentication-Results: mx.google.com; spf=pass (google.com: domain of jstultz@us.ibm.com designates 32.97.182.138 as permitted sender) smtp.mail=jstultz@us.ibm.com Received: from d01relay01.pok.ibm.com (d01relay01.pok.ibm.com [9.56.227.233]) by e8.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p8O1ITVl021625; Fri, 23 Sep 2011 21:18:29 -0400 Received: from d01av02.pok.ibm.com (d01av02.pok.ibm.com [9.56.224.216]) by d01relay01.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p8O1XFca217904; Fri, 23 Sep 2011 21:33:15 -0400 Received: from d01av02.pok.ibm.com (loopback [127.0.0.1]) by d01av02.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p8O1XFog021212; Fri, 23 Sep 2011 22:33:15 -0300 Received: from kernel.beaverton.ibm.com ([9.47.67.96]) by d01av02.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p8O1XE0P021197; Fri, 23 Sep 2011 22:33:15 -0300 Received: by kernel.beaverton.ibm.com (Postfix, from userid 1056) id EACAD1E7514; Fri, 23 Sep 2011 18:33:13 -0700 (PDT) From: John Stultz To: markgross@thegnar.org Cc: John Stultz Subject: [PATCH 5/6] [RFC] alarmtimer: Add pm_stay_awake /pm_relax calls Date: Fri, 23 Sep 2011 18:32:42 -0700 Message-Id: <1316827963-13122-6-git-send-email-john.stultz@linaro.org> X-Mailer: git-send-email 1.7.3.2.146.gca209 In-Reply-To: <1316827963-13122-1-git-send-email-john.stultz@linaro.org> References: <1316827963-13122-1-git-send-email-john.stultz@linaro.org> This provides wakelock like chaining to protects the RTC wakeup path to the hrtimer firing of the alarmtimer. NOTE: This doesn't handle the fact that normal hrtimer interrupts that would trigger alarm timers don't cause wakeups. That path still needs to be protected. Signed-off-by: John Stultz --- kernel/time/alarmtimer.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 40 insertions(+), 2 deletions(-) diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index ea5e1a9..523a123 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -46,12 +46,17 @@ static struct alarm_base { static ktime_t freezer_delta; static DEFINE_SPINLOCK(freezer_delta_lock); + #ifdef CONFIG_RTC_CLASS /* rtc timer and device for setting alarm wakeups at suspend */ static struct rtc_timer rtctimer; static struct rtc_device *rtcdev; static DEFINE_SPINLOCK(rtcdev_lock); +static struct wakeup_source *alarmtimer_wakelock; +static int stay_awake; +static DEFINE_SPINLOCK(stay_awake_lock); + /** * has_wakealarm - check rtc device has wakealarm ability * @dev: current device @@ -73,6 +78,20 @@ static int has_wakealarm(struct device *dev, void *name_ptr) return 1; } +/* rtctimer function called by first rtc interrupt after suspend */ +void alarmtimer_resume_call(void* p) +{ + unsigned long flags; + + spin_lock_irqsave(&stay_awake_lock, flags); + if (stay_awake == 1) { + printk("alarmtimer_resume: Calling stayawake!\n"); + stay_awake = 2; + __pm_stay_awake(alarmtimer_wakelock); + } + spin_unlock_irqrestore(&stay_awake_lock, flags); +} + /** * alarmtimer_get_rtcdev - Return selected rtcdevice * @@ -99,7 +118,7 @@ static struct rtc_device *alarmtimer_get_rtcdev(void) * rtc_open takes its own. */ put_device(dev); - rtc_timer_init(&rtctimer, NULL, NULL); + rtc_timer_init(&rtctimer, alarmtimer_resume_call, NULL); } } ret = rtcdev; @@ -158,6 +177,8 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) } + + /** * alarmtimer_fired - Handles alarm hrtimer being fired. * @timer: pointer to hrtimer being run @@ -206,6 +227,12 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) } spin_unlock_irqrestore(&base->lock, flags); + spin_lock_irqsave(&stay_awake_lock, flags); + if (stay_awake == 2) + __pm_relax(alarmtimer_wakelock); + stay_awake = 0; + spin_unlock_irqrestore(&stay_awake_lock, flags); + return ret; } @@ -225,12 +252,14 @@ static int alarmtimer_suspend(struct device *dev) { struct rtc_time tm; ktime_t min, now; + int min_base; unsigned long flags; struct rtc_device *rtc; int i; spin_lock_irqsave(&freezer_delta_lock, flags); min = freezer_delta; + min_base = 0; freezer_delta = ktime_set(0, 0); spin_unlock_irqrestore(&freezer_delta_lock, flags); @@ -251,8 +280,10 @@ static int alarmtimer_suspend(struct device *dev) if (!next) continue; delta = ktime_sub(next->expires, base->gettime()); - if (!min.tv64 || (delta.tv64 < min.tv64)) + if (!min.tv64 || (delta.tv64 < min.tv64)) { min = delta; + min_base = i; + } } if (min.tv64 == 0) return 0; @@ -266,6 +297,10 @@ static int alarmtimer_suspend(struct device *dev) now = rtc_tm_to_ktime(tm); now = ktime_add(now, min); + spin_lock_irqsave(&stay_awake_lock, flags); + stay_awake=1; + spin_unlock_irqrestore(&stay_awake_lock, flags); + rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); return 0; @@ -703,6 +738,9 @@ static int __init alarmtimer_init(void) .nsleep = alarm_timer_nsleep, }; + alarmtimer_wakelock = wakeup_source_register("alarmtimer"); + stay_awake=0; + posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock); posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);