23
23
24
24
#include "smpboot.h"
25
25
26
- enum {
27
- CSD_FLAG_LOCK = 0x01 ,
28
- CSD_FLAG_SYNCHRONOUS = 0x02 ,
29
- };
26
+
27
+ #define CSD_TYPE (_csd ) ((_csd)->flags & CSD_FLAG_TYPE_MASK)
30
28
31
29
struct call_function_data {
32
30
call_single_data_t __percpu * csd ;
@@ -137,15 +135,33 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(call_single_data_t, csd_data);
137
135
138
136
extern void send_call_function_single_ipi (int cpu );
139
137
138
+ void __smp_call_single_queue (int cpu , struct llist_node * node )
139
+ {
140
+ /*
141
+ * The list addition should be visible before sending the IPI
142
+ * handler locks the list to pull the entry off it because of
143
+ * normal cache coherency rules implied by spinlocks.
144
+ *
145
+ * If IPIs can go out of order to the cache coherency protocol
146
+ * in an architecture, sufficient synchronisation should be added
147
+ * to arch code to make it appear to obey cache coherency WRT
148
+ * locking and barrier primitives. Generic code isn't really
149
+ * equipped to do the right thing...
150
+ */
151
+ if (llist_add (node , & per_cpu (call_single_queue , cpu )))
152
+ send_call_function_single_ipi (cpu );
153
+ }
154
+
140
155
/*
141
156
* Insert a previously allocated call_single_data_t element
142
157
* for execution on the given CPU. data must already have
143
158
* ->func, ->info, and ->flags set.
144
159
*/
145
- static int generic_exec_single (int cpu , call_single_data_t * csd ,
146
- smp_call_func_t func , void * info )
160
+ static int generic_exec_single (int cpu , call_single_data_t * csd )
147
161
{
148
162
if (cpu == smp_processor_id ()) {
163
+ smp_call_func_t func = csd -> func ;
164
+ void * info = csd -> info ;
149
165
unsigned long flags ;
150
166
151
167
/*
@@ -159,28 +175,12 @@ static int generic_exec_single(int cpu, call_single_data_t *csd,
159
175
return 0 ;
160
176
}
161
177
162
-
163
178
if ((unsigned )cpu >= nr_cpu_ids || !cpu_online (cpu )) {
164
179
csd_unlock (csd );
165
180
return - ENXIO ;
166
181
}
167
182
168
- csd -> func = func ;
169
- csd -> info = info ;
170
-
171
- /*
172
- * The list addition should be visible before sending the IPI
173
- * handler locks the list to pull the entry off it because of
174
- * normal cache coherency rules implied by spinlocks.
175
- *
176
- * If IPIs can go out of order to the cache coherency protocol
177
- * in an architecture, sufficient synchronisation should be added
178
- * to arch code to make it appear to obey cache coherency WRT
179
- * locking and barrier primitives. Generic code isn't really
180
- * equipped to do the right thing...
181
- */
182
- if (llist_add (& csd -> llist , & per_cpu (call_single_queue , cpu )))
183
- send_call_function_single_ipi (cpu );
183
+ __smp_call_single_queue (cpu , & csd -> llist );
184
184
185
185
return 0 ;
186
186
}
@@ -194,16 +194,10 @@ static int generic_exec_single(int cpu, call_single_data_t *csd,
194
194
void generic_smp_call_function_single_interrupt (void )
195
195
{
196
196
flush_smp_call_function_queue (true);
197
-
198
- /*
199
- * Handle irq works queued remotely by irq_work_queue_on().
200
- * Smp functions above are typically synchronous so they
201
- * better run first since some other CPUs may be busy waiting
202
- * for them.
203
- */
204
- irq_work_run ();
205
197
}
206
198
199
+ extern void irq_work_single (void * );
200
+
207
201
/**
208
202
* flush_smp_call_function_queue - Flush pending smp-call-function callbacks
209
203
*
@@ -241,26 +235,39 @@ static void flush_smp_call_function_queue(bool warn_cpu_offline)
241
235
* We don't have to use the _safe() variant here
242
236
* because we are not invoking the IPI handlers yet.
243
237
*/
244
- llist_for_each_entry (csd , entry , llist )
245
- pr_warn ("IPI callback %pS sent to offline CPU\n" ,
246
- csd -> func );
238
+ llist_for_each_entry (csd , entry , llist ) {
239
+ switch (CSD_TYPE (csd )) {
240
+ case CSD_TYPE_ASYNC :
241
+ case CSD_TYPE_SYNC :
242
+ case CSD_TYPE_IRQ_WORK :
243
+ pr_warn ("IPI callback %pS sent to offline CPU\n" ,
244
+ csd -> func );
245
+ break ;
246
+
247
+ default :
248
+ pr_warn ("IPI callback, unknown type %d, sent to offline CPU\n" ,
249
+ CSD_TYPE (csd ));
250
+ break ;
251
+ }
252
+ }
247
253
}
248
254
249
255
/*
250
256
* First; run all SYNC callbacks, people are waiting for us.
251
257
*/
252
258
prev = NULL ;
253
259
llist_for_each_entry_safe (csd , csd_next , entry , llist ) {
254
- smp_call_func_t func = csd -> func ;
255
- void * info = csd -> info ;
256
-
257
260
/* Do we wait until *after* callback? */
258
- if (csd -> flags & CSD_FLAG_SYNCHRONOUS ) {
261
+ if (CSD_TYPE (csd ) == CSD_TYPE_SYNC ) {
262
+ smp_call_func_t func = csd -> func ;
263
+ void * info = csd -> info ;
264
+
259
265
if (prev ) {
260
266
prev -> next = & csd_next -> llist ;
261
267
} else {
262
268
entry = & csd_next -> llist ;
263
269
}
270
+
264
271
func (info );
265
272
csd_unlock (csd );
266
273
} else {
@@ -272,11 +279,17 @@ static void flush_smp_call_function_queue(bool warn_cpu_offline)
272
279
* Second; run all !SYNC callbacks.
273
280
*/
274
281
llist_for_each_entry_safe (csd , csd_next , entry , llist ) {
275
- smp_call_func_t func = csd -> func ;
276
- void * info = csd -> info ;
282
+ int type = CSD_TYPE (csd );
277
283
278
- csd_unlock (csd );
279
- func (info );
284
+ if (type == CSD_TYPE_ASYNC ) {
285
+ smp_call_func_t func = csd -> func ;
286
+ void * info = csd -> info ;
287
+
288
+ csd_unlock (csd );
289
+ func (info );
290
+ } else if (type == CSD_TYPE_IRQ_WORK ) {
291
+ irq_work_single (csd );
292
+ }
280
293
}
281
294
}
282
295
@@ -305,7 +318,7 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
305
318
{
306
319
call_single_data_t * csd ;
307
320
call_single_data_t csd_stack = {
308
- .flags = CSD_FLAG_LOCK | CSD_FLAG_SYNCHRONOUS ,
321
+ .flags = CSD_FLAG_LOCK | CSD_TYPE_SYNC ,
309
322
};
310
323
int this_cpu ;
311
324
int err ;
@@ -339,7 +352,10 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
339
352
csd_lock (csd );
340
353
}
341
354
342
- err = generic_exec_single (cpu , csd , func , info );
355
+ csd -> func = func ;
356
+ csd -> info = info ;
357
+
358
+ err = generic_exec_single (cpu , csd );
343
359
344
360
if (wait )
345
361
csd_lock_wait (csd );
@@ -385,7 +401,7 @@ int smp_call_function_single_async(int cpu, call_single_data_t *csd)
385
401
csd -> flags = CSD_FLAG_LOCK ;
386
402
smp_wmb ();
387
403
388
- err = generic_exec_single (cpu , csd , csd -> func , csd -> info );
404
+ err = generic_exec_single (cpu , csd );
389
405
390
406
out :
391
407
preempt_enable ();
@@ -500,7 +516,7 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
500
516
501
517
csd_lock (csd );
502
518
if (wait )
503
- csd -> flags |= CSD_FLAG_SYNCHRONOUS ;
519
+ csd -> flags |= CSD_TYPE_SYNC ;
504
520
csd -> func = func ;
505
521
csd -> info = info ;
506
522
if (llist_add (& csd -> llist , & per_cpu (call_single_queue , cpu )))
@@ -632,6 +648,17 @@ void __init smp_init(void)
632
648
{
633
649
int num_nodes , num_cpus ;
634
650
651
+ /*
652
+ * Ensure struct irq_work layout matches so that
653
+ * flush_smp_call_function_queue() can do horrible things.
654
+ */
655
+ BUILD_BUG_ON (offsetof(struct irq_work , llnode ) !=
656
+ offsetof(struct __call_single_data , llist ));
657
+ BUILD_BUG_ON (offsetof(struct irq_work , func ) !=
658
+ offsetof(struct __call_single_data , func ));
659
+ BUILD_BUG_ON (offsetof(struct irq_work , flags ) !=
660
+ offsetof(struct __call_single_data , flags ));
661
+
635
662
idle_threads_init ();
636
663
cpuhp_threads_init ();
637
664
0 commit comments