Skip to content

Commit c00cdfc

Browse files
zhang-ruigregkh
authored andcommitted
hwmon/coretemp: Handle large core ID value
commit 7108b80 upstream. The coretemp driver supports up to a hard-coded limit of 128 cores. Today, the driver can not support a core with an ID above that limit. Yet, the encoding of core ID's is arbitrary (BIOS APIC-ID) and so they may be sparse and they may be large. Update the driver to map arbitrary core ID numbers into appropriate array indexes so that 128 cores can be supported, no matter the encoding of core ID's. Signed-off-by: Zhang Rui <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Acked-by: Len Brown <[email protected]> Acked-by: Guenter Roeck <[email protected]> Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 3ea7da6 commit c00cdfc

File tree

1 file changed

+41
-15
lines changed

1 file changed

+41
-15
lines changed

drivers/hwmon/coretemp.c

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,6 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
4646
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
4747
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
4848

49-
#define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id)
50-
#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
51-
5249
#ifdef CONFIG_SMP
5350
#define for_each_sibling(i, cpu) \
5451
for_each_cpu(i, topology_sibling_cpumask(cpu))
@@ -91,6 +88,8 @@ struct temp_data {
9188
struct platform_data {
9289
struct device *hwmon_dev;
9390
u16 pkg_id;
91+
u16 cpu_map[NUM_REAL_CORES];
92+
struct ida ida;
9493
struct cpumask cpumask;
9594
struct temp_data *core_data[MAX_CORE_DATA];
9695
struct device_attribute name_attr;
@@ -441,7 +440,7 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
441440
MSR_IA32_THERM_STATUS;
442441
tdata->is_pkg_data = pkg_flag;
443442
tdata->cpu = cpu;
444-
tdata->cpu_core_id = TO_CORE_ID(cpu);
443+
tdata->cpu_core_id = topology_core_id(cpu);
445444
tdata->attr_size = MAX_CORE_ATTRS;
446445
mutex_init(&tdata->update_lock);
447446
return tdata;
@@ -454,22 +453,34 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
454453
struct platform_data *pdata = platform_get_drvdata(pdev);
455454
struct cpuinfo_x86 *c = &cpu_data(cpu);
456455
u32 eax, edx;
457-
int err, attr_no;
456+
int err, index, attr_no;
458457

459458
/*
460459
* Find attr number for sysfs:
461460
* We map the attr number to core id of the CPU
462461
* The attr number is always core id + 2
463462
* The Pkgtemp will always show up as temp1_*, if available
464463
*/
465-
attr_no = pkg_flag ? PKG_SYSFS_ATTR_NO : TO_ATTR_NO(cpu);
464+
if (pkg_flag) {
465+
attr_no = PKG_SYSFS_ATTR_NO;
466+
} else {
467+
index = ida_alloc(&pdata->ida, GFP_KERNEL);
468+
if (index < 0)
469+
return index;
470+
pdata->cpu_map[index] = topology_core_id(cpu);
471+
attr_no = index + BASE_SYSFS_ATTR_NO;
472+
}
466473

467-
if (attr_no > MAX_CORE_DATA - 1)
468-
return -ERANGE;
474+
if (attr_no > MAX_CORE_DATA - 1) {
475+
err = -ERANGE;
476+
goto ida_free;
477+
}
469478

470479
tdata = init_temp_data(cpu, pkg_flag);
471-
if (!tdata)
472-
return -ENOMEM;
480+
if (!tdata) {
481+
err = -ENOMEM;
482+
goto ida_free;
483+
}
473484

474485
/* Test if we can access the status register */
475486
err = rdmsr_safe_on_cpu(cpu, tdata->status_reg, &eax, &edx);
@@ -505,6 +516,9 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
505516
exit_free:
506517
pdata->core_data[attr_no] = NULL;
507518
kfree(tdata);
519+
ida_free:
520+
if (!pkg_flag)
521+
ida_free(&pdata->ida, index);
508522
return err;
509523
}
510524

@@ -524,6 +538,9 @@ static void coretemp_remove_core(struct platform_data *pdata, int indx)
524538

525539
kfree(pdata->core_data[indx]);
526540
pdata->core_data[indx] = NULL;
541+
542+
if (indx >= BASE_SYSFS_ATTR_NO)
543+
ida_free(&pdata->ida, indx - BASE_SYSFS_ATTR_NO);
527544
}
528545

529546
static int coretemp_probe(struct platform_device *pdev)
@@ -537,6 +554,7 @@ static int coretemp_probe(struct platform_device *pdev)
537554
return -ENOMEM;
538555

539556
pdata->pkg_id = pdev->id;
557+
ida_init(&pdata->ida);
540558
platform_set_drvdata(pdev, pdata);
541559

542560
pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,
@@ -553,6 +571,7 @@ static int coretemp_remove(struct platform_device *pdev)
553571
if (pdata->core_data[i])
554572
coretemp_remove_core(pdata, i);
555573

574+
ida_destroy(&pdata->ida);
556575
return 0;
557576
}
558577

@@ -647,7 +666,7 @@ static int coretemp_cpu_offline(unsigned int cpu)
647666
struct platform_device *pdev = coretemp_get_pdev(cpu);
648667
struct platform_data *pd;
649668
struct temp_data *tdata;
650-
int indx, target;
669+
int i, indx = -1, target;
651670

652671
/*
653672
* Don't execute this on suspend as the device remove locks
@@ -660,12 +679,19 @@ static int coretemp_cpu_offline(unsigned int cpu)
660679
if (!pdev)
661680
return 0;
662681

663-
/* The core id is too big, just return */
664-
indx = TO_ATTR_NO(cpu);
665-
if (indx > MAX_CORE_DATA - 1)
682+
pd = platform_get_drvdata(pdev);
683+
684+
for (i = 0; i < NUM_REAL_CORES; i++) {
685+
if (pd->cpu_map[i] == topology_core_id(cpu)) {
686+
indx = i + BASE_SYSFS_ATTR_NO;
687+
break;
688+
}
689+
}
690+
691+
/* Too many cores and this core is not populated, just return */
692+
if (indx < 0)
666693
return 0;
667694

668-
pd = platform_get_drvdata(pdev);
669695
tdata = pd->core_data[indx];
670696

671697
cpumask_clear_cpu(cpu, &pd->cpumask);

0 commit comments

Comments
 (0)