1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: stp/etr: smp_call_function races.
5 Symptom: System hangs when setting stp/etr online.
6 Problem: The stp/etr code uses smp_call_function() with blocking
7 function on the signalled cpus. This is prone to cause
9 Solution: Replace the smp_call_function() synchronization with one
10 based on stop_machine_run.
12 Acked-by: John Jolly <jjolly@suse.de>
14 arch/s390/kernel/time.c | 210 +++++++++++++++++++++++++++++-------------------
15 1 file changed, 130 insertions(+), 80 deletions(-)
17 Index: linux-2.6.27/arch/s390/kernel/time.c
18 ===================================================================
19 --- linux-2.6.27.orig/arch/s390/kernel/time.c
20 +++ linux-2.6.27/arch/s390/kernel/time.c
22 #include <linux/string.h>
24 #include <linux/interrupt.h>
25 +#include <linux/cpu.h>
26 +#include <linux/stop_machine.h>
27 #include <linux/time.h>
28 #include <linux/sysdev.h>
29 #include <linux/delay.h>
30 @@ -365,6 +367,15 @@ static void enable_sync_clock(void)
31 atomic_set_mask(0x80000000, sw_ptr);
34 +/* Single threaded workqueue used for etr and stp sync events */
35 +static struct workqueue_struct *time_sync_wq;
37 +static void __init time_init_wq(void)
40 + time_sync_wq = create_singlethread_workqueue("timesync");
44 * External Time Reference (ETR) code.
46 @@ -457,17 +468,18 @@ static int __init etr_init(void)
48 if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags))
51 /* Check if this machine has the steai instruction. */
52 if (etr_steai(&aib, ETR_STEAI_STEPPING_PORT) == 0)
53 etr_steai_available = 1;
54 setup_timer(&etr_timer, etr_timeout, 0UL);
55 if (etr_port0_online) {
56 set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
57 - schedule_work(&etr_work);
58 + queue_work(time_sync_wq, &etr_work);
60 if (etr_port1_online) {
61 set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
62 - schedule_work(&etr_work);
63 + queue_work(time_sync_wq, &etr_work);
67 @@ -494,7 +506,7 @@ void etr_switch_to_local(void)
68 if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
69 disable_sync_clock(NULL);
70 set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
71 - schedule_work(&etr_work);
72 + queue_work(time_sync_wq, &etr_work);
76 @@ -510,7 +522,7 @@ void etr_sync_check(void)
77 if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
78 disable_sync_clock(NULL);
79 set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
80 - schedule_work(&etr_work);
81 + queue_work(time_sync_wq, &etr_work);
85 @@ -534,13 +546,13 @@ static void etr_timing_alert(struct etr_
86 * Both ports are not up-to-date now.
88 set_bit(ETR_EVENT_PORT_ALERT, &etr_events);
89 - schedule_work(&etr_work);
90 + queue_work(time_sync_wq, &etr_work);
93 static void etr_timeout(unsigned long dummy)
95 set_bit(ETR_EVENT_UPDATE, &etr_events);
96 - schedule_work(&etr_work);
97 + queue_work(time_sync_wq, &etr_work);
101 @@ -647,14 +659,16 @@ static int etr_aib_follows(struct etr_ai
104 struct clock_sync_data {
107 unsigned long long fixup_cc;
109 + struct etr_aib *etr_aib;
112 -static void clock_sync_cpu_start(void *dummy)
113 +static void clock_sync_cpu(struct clock_sync_data *sync)
115 - struct clock_sync_data *sync = dummy;
117 + atomic_dec(&sync->cpus);
120 * This looks like a busy wait loop but it isn't. etr_sync_cpus
121 @@ -680,39 +694,35 @@ static void clock_sync_cpu_start(void *d
122 fixup_clock_comparator(sync->fixup_cc);
125 -static void clock_sync_cpu_end(void *dummy)
130 * Sync the TOD clock using the port refered to by aibp. This port
131 * has to be enabled and the other port has to be disabled. The
132 * last eacr update has to be more than 1.6 seconds in the past.
134 -static int etr_sync_clock(struct etr_aib *aib, int port)
135 +static int etr_sync_clock(void *data)
137 - struct etr_aib *sync_port;
138 - struct clock_sync_data etr_sync;
140 unsigned long long clock, old_clock, delay, delta;
142 + struct clock_sync_data *etr_sync;
143 + struct etr_aib *sync_port, *aib;
147 - /* Check if the current aib is adjacent to the sync port aib. */
148 - sync_port = (port == 0) ? &etr_port0 : &etr_port1;
149 - follows = etr_aib_follows(sync_port, aib, port);
150 - memcpy(sync_port, aib, sizeof(*aib));
156 - * Catch all other cpus and make them wait until we have
157 - * successfully synced the clock. smp_call_function will
158 - * return after all other cpus are in etr_sync_cpu_start.
160 - memset(&etr_sync, 0, sizeof(etr_sync));
162 - smp_call_function(clock_sync_cpu_start, &etr_sync, 0);
163 - local_irq_disable();
164 + if (xchg(&first, 1) == 1) {
166 + clock_sync_cpu(etr_sync);
170 + /* Wait until all other cpus entered the sync function. */
171 + while (atomic_read(&etr_sync->cpus) != 0)
174 + port = etr_sync->etr_port;
175 + aib = etr_sync->etr_aib;
176 + sync_port = (port == 0) ? &etr_port0 : &etr_port1;
179 /* Set clock to next OTE. */
180 @@ -729,16 +739,16 @@ static int etr_sync_clock(struct etr_aib
181 delay = (unsigned long long)
182 (aib->edf2.etv - sync_port->edf2.etv) << 32;
183 delta = adjust_time(old_clock, clock, delay);
184 - etr_sync.fixup_cc = delta;
185 + etr_sync->fixup_cc = delta;
186 fixup_clock_comparator(delta);
187 /* Verify that the clock is properly set. */
188 if (!etr_aib_follows(sync_port, aib, port)) {
190 disable_sync_clock(NULL);
191 - etr_sync.in_sync = -EAGAIN;
192 + etr_sync->in_sync = -EAGAIN;
195 - etr_sync.in_sync = 1;
196 + etr_sync->in_sync = 1;
200 @@ -746,12 +756,33 @@ static int etr_sync_clock(struct etr_aib
201 __ctl_clear_bit(0, 29);
202 __ctl_clear_bit(14, 21);
203 disable_sync_clock(NULL);
204 - etr_sync.in_sync = -EAGAIN;
205 + etr_sync->in_sync = -EAGAIN;
208 - local_irq_enable();
209 - smp_call_function(clock_sync_cpu_end, NULL, 0);
215 +static int etr_sync_clock_stop(struct etr_aib *aib, int port)
217 + struct clock_sync_data etr_sync;
218 + struct etr_aib *sync_port;
222 + /* Check if the current aib is adjacent to the sync port aib. */
223 + sync_port = (port == 0) ? &etr_port0 : &etr_port1;
224 + follows = etr_aib_follows(sync_port, aib, port);
225 + memcpy(sync_port, aib, sizeof(*aib));
228 + memset(&etr_sync, 0, sizeof(etr_sync));
229 + etr_sync.etr_aib = aib;
230 + etr_sync.etr_port = port;
232 + atomic_set(&etr_sync.cpus, num_online_cpus() - 1);
233 + rc = stop_machine(etr_sync_clock, &etr_sync, &cpu_online_map);
238 @@ -908,7 +939,7 @@ static void etr_update_eacr(struct etr_e
242 - * ETR tasklet. In this function you'll find the main logic. In
243 + * ETR work. In this function you'll find the main logic. In
244 * particular this is the only function that calls etr_update_eacr(),
245 * it "controls" the etr control register.
247 @@ -1041,7 +1072,7 @@ static void etr_work_fn(struct work_stru
248 etr_update_eacr(eacr);
249 set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
250 if (now < etr_tolec + (1600000 << 12) ||
251 - etr_sync_clock(&aib, sync_port) != 0) {
252 + etr_sync_clock_stop(&aib, sync_port) != 0) {
253 /* Sync failed. Try again in 1/2 second. */
255 etr_update_eacr(eacr);
256 @@ -1130,13 +1161,13 @@ static ssize_t etr_online_store(struct s
257 return count; /* Nothing to do. */
258 etr_port0_online = value;
259 set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
260 - schedule_work(&etr_work);
261 + queue_work(time_sync_wq, &etr_work);
263 if (etr_port1_online == value)
264 return count; /* Nothing to do. */
265 etr_port1_online = value;
266 set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
267 - schedule_work(&etr_work);
268 + queue_work(time_sync_wq, &etr_work);
272 @@ -1371,8 +1402,12 @@ static void __init stp_reset(void)
274 static int __init stp_init(void)
276 - if (test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags) && stp_online)
277 - schedule_work(&stp_work);
278 + if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
283 + queue_work(time_sync_wq, &stp_work);
287 @@ -1389,7 +1424,7 @@ arch_initcall(stp_init);
288 static void stp_timing_alert(struct stp_irq_parm *intparm)
290 if (intparm->tsc || intparm->lac || intparm->tcpc)
291 - schedule_work(&stp_work);
292 + queue_work(time_sync_wq, &stp_work);
296 @@ -1417,46 +1452,34 @@ void stp_island_check(void)
297 if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
299 disable_sync_clock(NULL);
300 - schedule_work(&stp_work);
301 + queue_work(time_sync_wq, &stp_work);
305 - * STP tasklet. Check for the STP state and take over the clock
306 - * synchronization if the STP clock source is usable.
308 -static void stp_work_fn(struct work_struct *work)
310 +static int stp_sync_clock(void *data)
312 - struct clock_sync_data stp_sync;
314 unsigned long long old_clock, delta;
315 + struct clock_sync_data *stp_sync;
319 - chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
324 - rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0xb0e0);
327 + if (xchg(&first, 1) == 1) {
329 + clock_sync_cpu(stp_sync);
333 - rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
334 - if (rc || stp_info.c == 0)
336 + /* Wait until all other cpus entered the sync function. */
337 + while (atomic_read(&stp_sync->cpus) != 0)
341 - * Catch all other cpus and make them wait until we have
342 - * successfully synced the clock. smp_call_function will
343 - * return after all other cpus are in clock_sync_cpu_start.
345 - memset(&stp_sync, 0, sizeof(stp_sync));
347 - smp_call_function(clock_sync_cpu_start, &stp_sync, 0);
348 - local_irq_disable();
351 set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
352 if (test_and_clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
353 - schedule_work(&etr_work);
354 + queue_work(time_sync_wq, &etr_work);
357 if (stp_info.todoff[0] || stp_info.todoff[1] ||
358 @@ -1475,16 +1498,43 @@ static void stp_work_fn(struct work_stru
361 disable_sync_clock(NULL);
362 - stp_sync.in_sync = -EAGAIN;
363 + stp_sync->in_sync = -EAGAIN;
364 clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
365 if (etr_port0_online || etr_port1_online)
366 - schedule_work(&etr_work);
367 + queue_work(time_sync_wq, &etr_work);
369 - stp_sync.in_sync = 1;
370 + stp_sync->in_sync = 1;
375 - local_irq_enable();
376 - smp_call_function(clock_sync_cpu_end, NULL, 0);
379 + * STP work. Check for the STP state and take over the clock
380 + * synchronization if the STP clock source is usable.
382 +static void stp_work_fn(struct work_struct *work)
384 + struct clock_sync_data stp_sync;
388 + chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
392 + rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0xb0e0);
396 + rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
397 + if (rc || stp_info.c == 0)
400 + memset(&stp_sync, 0, sizeof(stp_sync));
402 + atomic_set(&stp_sync.cpus, num_online_cpus() - 1);
403 + stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map);
408 @@ -1593,7 +1643,7 @@ static ssize_t stp_online_store(struct s
409 if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
412 - schedule_work(&stp_work);
413 + queue_work(time_sync_wq, &stp_work);