]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
rtc: add rtc_shutdown api to service pending work
authorBibek Basu <bbasu@nvidia.com>
Tue, 27 Jan 2015 11:40:15 +0000 (17:10 +0530)
committerLaxman Dewangan <ldewangan@nvidia.com>
Wed, 28 Jan 2015 18:05:36 +0000 (10:05 -0800)
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/677758
GVS: Gerrit_Virtual_Submit
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
drivers/rtc/class.c
drivers/rtc/interface.c
include/linux/rtc.h

index 66385402d20ebf52672a2fa2eab03cbe4b59eedc..bb2f9aa20bff45585795e869b96baffb3010737d 100644 (file)
@@ -178,6 +178,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 +260,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;
index 42bd57da239de73a05c79c2f11ac129092aa9a19..e1cb5b220806493e27e4861105fa32aa2fc5bf4a 100644 (file)
@@ -38,6 +38,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 +54,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 +87,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 +131,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 +313,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 +370,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 +429,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 +460,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;
 
index b608a6f392e1db2706bc5d1477a0bb3398e0b775..4eb328cef8e9a3e9c315a2601c6ac02c7bac1ead 100644 (file)
@@ -115,6 +115,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 +141,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);