Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/mce/amd: Straighten CPU hotplug path

mce_threshold_create_device() hotplug callback runs on the plugged in
CPU so:

- use this_cpu_read() which is faster
- pass in struct threshold_bank **bp to threshold_create_bank() and
instead of doing per-CPU accesses
- Use rdmsr_safe() instead of rdmsr_safe_on_cpu() which avoids an IPI.

No functional changes.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20200403161943.1458-6-bp@alien8.de

authored by

Thomas Gleixner and committed by
Borislav Petkov
6458de97 6e7a41c6

+15 -17
+15 -17
arch/x86/kernel/cpu/mce/amd.c
··· 1223 1223 u32 low, high; 1224 1224 int err; 1225 1225 1226 - if ((bank >= per_cpu(mce_num_banks, cpu)) || (block >= NR_BLOCKS)) 1226 + if ((bank >= this_cpu_read(mce_num_banks)) || (block >= NR_BLOCKS)) 1227 1227 return 0; 1228 1228 1229 - if (rdmsr_safe_on_cpu(cpu, address, &low, &high)) 1229 + if (rdmsr_safe(address, &low, &high)) 1230 1230 return 0; 1231 1231 1232 1232 if (!(high & MASK_VALID_HI)) { ··· 1316 1316 return err; 1317 1317 } 1318 1318 1319 - static int threshold_create_bank(unsigned int cpu, unsigned int bank) 1319 + static int threshold_create_bank(struct threshold_bank **bp, unsigned int cpu, 1320 + unsigned int bank) 1320 1321 { 1321 - struct device *dev = per_cpu(mce_device, cpu); 1322 + struct device *dev = this_cpu_read(mce_device); 1322 1323 struct amd_northbridge *nb = NULL; 1323 1324 struct threshold_bank *b = NULL; 1324 1325 const char *name = get_name(bank, NULL); ··· 1339 1338 if (err) 1340 1339 goto out; 1341 1340 1342 - per_cpu(threshold_banks, cpu)[bank] = b; 1341 + bp[bank] = b; 1343 1342 refcount_inc(&b->cpus); 1344 1343 1345 1344 err = __threshold_add_blocks(b); ··· 1375 1374 if (err) 1376 1375 goto out_kobj; 1377 1376 1378 - per_cpu(threshold_banks, cpu)[bank] = b; 1379 - 1377 + bp[bank] = b; 1380 1378 return 0; 1381 1379 1382 1380 out_kobj: ··· 1487 1487 */ 1488 1488 int mce_threshold_create_device(unsigned int cpu) 1489 1489 { 1490 - unsigned int bank; 1490 + unsigned int numbanks, bank; 1491 1491 struct threshold_bank **bp; 1492 1492 int err; 1493 1493 1494 1494 if (!mce_flags.amd_threshold) 1495 1495 return 0; 1496 1496 1497 - bp = per_cpu(threshold_banks, cpu); 1497 + bp = this_cpu_read(threshold_banks); 1498 1498 if (bp) 1499 1499 return 0; 1500 1500 1501 - bp = kcalloc(per_cpu(mce_num_banks, cpu), sizeof(struct threshold_bank *), 1502 - GFP_KERNEL); 1501 + numbanks = this_cpu_read(mce_num_banks); 1502 + bp = kcalloc(numbanks, sizeof(*bp), GFP_KERNEL); 1503 1503 if (!bp) 1504 1504 return -ENOMEM; 1505 1505 1506 - per_cpu(threshold_banks, cpu) = bp; 1507 - 1508 - for (bank = 0; bank < per_cpu(mce_num_banks, cpu); ++bank) { 1509 - if (!(per_cpu(bank_map, cpu) & (1 << bank))) 1506 + for (bank = 0; bank < numbanks; ++bank) { 1507 + if (!(this_cpu_read(bank_map) & (1 << bank))) 1510 1508 continue; 1511 - err = threshold_create_bank(cpu, bank); 1509 + err = threshold_create_bank(bp, cpu, bank); 1512 1510 if (err) 1513 1511 goto out_err; 1514 1512 } 1513 + this_cpu_write(threshold_banks, bp); 1515 1514 1516 1515 if (thresholding_irq_en) 1517 1516 mce_threshold_vector = amd_threshold_interrupt; 1518 - 1519 1517 return 0; 1520 1518 out_err: 1521 1519 mce_threshold_remove_device(cpu);