aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/idle.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/idle.c')
-rw-r--r--arch/s390/kernel/idle.c29
1 files changed, 15 insertions, 14 deletions
diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c
index 7559f1beab29..7a55c29b0b33 100644
--- a/arch/s390/kernel/idle.c
+++ b/arch/s390/kernel/idle.c
@@ -19,7 +19,7 @@
19 19
20static DEFINE_PER_CPU(struct s390_idle_data, s390_idle); 20static DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
21 21
22void __kprobes enabled_wait(void) 22void enabled_wait(void)
23{ 23{
24 struct s390_idle_data *idle = this_cpu_ptr(&s390_idle); 24 struct s390_idle_data *idle = this_cpu_ptr(&s390_idle);
25 unsigned long long idle_time; 25 unsigned long long idle_time;
@@ -35,31 +35,32 @@ void __kprobes enabled_wait(void)
35 /* Call the assembler magic in entry.S */ 35 /* Call the assembler magic in entry.S */
36 psw_idle(idle, psw_mask); 36 psw_idle(idle, psw_mask);
37 37
38 trace_hardirqs_off();
39
38 /* Account time spent with enabled wait psw loaded as idle time. */ 40 /* Account time spent with enabled wait psw loaded as idle time. */
39 idle->sequence++; 41 write_seqcount_begin(&idle->seqcount);
40 smp_wmb();
41 idle_time = idle->clock_idle_exit - idle->clock_idle_enter; 42 idle_time = idle->clock_idle_exit - idle->clock_idle_enter;
42 idle->clock_idle_enter = idle->clock_idle_exit = 0ULL; 43 idle->clock_idle_enter = idle->clock_idle_exit = 0ULL;
43 idle->idle_time += idle_time; 44 idle->idle_time += idle_time;
44 idle->idle_count++; 45 idle->idle_count++;
45 account_idle_time(idle_time); 46 account_idle_time(idle_time);
46 smp_wmb(); 47 write_seqcount_end(&idle->seqcount);
47 idle->sequence++;
48} 48}
49NOKPROBE_SYMBOL(enabled_wait);
49 50
50static ssize_t show_idle_count(struct device *dev, 51static ssize_t show_idle_count(struct device *dev,
51 struct device_attribute *attr, char *buf) 52 struct device_attribute *attr, char *buf)
52{ 53{
53 struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); 54 struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
54 unsigned long long idle_count; 55 unsigned long long idle_count;
55 unsigned int sequence; 56 unsigned int seq;
56 57
57 do { 58 do {
58 sequence = ACCESS_ONCE(idle->sequence); 59 seq = read_seqcount_begin(&idle->seqcount);
59 idle_count = ACCESS_ONCE(idle->idle_count); 60 idle_count = ACCESS_ONCE(idle->idle_count);
60 if (ACCESS_ONCE(idle->clock_idle_enter)) 61 if (ACCESS_ONCE(idle->clock_idle_enter))
61 idle_count++; 62 idle_count++;
62 } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); 63 } while (read_seqcount_retry(&idle->seqcount, seq));
63 return sprintf(buf, "%llu\n", idle_count); 64 return sprintf(buf, "%llu\n", idle_count);
64} 65}
65DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); 66DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -69,15 +70,15 @@ static ssize_t show_idle_time(struct device *dev,
69{ 70{
70 struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); 71 struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
71 unsigned long long now, idle_time, idle_enter, idle_exit; 72 unsigned long long now, idle_time, idle_enter, idle_exit;
72 unsigned int sequence; 73 unsigned int seq;
73 74
74 do { 75 do {
75 now = get_tod_clock(); 76 now = get_tod_clock();
76 sequence = ACCESS_ONCE(idle->sequence); 77 seq = read_seqcount_begin(&idle->seqcount);
77 idle_time = ACCESS_ONCE(idle->idle_time); 78 idle_time = ACCESS_ONCE(idle->idle_time);
78 idle_enter = ACCESS_ONCE(idle->clock_idle_enter); 79 idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
79 idle_exit = ACCESS_ONCE(idle->clock_idle_exit); 80 idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
80 } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); 81 } while (read_seqcount_retry(&idle->seqcount, seq));
81 idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0; 82 idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
82 return sprintf(buf, "%llu\n", idle_time >> 12); 83 return sprintf(buf, "%llu\n", idle_time >> 12);
83} 84}
@@ -87,14 +88,14 @@ cputime64_t arch_cpu_idle_time(int cpu)
87{ 88{
88 struct s390_idle_data *idle = &per_cpu(s390_idle, cpu); 89 struct s390_idle_data *idle = &per_cpu(s390_idle, cpu);
89 unsigned long long now, idle_enter, idle_exit; 90 unsigned long long now, idle_enter, idle_exit;
90 unsigned int sequence; 91 unsigned int seq;
91 92
92 do { 93 do {
93 now = get_tod_clock(); 94 now = get_tod_clock();
94 sequence = ACCESS_ONCE(idle->sequence); 95 seq = read_seqcount_begin(&idle->seqcount);
95 idle_enter = ACCESS_ONCE(idle->clock_idle_enter); 96 idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
96 idle_exit = ACCESS_ONCE(idle->clock_idle_exit); 97 idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
97 } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); 98 } while (read_seqcount_retry(&idle->seqcount, seq));
98 return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0; 99 return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
99} 100}
100 101