Skip to content

Commit f26d258

Browse files
KAGA-KOKOsuryasaimadhu
authored andcommitted
x86/mce/amd: Cleanup threshold device remove path
Pass in the bank pointer directly to the cleaning up functions, obviating the need for per-CPU accesses. Make the clean up path interrupt-safe by cleaning the bank pointer first so that the rest of the teardown happens safe from the thresholding interrupt. No functional changes. [ bp: Write commit message and reverse bank->shared test to save an indentation level in threshold_remove_bank(). ] Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 6458de9 commit f26d258

File tree

2 files changed

+38
-42
lines changed

2 files changed

+38
-42
lines changed

arch/x86/include/asm/amd_nb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct threshold_bank {
5757

5858
/* initialized to the number of CPUs on the node sharing this bank */
5959
refcount_t cpus;
60+
unsigned int shared;
6061
};
6162

6263
struct amd_northbridge {

arch/x86/kernel/cpu/mce/amd.c

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,7 @@ static int threshold_create_bank(struct threshold_bank **bp, unsigned int cpu,
13621362
}
13631363

13641364
if (is_shared_bank(bank)) {
1365+
b->shared = 1;
13651366
refcount_set(&b->cpus, 1);
13661367

13671368
/* nb is already initialized, see above */
@@ -1391,21 +1392,16 @@ static void threshold_block_release(struct kobject *kobj)
13911392
kfree(to_block(kobj));
13921393
}
13931394

1394-
static void deallocate_threshold_block(unsigned int cpu, unsigned int bank)
1395+
static void deallocate_threshold_blocks(struct threshold_bank *bank)
13951396
{
1396-
struct threshold_block *pos = NULL;
1397-
struct threshold_block *tmp = NULL;
1398-
struct threshold_bank *head = per_cpu(threshold_banks, cpu)[bank];
1399-
1400-
if (!head)
1401-
return;
1397+
struct threshold_block *pos, *tmp;
14021398

1403-
list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
1399+
list_for_each_entry_safe(pos, tmp, &bank->blocks->miscj, miscj) {
14041400
list_del(&pos->miscj);
14051401
kobject_put(&pos->kobj);
14061402
}
14071403

1408-
kobject_put(&head->blocks->kobj);
1404+
kobject_put(&bank->blocks->kobj);
14091405
}
14101406

14111407
static void __threshold_remove_blocks(struct threshold_bank *b)
@@ -1419,57 +1415,56 @@ static void __threshold_remove_blocks(struct threshold_bank *b)
14191415
kobject_del(&pos->kobj);
14201416
}
14211417

1422-
static void threshold_remove_bank(unsigned int cpu, int bank)
1418+
static void threshold_remove_bank(struct threshold_bank *bank)
14231419
{
14241420
struct amd_northbridge *nb;
1425-
struct threshold_bank *b;
14261421

1427-
b = per_cpu(threshold_banks, cpu)[bank];
1428-
if (!b)
1429-
return;
1422+
if (!bank->blocks)
1423+
goto out_free;
14301424

1431-
if (!b->blocks)
1432-
goto free_out;
1425+
if (!bank->shared)
1426+
goto out_dealloc;
14331427

1434-
if (is_shared_bank(bank)) {
1435-
if (!refcount_dec_and_test(&b->cpus)) {
1436-
__threshold_remove_blocks(b);
1437-
per_cpu(threshold_banks, cpu)[bank] = NULL;
1438-
return;
1439-
} else {
1440-
/*
1441-
* the last CPU on this node using the shared bank is
1442-
* going away, remove that bank now.
1443-
*/
1444-
nb = node_to_amd_nb(amd_get_nb_id(cpu));
1445-
nb->bank4 = NULL;
1446-
}
1428+
if (!refcount_dec_and_test(&bank->cpus)) {
1429+
__threshold_remove_blocks(bank);
1430+
return;
1431+
} else {
1432+
/*
1433+
* The last CPU on this node using the shared bank is going
1434+
* away, remove that bank now.
1435+
*/
1436+
nb = node_to_amd_nb(amd_get_nb_id(smp_processor_id()));
1437+
nb->bank4 = NULL;
14471438
}
14481439

1449-
deallocate_threshold_block(cpu, bank);
1440+
out_dealloc:
1441+
deallocate_threshold_blocks(bank);
14501442

1451-
free_out:
1452-
kobject_del(b->kobj);
1453-
kobject_put(b->kobj);
1454-
kfree(b);
1455-
per_cpu(threshold_banks, cpu)[bank] = NULL;
1443+
out_free:
1444+
kobject_put(bank->kobj);
1445+
kfree(bank);
14561446
}
14571447

14581448
int mce_threshold_remove_device(unsigned int cpu)
14591449
{
14601450
struct threshold_bank **bp = this_cpu_read(threshold_banks);
1461-
unsigned int bank;
1451+
unsigned int bank, numbanks = this_cpu_read(mce_num_banks);
14621452

14631453
if (!bp)
14641454
return 0;
14651455

1466-
for (bank = 0; bank < per_cpu(mce_num_banks, cpu); ++bank) {
1467-
if (!(per_cpu(bank_map, cpu) & (1 << bank)))
1468-
continue;
1469-
threshold_remove_bank(cpu, bank);
1470-
}
1471-
/* Clear the pointer before freeing the memory */
1456+
/*
1457+
* Clear the pointer before cleaning up, so that the interrupt won't
1458+
* touch anything of this.
1459+
*/
14721460
this_cpu_write(threshold_banks, NULL);
1461+
1462+
for (bank = 0; bank < numbanks; bank++) {
1463+
if (bp[bank]) {
1464+
threshold_remove_bank(bp[bank]);
1465+
bp[bank] = NULL;
1466+
}
1467+
}
14731468
kfree(bp);
14741469
return 0;
14751470
}

0 commit comments

Comments
 (0)