@@ -123,13 +123,16 @@ static struct cpuhp_step *cpuhp_get_step(enum cpuhp_state state)
123
123
/**
124
124
* cpuhp_invoke_callback _ Invoke the callbacks for a given state
125
125
* @cpu: The cpu for which the callback should be invoked
126
- * @step : The step in the state machine
126
+ * @state : The state to do callbacks for
127
127
* @bringup: True if the bringup callback should be invoked
128
+ * @node: For multi-instance, do a single entry callback for install/remove
129
+ * @lastp: For multi-instance rollback, remember how far we got
128
130
*
129
131
* Called from cpu hotplug and from the state register machinery.
130
132
*/
131
133
static int cpuhp_invoke_callback (unsigned int cpu , enum cpuhp_state state ,
132
- bool bringup , struct hlist_node * node )
134
+ bool bringup , struct hlist_node * node ,
135
+ struct hlist_node * * lastp )
133
136
{
134
137
struct cpuhp_cpu_state * st = per_cpu_ptr (& cpuhp_state , cpu );
135
138
struct cpuhp_step * step = cpuhp_get_step (state );
@@ -138,6 +141,7 @@ static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
138
141
int ret , cnt ;
139
142
140
143
if (!step -> multi_instance ) {
144
+ WARN_ON_ONCE (lastp && * lastp );
141
145
cb = bringup ? step -> startup .single : step -> teardown .single ;
142
146
if (!cb )
143
147
return 0 ;
@@ -152,6 +156,7 @@ static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
152
156
153
157
/* Single invocation for instance add/remove */
154
158
if (node ) {
159
+ WARN_ON_ONCE (lastp && * lastp );
155
160
trace_cpuhp_multi_enter (cpu , st -> target , state , cbm , node );
156
161
ret = cbm (cpu , node );
157
162
trace_cpuhp_exit (cpu , st -> state , state , ret );
@@ -161,13 +166,23 @@ static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
161
166
/* State transition. Invoke on all instances */
162
167
cnt = 0 ;
163
168
hlist_for_each (node , & step -> list ) {
169
+ if (lastp && node == * lastp )
170
+ break ;
171
+
164
172
trace_cpuhp_multi_enter (cpu , st -> target , state , cbm , node );
165
173
ret = cbm (cpu , node );
166
174
trace_cpuhp_exit (cpu , st -> state , state , ret );
167
- if (ret )
168
- goto err ;
175
+ if (ret ) {
176
+ if (!lastp )
177
+ goto err ;
178
+
179
+ * lastp = node ;
180
+ return ret ;
181
+ }
169
182
cnt ++ ;
170
183
}
184
+ if (lastp )
185
+ * lastp = NULL ;
171
186
return 0 ;
172
187
err :
173
188
/* Rollback the instances if one failed */
@@ -323,7 +338,7 @@ static void undo_cpu_down(unsigned int cpu, struct cpuhp_cpu_state *st)
323
338
struct cpuhp_step * step = cpuhp_get_step (st -> state );
324
339
325
340
if (!step -> skip_onerr )
326
- cpuhp_invoke_callback (cpu , st -> state , true, NULL );
341
+ cpuhp_invoke_callback (cpu , st -> state , true, NULL , NULL );
327
342
}
328
343
}
329
344
@@ -334,7 +349,7 @@ static int cpuhp_down_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
334
349
int ret = 0 ;
335
350
336
351
for (; st -> state > target ; st -> state -- ) {
337
- ret = cpuhp_invoke_callback (cpu , st -> state , false, NULL );
352
+ ret = cpuhp_invoke_callback (cpu , st -> state , false, NULL , NULL );
338
353
if (ret ) {
339
354
st -> target = prev_state ;
340
355
undo_cpu_down (cpu , st );
@@ -350,7 +365,7 @@ static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st)
350
365
struct cpuhp_step * step = cpuhp_get_step (st -> state );
351
366
352
367
if (!step -> skip_onerr )
353
- cpuhp_invoke_callback (cpu , st -> state , false, NULL );
368
+ cpuhp_invoke_callback (cpu , st -> state , false, NULL , NULL );
354
369
}
355
370
}
356
371
@@ -362,7 +377,7 @@ static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
362
377
363
378
while (st -> state < target ) {
364
379
st -> state ++ ;
365
- ret = cpuhp_invoke_callback (cpu , st -> state , true, NULL );
380
+ ret = cpuhp_invoke_callback (cpu , st -> state , true, NULL , NULL );
366
381
if (ret ) {
367
382
st -> target = prev_state ;
368
383
undo_cpu_up (cpu , st );
@@ -428,11 +443,13 @@ static void cpuhp_thread_fun(unsigned int cpu)
428
443
if (st -> cb_state < CPUHP_AP_ONLINE ) {
429
444
local_irq_disable ();
430
445
ret = cpuhp_invoke_callback (cpu , st -> cb_state ,
431
- st -> bringup , st -> node );
446
+ st -> bringup , st -> node ,
447
+ NULL );
432
448
local_irq_enable ();
433
449
} else {
434
450
ret = cpuhp_invoke_callback (cpu , st -> cb_state ,
435
- st -> bringup , st -> node );
451
+ st -> bringup , st -> node ,
452
+ NULL );
436
453
}
437
454
} else if (st -> rollback ) {
438
455
BUG_ON (st -> state < CPUHP_AP_ONLINE_IDLE );
@@ -472,7 +489,7 @@ cpuhp_invoke_ap_callback(int cpu, enum cpuhp_state state, bool bringup,
472
489
* we invoke the thread function directly.
473
490
*/
474
491
if (!st -> thread )
475
- return cpuhp_invoke_callback (cpu , state , bringup , node );
492
+ return cpuhp_invoke_callback (cpu , state , bringup , node , NULL );
476
493
477
494
st -> cb_state = state ;
478
495
st -> single = true;
@@ -595,7 +612,7 @@ static int take_cpu_down(void *_param)
595
612
st -> state -- ;
596
613
/* Invoke the former CPU_DYING callbacks */
597
614
for (; st -> state > target ; st -> state -- )
598
- cpuhp_invoke_callback (cpu , st -> state , false, NULL );
615
+ cpuhp_invoke_callback (cpu , st -> state , false, NULL , NULL );
599
616
600
617
/* Give up timekeeping duties */
601
618
tick_handover_do_timer ();
@@ -776,7 +793,7 @@ void notify_cpu_starting(unsigned int cpu)
776
793
rcu_cpu_starting (cpu ); /* Enables RCU usage on this CPU. */
777
794
while (st -> state < target ) {
778
795
st -> state ++ ;
779
- cpuhp_invoke_callback (cpu , st -> state , true, NULL );
796
+ cpuhp_invoke_callback (cpu , st -> state , true, NULL , NULL );
780
797
}
781
798
}
782
799
@@ -1307,9 +1324,9 @@ static int cpuhp_issue_call(int cpu, enum cpuhp_state state, bool bringup,
1307
1324
if (cpuhp_is_ap_state (state ))
1308
1325
ret = cpuhp_invoke_ap_callback (cpu , state , bringup , node );
1309
1326
else
1310
- ret = cpuhp_invoke_callback (cpu , state , bringup , node );
1327
+ ret = cpuhp_invoke_callback (cpu , state , bringup , node , NULL );
1311
1328
#else
1312
- ret = cpuhp_invoke_callback (cpu , state , bringup , node );
1329
+ ret = cpuhp_invoke_callback (cpu , state , bringup , node , NULL );
1313
1330
#endif
1314
1331
BUG_ON (ret && !bringup );
1315
1332
return ret ;
0 commit comments