|
@@ -1252,7 +1252,17 @@ static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name,
|
|
|
struct cpuhp_step *sp;
|
|
|
int ret = 0;
|
|
|
|
|
|
- if (state == CPUHP_AP_ONLINE_DYN || state == CPUHP_BP_PREPARE_DYN) {
|
|
|
+ /*
|
|
|
+ * If name is NULL, then the state gets removed.
|
|
|
+ *
|
|
|
+ * CPUHP_AP_ONLINE_DYN and CPUHP_BP_PREPARE_DYN are handed out on
|
|
|
+ * the first allocation from these dynamic ranges, so the removal
|
|
|
+ * would trigger a new allocation and clear the wrong (already
|
|
|
+ * empty) state, leaving the callbacks of the to be cleared state
|
|
|
+ * dangling, which causes wreckage on the next hotplug operation.
|
|
|
+ */
|
|
|
+ if (name && (state == CPUHP_AP_ONLINE_DYN ||
|
|
|
+ state == CPUHP_BP_PREPARE_DYN)) {
|
|
|
ret = cpuhp_reserve_state(state);
|
|
|
if (ret < 0)
|
|
|
return ret;
|