diff options
Diffstat (limited to 'arch/s390/kernel/idle.c')
-rw-r--r-- | arch/s390/kernel/idle.c | 29 |
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 | ||
20 | static DEFINE_PER_CPU(struct s390_idle_data, s390_idle); | 20 | static DEFINE_PER_CPU(struct s390_idle_data, s390_idle); |
21 | 21 | ||
22 | void __kprobes enabled_wait(void) | 22 | void 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 | } |
49 | NOKPROBE_SYMBOL(enabled_wait); | ||
49 | 50 | ||
50 | static ssize_t show_idle_count(struct device *dev, | 51 | static 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 | } |
65 | DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); | 66 | DEVICE_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 | ||