greybus: svc watchdog: Disable watchdog upon entering suspend
authorDavid Lin <dtwlin@google.com>
Fri, 15 Apr 2016 19:45:16 +0000 (01:15 +0530)
committerGreg Kroah-Hartman <gregkh@google.com>
Fri, 15 Apr 2016 21:42:53 +0000 (14:42 -0700)
SVC watchdog should be disabled when device is entering suspend mode.

Testing done:
 - Sanity tested on EVT1.5
 - Check no SVC ping during the suspend process
 - Check SVC watchdog is back on pinging once device is resumed

Signed-off-by: David Lin <dtwlin@google.com>
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
[vaibhav.hiremath@linaro.org: Removed unwanted check in notifier callback and
Updated commit description]
Tested-by: Sandeep Patil <sspatil@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/svc_watchdog.c

index 9bd68f4f4cf7c138ef556fbaeca01480e9d446bc..6cd3bac59852ebe63d25a9e5fc339bff65de71b3 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/suspend.h>
 #include <linux/workqueue.h>
 #include "greybus.h"
 
@@ -16,10 +17,31 @@ struct gb_svc_watchdog {
        struct delayed_work     work;
        struct gb_svc           *svc;
        bool                    enabled;
+       struct notifier_block pm_notifier;
 };
 
 static struct delayed_work reset_work;
 
+static int svc_watchdog_pm_notifier(struct notifier_block *notifier,
+                                   unsigned long pm_event, void *unused)
+{
+       struct gb_svc_watchdog *watchdog =
+               container_of(notifier, struct gb_svc_watchdog, pm_notifier);
+
+       switch (pm_event) {
+       case PM_SUSPEND_PREPARE:
+               gb_svc_watchdog_disable(watchdog->svc);
+               break;
+       case PM_POST_SUSPEND:
+               gb_svc_watchdog_enable(watchdog->svc);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
 static void greybus_reset(struct work_struct *work)
 {
        static char start_path[256] = "/system/bin/start";
@@ -82,6 +104,7 @@ static void do_work(struct work_struct *work)
 int gb_svc_watchdog_create(struct gb_svc *svc)
 {
        struct gb_svc_watchdog *watchdog;
+       int retval;
 
        if (svc->watchdog)
                return 0;
@@ -95,7 +118,27 @@ int gb_svc_watchdog_create(struct gb_svc *svc)
        INIT_DELAYED_WORK(&watchdog->work, do_work);
        svc->watchdog = watchdog;
 
-       return gb_svc_watchdog_enable(svc);
+       watchdog->pm_notifier.notifier_call = svc_watchdog_pm_notifier;
+       retval = register_pm_notifier(&watchdog->pm_notifier);
+       if (retval) {
+               dev_err(&svc->dev, "error registering pm notifier(%d)\n",
+                       retval);
+               goto svc_watchdog_create_err;
+       }
+
+       retval = gb_svc_watchdog_enable(svc);
+       if (retval) {
+               dev_err(&svc->dev, "error enabling watchdog (%d)\n", retval);
+               unregister_pm_notifier(&watchdog->pm_notifier);
+               goto svc_watchdog_create_err;
+       }
+       return retval;
+
+svc_watchdog_create_err:
+       svc->watchdog = NULL;
+       kfree(watchdog);
+
+       return retval;
 }
 
 void gb_svc_watchdog_destroy(struct gb_svc *svc)
@@ -105,6 +148,7 @@ void gb_svc_watchdog_destroy(struct gb_svc *svc)
        if (!watchdog)
                return;
 
+       unregister_pm_notifier(&watchdog->pm_notifier);
        gb_svc_watchdog_disable(svc);
        svc->watchdog = NULL;
        kfree(watchdog);