From patchwork Fri May 8 09:35:06 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Huang Adrian X-Patchwork-Id: 469953 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-pd0-x23b.google.com (mail-pd0-x23b.google.com [IPv6:2607:f8b0:400e:c02::23b]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6A99114012C for ; Fri, 8 May 2015 19:36:16 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.b=JUx+f46b; dkim-atps=neutral Received: by pdjg10 with SMTP id g10sf17447607pdj.0 for ; Fri, 08 May 2015 02:36:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20120806; h=mime-version:from:to:cc:subject:date:message-id:x-original-sender :x-original-authentication-results:reply-to:content-type:precedence :mailing-list:list-id:list-post:list-help:list-archive:sender :list-subscribe:list-unsubscribe; bh=N85sIRpfmkiFIir6ZB3ZRA1HDCnLTzNLq+RME6zoids=; b=JUx+f46baUqPsiW8REzYmOtky3uF8XZt64/SbUTAwDMsjULHVzxzNHNrD7t8SKPmKc XzFr5vulZY7hFlXG42Z7aHGZo/KBTIgB1Mwiv9aiD8EGuWh5VsbWmy9172NyErSilUCN niuOBQN2n0Nd95T2wYrCQQ5w1XEEGRohMLFOJEwzM2pAMNSTwliinAdr9uPOFsJzdxw8 RpJ+ZHd7koYDnjLim0AaMVRIY4wbiwzNloSo+97jg+m2kRY2iAQsj8XoXApoOtBRekGW sgCQvYGRnUdbYR2g0l7a0JYSsUw/KYdF6hvA6euNPgV1udslIU6q3sFZSmfPgY5DxHTa 7gxg== X-Received: by 10.182.230.198 with SMTP id ta6mr20532obc.24.1431077774751; Fri, 08 May 2015 02:36:14 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: rtc-linux@googlegroups.com Received: by 10.182.79.9 with SMTP id f9ls472526obx.7.gmail; Fri, 08 May 2015 02:36:14 -0700 (PDT) X-Received: by 10.182.149.168 with SMTP id ub8mr4513638obb.8.1431077774565; Fri, 08 May 2015 02:36:14 -0700 (PDT) Received: from mail-pd0-x22b.google.com (mail-pd0-x22b.google.com. [2607:f8b0:400e:c02::22b]) by gmr-mx.google.com with ESMTPS id x3si530746pdh.2.2015.05.08.02.36.14 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 08 May 2015 02:36:14 -0700 (PDT) Received-SPF: pass (google.com: domain of adrianhuang0701@gmail.com designates 2607:f8b0:400e:c02::22b as permitted sender) client-ip=2607:f8b0:400e:c02::22b; Received: by mail-pd0-x22b.google.com with SMTP id nk13so74070720pdb.0 for ; Fri, 08 May 2015 02:36:14 -0700 (PDT) X-Received: by 10.68.215.97 with SMTP id oh1mr5063186pbc.88.1431077723537; Fri, 08 May 2015 02:35:23 -0700 (PDT) Received: from localhost.localdomain (218-173-182-161.dynamic.hinet.net. [218.173.182.161]) by mx.google.com with ESMTPSA id yn5sm4606571pac.48.2015.05.08.02.35.20 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 08 May 2015 02:35:22 -0700 (PDT) From: Adrian Huang To: Alessandro Zummo , Alexandre Belloni , rtc-linux@googlegroups.com Cc: Brecht Machiels , Thomas Gleixner , John Stultz , Rabin Vincent , Borislav Petkov , Nagananda Chumbalkar , Adrian Huang , Adrian Huang Subject: [rtc-linux] [RFC PATCH 2/2] rtc: Restore the RTC alarm time to the configured alarm time in BIOS Setup Date: Fri, 8 May 2015 17:35:06 +0800 Message-Id: <1431077706-3560-1-git-send-email-adrianhuang0701@gmail.com> X-Mailer: git-send-email 1.9.1 X-Original-Sender: AdrianHuang0701@gmail.com X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of adrianhuang0701@gmail.com designates 2607:f8b0:400e:c02::22b as permitted sender) smtp.mail=adrianhuang0701@gmail.com; dkim=pass header.i=@gmail.com; dmarc=pass (p=NONE dis=NONE) header.from=gmail.com Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: X-Google-Group-Id: 712029733259 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , Steps to reproduce the problem: 1) Enable RTC wake-up option in BIOS Setup 2) Issue one of these commands in the OS: "poweroff" or "shutdown -h now" 3) System will shut down and then reboot automatically Root-cause of the issue: 1) During the shutdown process, the hwclock utility is used to save the system clock to hardware clock (RTC). 2) The hwclock utility invokes ioctl() with RTC_UIE_ON. The kernel configures the RTC alarm for the periodic interrupt (every 1 second). 3) The hwclock uitlity closes the /dev/rtc0 device, and the kernel disables the RTC alarm irq (AIE bit of Register B) via ioctl() with RTC_UIE_OFF. But, the configured alarm time is the current_time + 1. 4) After the next 1 second is elapsed, the AF (alarm interrupt flag) of Register C is set. 5) The S5 handler in BIOS is invoked to configure alarm registers (enable AIE bit and configure alarm date/time). But, BIOS does not clear the previous interrupt status during alarm configuration. Therefore, "AF=AIE=1" causes the rtc device to trigger an interrupt. 6) So, the machine reboots automatically right after shutdown. This patch restores the configured alarm time (user configures the time in BIOS Setup) to rtc alarm registers. In some circumstances, the time of the rtc alarm registers is the past time because user-space programs (for example: hwclock) may invoke ioctl() with RTC_UIE_ON. In any case, this patch prevents the AF bit from getting set to 1. Note, AF=1 will cause the system to reboot after shut down. Therefore, this patch fixes the issue from occurring. Signed-off-by: Adrian Huang Reviewed-by: Nagananda Chumbalkar --- drivers/rtc/interface.c | 21 +++++++++++++++++++++ drivers/rtc/rtc-dev.c | 1 + include/linux/rtc.h | 1 + 3 files changed, 23 insertions(+) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 166fc60..2fe17da 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -986,4 +986,25 @@ int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer) return ret; } +/* rtc_alarm_restore - Restores the alarm time + * @ rtc: rtc device to be used + * + * Kernel interface to restore the alarm time + */ +int rtc_alarm_restore(struct rtc_device *rtc) +{ + struct rtc_wkalrm aie_alarm; + int err; + /* If someone has configured the AIE timer, do nothing. */ + if (rtc->aie_timer.enabled) + return 0; + + /* Read the alarm date/time from aie_timer. */ + err = rtc_read_alarm(rtc, &aie_alarm); + if (err < 0) + return err; + + return __rtc_set_alarm(rtc, &aie_alarm); +} +EXPORT_SYMBOL_GPL(rtc_alarm_restore); diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 799c34b..a5ea279 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -437,6 +437,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) rtc_dev_ioctl(file, RTC_UIE_OFF, 0); rtc_update_irq_enable(rtc, 0); rtc_irq_set_state(rtc, NULL, 0); + rtc_alarm_restore(rtc); if (rtc->ops->release) rtc->ops->release(rtc->dev.parent); diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 8dcf682..bf945cb 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -188,6 +188,7 @@ 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); +extern int rtc_alarm_restore(struct rtc_device *rtc); void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode); void rtc_aie_update_irq(void *private);