summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBibek Basu <bbasu@nvidia.com>2015-01-27 17:10:15 +0530
committerWinnie Hsu <whsu@nvidia.com>2015-01-29 21:47:30 -0800
commit097e6ff87a8450a0040091d7a69e9894611df6e6 (patch)
treebdce4af6865af47244e182016ef4dcd02efb8c9a
parente0de594224b867533b58b2106a98448a6f36df91 (diff)
rtc: add rtc_shutdown api to service pending work
During shutdown/reboot process, its better to finish any pending irqwork so that the work is not scheduled after devices like i2c are shutdown. This patch provides hook to be called from rtc driver after disabling rtc irq. Also any further request to access rtc_class_ops will be prohibited. Bug 200072946 Change-Id: I8eb20e5214a31fbc8a280ccfff8e190a5fabbb96 Signed-off-by: Bibek Basu <bbasu@nvidia.com> Reviewed-on: http://git-master/r/677750 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Venkat Moganty <vmoganty@nvidia.com> Reviewed-by: Matthew Pedro <mapedro@nvidia.com>
-rw-r--r--drivers/rtc/class.c14
-rw-r--r--drivers/rtc/interface.c25
-rw-r--r--include/linux/rtc.h3
3 files changed, 40 insertions, 2 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 66385402d20e..2f6466d69e3d 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -2,6 +2,7 @@
* RTC subsystem, base class
*
* Copyright (C) 2005 Tower Technologies
+ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
* Author: Alessandro Zummo <a.zummo@towertech.it>
*
* class skeleton from drivers/hwmon/hwmon.c
@@ -178,6 +179,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
rtc->dev.parent = dev;
rtc->dev.class = rtc_class;
rtc->dev.release = rtc_device_release;
+ rtc->system_shutting = false;
mutex_init(&rtc->ops_lock);
spin_lock_init(&rtc->irq_lock);
@@ -259,6 +261,18 @@ void rtc_device_unregister(struct rtc_device *rtc)
}
EXPORT_SYMBOL_GPL(rtc_device_unregister);
+/**
+ * rtc_device_shutdown - flush any pending irq workqueue
+ *
+ * @rtc: the RTC class device to cancel pending work
+ */
+void rtc_device_shutdown(struct rtc_device *rtc)
+{
+ cancel_work_sync(&rtc->irqwork);
+ rtc->system_shutting = true;
+}
+EXPORT_SYMBOL_GPL(rtc_device_shutdown);
+
static void devm_rtc_device_release(struct device *dev, void *res)
{
struct rtc_device *rtc = *(struct rtc_device **)res;
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 42bd57da239d..37059d8ead10 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -2,6 +2,7 @@
* RTC subsystem, interface functions
*
* Copyright (C) 2005 Tower Technologies
+ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
* Author: Alessandro Zummo <a.zummo@towertech.it>
*
* based on arch/arm/common/rtctime.c
@@ -38,6 +39,8 @@ int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
{
int err;
+ if (unlikely(rtc->system_shutting))
+ return -ESHUTDOWN;
err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;
@@ -52,6 +55,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
{
int err;
+ if (unlikely(rtc->system_shutting))
+ return -ESHUTDOWN;
err = rtc_valid_tm(tm);
if (err != 0)
return err;
@@ -83,6 +88,8 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
{
int err;
+ if (unlikely(rtc->system_shutting))
+ return -ESHUTDOWN;
err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;
@@ -125,6 +132,8 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al
{
int err;
+ if (unlikely(rtc->system_shutting))
+ return -ESHUTDOWN;
err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;
@@ -305,6 +314,8 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
int err;
+ if (unlikely(rtc->system_shutting))
+ return -ESHUTDOWN;
err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;
@@ -360,6 +371,8 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
int err;
+ if (unlikely(rtc->system_shutting))
+ return -ESHUTDOWN;
err = rtc_valid_tm(&alarm->time);
if (err != 0)
return err;
@@ -417,7 +430,11 @@ EXPORT_SYMBOL_GPL(rtc_initialize_alarm);
int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
{
- int err = mutex_lock_interruptible(&rtc->ops_lock);
+ int err;
+
+ if (unlikely(rtc->system_shutting))
+ return -ESHUTDOWN;
+ err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;
@@ -444,7 +461,11 @@ EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);
int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
{
- int err = mutex_lock_interruptible(&rtc->ops_lock);
+ int err;
+
+ if (unlikely(rtc->system_shutting))
+ return -ESHUTDOWN;
+ err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index b608a6f392e1..871aec66ab9e 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -7,6 +7,7 @@
*
* Copyright (C) 1999 Hewlett-Packard Co.
* Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef _LINUX_RTC_H_
#define _LINUX_RTC_H_
@@ -115,6 +116,7 @@ struct rtc_device
struct work_struct irqwork;
/* Some hardware can't support UIE mode */
int uie_unsupported;
+ bool system_shutting;
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
struct work_struct uie_task;
@@ -140,6 +142,7 @@ extern struct rtc_device *devm_rtc_device_register(struct device *dev,
extern void rtc_device_unregister(struct rtc_device *rtc);
extern void devm_rtc_device_unregister(struct device *dev,
struct rtc_device *rtc);
+void rtc_device_shutdown(struct rtc_device *rtc);
extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);