From: John Jacques <[email protected]>

Add a kernel command line option to force the use of acpi_pm as the
watchdog clocksource. To use it, add the following to the
kernel command line:

     ricardo_clocksource_wd=force_acpi_pm_wd

and in dmesg look for:

     RICARDO: Force acpi_pm as watchdog

Also, add a debugfs entry to inspect the current clocksource watchdog
and the history watchdoug sources. The file is

/sys/kernel/debug/ricardo_clocksource/watchdog_info

It look like something like:

CURRENT: acpi_pm
HISTORY:
apci-pm

Signed-off-by: Ricardo Neri <[email protected]>
Signed-off-by: John Jacques <[email protected]>
[YL: Original patch from
https://github.com/intel-collab/networking.wireless.transport.rdk.board-support.meta-intel-axxia.git.]
Signed-off-by: Yongxin Liu <[email protected]>
---
 kernel/time/clocksource.c | 82 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 80 insertions(+), 2 deletions(-)

diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 3052b1f1168e..fb89243cb6d6 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -16,7 +16,7 @@
 #include <linux/kthread.h>
 #include <linux/prandom.h>
 #include <linux/cpu.h>
-
+#include <linux/debugfs.h>
 #include "tick-internal.h"
 #include "timekeeping_internal.h"
 
@@ -398,6 +398,58 @@ static inline void clocksource_reset_watchdog(void)
 }
 
 
+#define RICARDO_WD_HISTORY_SIZE 1024
+static bool force_acpi_pm_wd;
+static char ricardo_watchdog_history[RICARDO_WD_HISTORY_SIZE];
+
+static void ricardo_append_wd_select(const char *name)
+{
+       static bool buff_full = false;
+       static unsigned buff_pos = 0;
+       unsigned int len;
+
+       if (buff_full)
+               return;
+
+       if (!name)
+               return;
+
+       if (!buff_pos)
+               memset(ricardo_watchdog_history, '\0', RICARDO_WD_HISTORY_SIZE 
* sizeof(char));
+
+       len = strlen(name);
+
+       if ((buff_pos + len) > (RICARDO_WD_HISTORY_SIZE - 6)) {
+               memcpy(ricardo_watchdog_history + buff_pos, "FULL\n", 6);
+               buff_full = true;
+               return;
+       }
+
+       memcpy(ricardo_watchdog_history + buff_pos, name, len);
+       buff_pos += len;
+       memcpy(ricardo_watchdog_history + buff_pos, "\n", 1);
+       buff_pos ++;
+}
+
+static int ricardo_watchdog_name_show(struct seq_file *m, void *data)
+{
+       seq_printf(m, "CURRENT: %s\n", watchdog ? watchdog->name : "none");
+       seq_printf(m, "HISTORY: \n%s\n", ricardo_watchdog_history);
+       return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(ricardo_watchdog_name);
+
+static int __init ricardo_override_cs_watchdog(char *str)
+{
+       if (!strcmp(str, "force_acpi_pm_wd")) {
+               printk(KERN_ERR "RICARDO: Force acpi_pm as watchdog\n");
+               force_acpi_pm_wd = true;
+       }
+       return 1;
+}
+early_param("ricardo_clocksource_wd", ricardo_override_cs_watchdog);
+
 static void clocksource_watchdog(struct timer_list *unused)
 {
        u64 csnow, wdnow, cslast, wdlast, delta;
@@ -642,13 +694,23 @@ static void clocksource_select_watchdog(bool fallback)
                if (!watchdog || cs->rating > watchdog->rating)
                        watchdog = cs;
        }
+
        /* If we failed to find a fallback restore the old one. */
        if (!watchdog)
                watchdog = old_wd;
 
+       /*
+        * If selected watchdog is not old_wd, replace with old one. It
+        * will be NULL if not watchdog has been selected
+        */
+       if (force_acpi_pm_wd && strcmp(watchdog->name, "acpi_pm"))
+               watchdog = old_wd;
+
        /* If we changed the watchdog we need to reset cycles. */
-       if (watchdog != old_wd)
+       if (watchdog != old_wd) {
                clocksource_reset_watchdog();
+               ricardo_append_wd_select(watchdog->name);
+       }
 
        /* Check if the watchdog timer needs to be started. */
        clocksource_start_watchdog();
@@ -1077,6 +1139,12 @@ static void clocksource_select_fallback(void)
  */
 static int __init clocksource_done_booting(void)
 {
+       /*
+        * static variable to ensure debugfs entry is called only once even
+        * if this function is called multiple times (once per SMP core up?)
+        */
+       static bool debugfs_done = false;
+       struct dentry *root;
        mutex_lock(&clocksource_mutex);
        curr_clocksource = clocksource_default_clock();
        finished_booting = 1;
@@ -1086,6 +1154,16 @@ static int __init clocksource_done_booting(void)
        __clocksource_watchdog_kthread();
        clocksource_select();
        mutex_unlock(&clocksource_mutex);
+
+       if (!debugfs_done) {
+               debugfs_done = true;
+               root = debugfs_create_dir("ricardo_clocksource", NULL);
+               if (!root) {
+                       printk(KERN_ERR "RICARDO Unable to create debugfs 
dir\n");
+                       return 0;
+               }
+               debugfs_create_file("watchdog_info", 0444, root, NULL, 
&ricardo_watchdog_name_fops);
+       }
        return 0;
 }
 fs_initcall(clocksource_done_booting);
-- 
2.45.0

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#13975): 
https://lists.yoctoproject.org/g/linux-yocto/message/13975
Mute This Topic: https://lists.yoctoproject.org/mt/106499073/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to