diff options
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r-- | kernel/cpu.c | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index f7c063239fa5..37b223e4fc05 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -1335,26 +1335,21 @@ static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name, | |||
1335 | struct cpuhp_step *sp; | 1335 | struct cpuhp_step *sp; |
1336 | int ret = 0; | 1336 | int ret = 0; |
1337 | 1337 | ||
1338 | mutex_lock(&cpuhp_state_mutex); | ||
1339 | |||
1340 | if (state == CPUHP_AP_ONLINE_DYN || state == CPUHP_BP_PREPARE_DYN) { | 1338 | if (state == CPUHP_AP_ONLINE_DYN || state == CPUHP_BP_PREPARE_DYN) { |
1341 | ret = cpuhp_reserve_state(state); | 1339 | ret = cpuhp_reserve_state(state); |
1342 | if (ret < 0) | 1340 | if (ret < 0) |
1343 | goto out; | 1341 | return ret; |
1344 | state = ret; | 1342 | state = ret; |
1345 | } | 1343 | } |
1346 | sp = cpuhp_get_step(state); | 1344 | sp = cpuhp_get_step(state); |
1347 | if (name && sp->name) { | 1345 | if (name && sp->name) |
1348 | ret = -EBUSY; | 1346 | return -EBUSY; |
1349 | goto out; | 1347 | |
1350 | } | ||
1351 | sp->startup.single = startup; | 1348 | sp->startup.single = startup; |
1352 | sp->teardown.single = teardown; | 1349 | sp->teardown.single = teardown; |
1353 | sp->name = name; | 1350 | sp->name = name; |
1354 | sp->multi_instance = multi_instance; | 1351 | sp->multi_instance = multi_instance; |
1355 | INIT_HLIST_HEAD(&sp->list); | 1352 | INIT_HLIST_HEAD(&sp->list); |
1356 | out: | ||
1357 | mutex_unlock(&cpuhp_state_mutex); | ||
1358 | return ret; | 1353 | return ret; |
1359 | } | 1354 | } |
1360 | 1355 | ||
@@ -1428,6 +1423,7 @@ int __cpuhp_state_add_instance(enum cpuhp_state state, struct hlist_node *node, | |||
1428 | return -EINVAL; | 1423 | return -EINVAL; |
1429 | 1424 | ||
1430 | get_online_cpus(); | 1425 | get_online_cpus(); |
1426 | mutex_lock(&cpuhp_state_mutex); | ||
1431 | 1427 | ||
1432 | if (!invoke || !sp->startup.multi) | 1428 | if (!invoke || !sp->startup.multi) |
1433 | goto add_node; | 1429 | goto add_node; |
@@ -1447,16 +1443,14 @@ int __cpuhp_state_add_instance(enum cpuhp_state state, struct hlist_node *node, | |||
1447 | if (ret) { | 1443 | if (ret) { |
1448 | if (sp->teardown.multi) | 1444 | if (sp->teardown.multi) |
1449 | cpuhp_rollback_install(cpu, state, node); | 1445 | cpuhp_rollback_install(cpu, state, node); |
1450 | goto err; | 1446 | goto unlock; |
1451 | } | 1447 | } |
1452 | } | 1448 | } |
1453 | add_node: | 1449 | add_node: |
1454 | ret = 0; | 1450 | ret = 0; |
1455 | mutex_lock(&cpuhp_state_mutex); | ||
1456 | hlist_add_head(node, &sp->list); | 1451 | hlist_add_head(node, &sp->list); |
1452 | unlock: | ||
1457 | mutex_unlock(&cpuhp_state_mutex); | 1453 | mutex_unlock(&cpuhp_state_mutex); |
1458 | |||
1459 | err: | ||
1460 | put_online_cpus(); | 1454 | put_online_cpus(); |
1461 | return ret; | 1455 | return ret; |
1462 | } | 1456 | } |
@@ -1491,6 +1485,7 @@ int __cpuhp_setup_state(enum cpuhp_state state, | |||
1491 | return -EINVAL; | 1485 | return -EINVAL; |
1492 | 1486 | ||
1493 | get_online_cpus(); | 1487 | get_online_cpus(); |
1488 | mutex_lock(&cpuhp_state_mutex); | ||
1494 | 1489 | ||
1495 | ret = cpuhp_store_callbacks(state, name, startup, teardown, | 1490 | ret = cpuhp_store_callbacks(state, name, startup, teardown, |
1496 | multi_instance); | 1491 | multi_instance); |
@@ -1524,6 +1519,7 @@ int __cpuhp_setup_state(enum cpuhp_state state, | |||
1524 | } | 1519 | } |
1525 | } | 1520 | } |
1526 | out: | 1521 | out: |
1522 | mutex_unlock(&cpuhp_state_mutex); | ||
1527 | put_online_cpus(); | 1523 | put_online_cpus(); |
1528 | /* | 1524 | /* |
1529 | * If the requested state is CPUHP_AP_ONLINE_DYN, return the | 1525 | * If the requested state is CPUHP_AP_ONLINE_DYN, return the |
@@ -1547,6 +1543,8 @@ int __cpuhp_state_remove_instance(enum cpuhp_state state, | |||
1547 | return -EINVAL; | 1543 | return -EINVAL; |
1548 | 1544 | ||
1549 | get_online_cpus(); | 1545 | get_online_cpus(); |
1546 | mutex_lock(&cpuhp_state_mutex); | ||
1547 | |||
1550 | if (!invoke || !cpuhp_get_teardown_cb(state)) | 1548 | if (!invoke || !cpuhp_get_teardown_cb(state)) |
1551 | goto remove; | 1549 | goto remove; |
1552 | /* | 1550 | /* |
@@ -1563,7 +1561,6 @@ int __cpuhp_state_remove_instance(enum cpuhp_state state, | |||
1563 | } | 1561 | } |
1564 | 1562 | ||
1565 | remove: | 1563 | remove: |
1566 | mutex_lock(&cpuhp_state_mutex); | ||
1567 | hlist_del(node); | 1564 | hlist_del(node); |
1568 | mutex_unlock(&cpuhp_state_mutex); | 1565 | mutex_unlock(&cpuhp_state_mutex); |
1569 | put_online_cpus(); | 1566 | put_online_cpus(); |
@@ -1571,6 +1568,7 @@ remove: | |||
1571 | return 0; | 1568 | return 0; |
1572 | } | 1569 | } |
1573 | EXPORT_SYMBOL_GPL(__cpuhp_state_remove_instance); | 1570 | EXPORT_SYMBOL_GPL(__cpuhp_state_remove_instance); |
1571 | |||
1574 | /** | 1572 | /** |
1575 | * __cpuhp_remove_state - Remove the callbacks for an hotplug machine state | 1573 | * __cpuhp_remove_state - Remove the callbacks for an hotplug machine state |
1576 | * @state: The state to remove | 1574 | * @state: The state to remove |
@@ -1589,6 +1587,7 @@ void __cpuhp_remove_state(enum cpuhp_state state, bool invoke) | |||
1589 | 1587 | ||
1590 | get_online_cpus(); | 1588 | get_online_cpus(); |
1591 | 1589 | ||
1590 | mutex_lock(&cpuhp_state_mutex); | ||
1592 | if (sp->multi_instance) { | 1591 | if (sp->multi_instance) { |
1593 | WARN(!hlist_empty(&sp->list), | 1592 | WARN(!hlist_empty(&sp->list), |
1594 | "Error: Removing state %d which has instances left.\n", | 1593 | "Error: Removing state %d which has instances left.\n", |
@@ -1613,6 +1612,7 @@ void __cpuhp_remove_state(enum cpuhp_state state, bool invoke) | |||
1613 | } | 1612 | } |
1614 | remove: | 1613 | remove: |
1615 | cpuhp_store_callbacks(state, NULL, NULL, NULL, false); | 1614 | cpuhp_store_callbacks(state, NULL, NULL, NULL, false); |
1615 | mutex_unlock(&cpuhp_state_mutex); | ||
1616 | put_online_cpus(); | 1616 | put_online_cpus(); |
1617 | } | 1617 | } |
1618 | EXPORT_SYMBOL(__cpuhp_remove_state); | 1618 | EXPORT_SYMBOL(__cpuhp_remove_state); |