Skip to content

Commit a0fea88

Browse files
committed
hwmon/coretemp: Handle large core ID value
Bugzilla: https://bugzilla.redhat.com/2159554 commit 7108b80 Author: Zhang Rui <rui.zhang@intel.com> Date: Fri Oct 14 17:01:45 2022 +0800 hwmon/coretemp: Handle large core ID value 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 <rui.zhang@intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Acked-by: Len Brown <len.brown@intel.com> Acked-by: Guenter Roeck <linux@roeck-us.net> Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20221014090147.1836-3-rui.zhang@intel.com Signed-off-by: David Arcari <darcari@redhat.com>
1 parent 5e8cf7d commit a0fea88

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

@@ -528,6 +542,9 @@ static void coretemp_remove_core(struct platform_data *pdata, int indx)
528542

529543
kfree(pdata->core_data[indx]);
530544
pdata->core_data[indx] = NULL;
545+
546+
if (indx >= BASE_SYSFS_ATTR_NO)
547+
ida_free(&pdata->ida, indx - BASE_SYSFS_ATTR_NO);
531548
}
532549

533550
static int coretemp_probe(struct platform_device *pdev)
@@ -541,6 +558,7 @@ static int coretemp_probe(struct platform_device *pdev)
541558
return -ENOMEM;
542559

543560
pdata->pkg_id = pdev->id;
561+
ida_init(&pdata->ida);
544562
platform_set_drvdata(pdev, pdata);
545563

546564
pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,
@@ -557,6 +575,7 @@ static int coretemp_remove(struct platform_device *pdev)
557575
if (pdata->core_data[i])
558576
coretemp_remove_core(pdata, i);
559577

578+
ida_destroy(&pdata->ida);
560579
return 0;
561580
}
562581

@@ -651,7 +670,7 @@ static int coretemp_cpu_offline(unsigned int cpu)
651670
struct platform_device *pdev = coretemp_get_pdev(cpu);
652671
struct platform_data *pd;
653672
struct temp_data *tdata;
654-
int indx, target;
673+
int i, indx = -1, target;
655674

656675
/*
657676
* Don't execute this on suspend as the device remove locks
@@ -664,12 +683,19 @@ static int coretemp_cpu_offline(unsigned int cpu)
664683
if (!pdev)
665684
return 0;
666685

667-
/* The core id is too big, just return */
668-
indx = TO_ATTR_NO(cpu);
669-
if (indx > MAX_CORE_DATA - 1)
686+
pd = platform_get_drvdata(pdev);
687+
688+
for (i = 0; i < NUM_REAL_CORES; i++) {
689+
if (pd->cpu_map[i] == topology_core_id(cpu)) {
690+
indx = i + BASE_SYSFS_ATTR_NO;
691+
break;
692+
}
693+
}
694+
695+
/* Too many cores and this core is not populated, just return */
696+
if (indx < 0)
670697
return 0;
671698

672-
pd = platform_get_drvdata(pdev);
673699
tdata = pd->core_data[indx];
674700

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

0 commit comments

Comments
 (0)