s390 uses open coded seqcount to synchronize idle time accounting.
Lets consolidate it with the standard API.

Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Heiko Carstens <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Martin Schwidefsky <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Rik van Riel <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Wu Fengguang <[email protected]>
Signed-off-by: Frederic Weisbecker <[email protected]>
---
 arch/s390/include/asm/idle.h |  3 ++-
 arch/s390/kernel/idle.c      | 28 +++++++++++++++-------------
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/arch/s390/include/asm/idle.h b/arch/s390/include/asm/idle.h
index 6af037f..113cd96 100644
--- a/arch/s390/include/asm/idle.h
+++ b/arch/s390/include/asm/idle.h
@@ -9,9 +9,10 @@
 
 #include <linux/types.h>
 #include <linux/device.h>
+#include <linux/seqlock.h>
 
 struct s390_idle_data {
-       unsigned int sequence;
+       seqcount_t seqcount;
        unsigned long long idle_count;
        unsigned long long idle_time;
        unsigned long long clock_idle_enter;
diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c
index 7559f1b..9b75577 100644
--- a/arch/s390/kernel/idle.c
+++ b/arch/s390/kernel/idle.c
@@ -36,15 +36,13 @@ void __kprobes enabled_wait(void)
        psw_idle(idle, psw_mask);
 
        /* Account time spent with enabled wait psw loaded as idle time. */
-       idle->sequence++;
-       smp_wmb();
+       write_seqcount_begin(&idle->seqcount);
        idle_time = idle->clock_idle_exit - idle->clock_idle_enter;
        idle->clock_idle_enter = idle->clock_idle_exit = 0ULL;
        idle->idle_time += idle_time;
        idle->idle_count++;
        account_idle_time(idle_time);
-       smp_wmb();
-       idle->sequence++;
+       write_seqcount_end(&idle->seqcount);
 }
 
 static ssize_t show_idle_count(struct device *dev,
@@ -52,14 +50,15 @@ static ssize_t show_idle_count(struct device *dev,
 {
        struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
        unsigned long long idle_count;
-       unsigned int sequence;
+       unsigned int seq;
 
        do {
-               sequence = ACCESS_ONCE(idle->sequence);
+               seq = read_seqcount_begin(&idle->seqcount);
                idle_count = ACCESS_ONCE(idle->idle_count);
                if (ACCESS_ONCE(idle->clock_idle_enter))
                        idle_count++;
-       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
+       } while (read_seqcount_retry(&idle->seqcount, seq));
+
        return sprintf(buf, "%llu\n", idle_count);
 }
 DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -69,16 +68,18 @@ static ssize_t show_idle_time(struct device *dev,
 {
        struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
        unsigned long long now, idle_time, idle_enter, idle_exit;
-       unsigned int sequence;
+       unsigned int seq;
 
        do {
                now = get_tod_clock();
-               sequence = ACCESS_ONCE(idle->sequence);
+               seq = read_seqcount_begin(&idle->seqcount);
                idle_time = ACCESS_ONCE(idle->idle_time);
                idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
                idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
-       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
+       } while (read_seqcount_retry(&idle->seqcount, seq));
+
        idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
+
        return sprintf(buf, "%llu\n", idle_time >> 12);
 }
 DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
@@ -87,14 +88,15 @@ cputime64_t arch_cpu_idle_time(int cpu)
 {
        struct s390_idle_data *idle = &per_cpu(s390_idle, cpu);
        unsigned long long now, idle_enter, idle_exit;
-       unsigned int sequence;
+       unsigned int seq;
 
        do {
                now = get_tod_clock();
-               sequence = ACCESS_ONCE(idle->sequence);
+               seq = read_seqcount_begin(&idle->seqcount);
                idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
                idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
-       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
+       } while (read_seqcount_retry(&idle->seqcount, seq));
+
        return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
 }
 
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to