hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/hwmon/coretemp.c
....@@ -1,23 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * coretemp.c - Linux kernel module for hardware monitoring
34 *
45 * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
56 *
67 * Inspired from many hwmon drivers
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; version 2 of the License.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, write to the Free Software
19
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
- * 02110-1301 USA.
218 */
229
2310 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
....@@ -58,9 +45,6 @@
5845 #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
5946 #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
6047 #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
61
-
62
-#define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id)
63
-#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
6448
6549 #ifdef CONFIG_SMP
6650 #define for_each_sibling(i, cpu) \
....@@ -104,15 +88,17 @@
10488 struct platform_data {
10589 struct device *hwmon_dev;
10690 u16 pkg_id;
91
+ u16 cpu_map[NUM_REAL_CORES];
92
+ struct ida ida;
10793 struct cpumask cpumask;
10894 struct temp_data *core_data[MAX_CORE_DATA];
10995 struct device_attribute name_attr;
11096 };
11197
112
-/* Keep track of how many package pointers we allocated in init() */
113
-static int max_packages __read_mostly;
114
-/* Array of package pointers. Serialized by cpu hotplug lock */
115
-static struct platform_device **pkg_devices;
98
+/* Keep track of how many zone pointers we allocated in init() */
99
+static int max_zones __read_mostly;
100
+/* Array of zone pointers. Serialized by cpu hotplug lock */
101
+static struct platform_device **zone_devices;
116102
117103 static ssize_t show_label(struct device *dev,
118104 struct device_attribute *devattr, char *buf)
....@@ -256,10 +242,13 @@
256242 */
257243 if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) {
258244 for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) {
259
- if (host_bridge->device == tjmax_pci_table[i].device)
245
+ if (host_bridge->device == tjmax_pci_table[i].device) {
246
+ pci_dev_put(host_bridge);
260247 return tjmax_pci_table[i].tjmax;
248
+ }
261249 }
262250 }
251
+ pci_dev_put(host_bridge);
263252
264253 for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) {
265254 if (strstr(c->x86_model_id, tjmax_table[i].id))
....@@ -407,7 +396,7 @@
407396 "temp%d_%s", attr_no, suffixes[i]);
408397 sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
409398 tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
410
- tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO;
399
+ tdata->sd_attrs[i].dev_attr.attr.mode = 0444;
411400 tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
412401 tdata->sd_attrs[i].index = attr_no;
413402 tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr;
....@@ -435,10 +424,10 @@
435424
436425 static struct platform_device *coretemp_get_pdev(unsigned int cpu)
437426 {
438
- int pkgid = topology_logical_package_id(cpu);
427
+ int id = topology_logical_die_id(cpu);
439428
440
- if (pkgid >= 0 && pkgid < max_packages)
441
- return pkg_devices[pkgid];
429
+ if (id >= 0 && id < max_zones)
430
+ return zone_devices[id];
442431 return NULL;
443432 }
444433
....@@ -454,7 +443,7 @@
454443 MSR_IA32_THERM_STATUS;
455444 tdata->is_pkg_data = pkg_flag;
456445 tdata->cpu = cpu;
457
- tdata->cpu_core_id = TO_CORE_ID(cpu);
446
+ tdata->cpu_core_id = topology_core_id(cpu);
458447 tdata->attr_size = MAX_CORE_ATTRS;
459448 mutex_init(&tdata->update_lock);
460449 return tdata;
....@@ -467,7 +456,7 @@
467456 struct platform_data *pdata = platform_get_drvdata(pdev);
468457 struct cpuinfo_x86 *c = &cpu_data(cpu);
469458 u32 eax, edx;
470
- int err, attr_no;
459
+ int err, index, attr_no;
471460
472461 /*
473462 * Find attr number for sysfs:
....@@ -475,14 +464,26 @@
475464 * The attr number is always core id + 2
476465 * The Pkgtemp will always show up as temp1_*, if available
477466 */
478
- attr_no = pkg_flag ? PKG_SYSFS_ATTR_NO : TO_ATTR_NO(cpu);
467
+ if (pkg_flag) {
468
+ attr_no = PKG_SYSFS_ATTR_NO;
469
+ } else {
470
+ index = ida_alloc(&pdata->ida, GFP_KERNEL);
471
+ if (index < 0)
472
+ return index;
473
+ pdata->cpu_map[index] = topology_core_id(cpu);
474
+ attr_no = index + BASE_SYSFS_ATTR_NO;
475
+ }
479476
480
- if (attr_no > MAX_CORE_DATA - 1)
481
- return -ERANGE;
477
+ if (attr_no > MAX_CORE_DATA - 1) {
478
+ err = -ERANGE;
479
+ goto ida_free;
480
+ }
482481
483482 tdata = init_temp_data(cpu, pkg_flag);
484
- if (!tdata)
485
- return -ENOMEM;
483
+ if (!tdata) {
484
+ err = -ENOMEM;
485
+ goto ida_free;
486
+ }
486487
487488 /* Test if we can access the status register */
488489 err = rdmsr_safe_on_cpu(cpu, tdata->status_reg, &eax, &edx);
....@@ -518,6 +519,9 @@
518519 exit_free:
519520 pdata->core_data[attr_no] = NULL;
520521 kfree(tdata);
522
+ida_free:
523
+ if (!pkg_flag)
524
+ ida_free(&pdata->ida, index);
521525 return err;
522526 }
523527
....@@ -532,71 +536,63 @@
532536 {
533537 struct temp_data *tdata = pdata->core_data[indx];
534538
539
+ /* if we errored on add then this is already gone */
540
+ if (!tdata)
541
+ return;
542
+
535543 /* Remove the sysfs attributes */
536544 sysfs_remove_group(&pdata->hwmon_dev->kobj, &tdata->attr_group);
537545
538546 kfree(pdata->core_data[indx]);
539547 pdata->core_data[indx] = NULL;
548
+
549
+ if (indx >= BASE_SYSFS_ATTR_NO)
550
+ ida_free(&pdata->ida, indx - BASE_SYSFS_ATTR_NO);
540551 }
541552
542
-static int coretemp_probe(struct platform_device *pdev)
553
+static int coretemp_device_add(int zoneid)
543554 {
544
- struct device *dev = &pdev->dev;
555
+ struct platform_device *pdev;
545556 struct platform_data *pdata;
557
+ int err;
546558
547
- /* Initialize the per-package data structures */
548
- pdata = devm_kzalloc(dev, sizeof(struct platform_data), GFP_KERNEL);
559
+ /* Initialize the per-zone data structures */
560
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
549561 if (!pdata)
550562 return -ENOMEM;
551563
552
- pdata->pkg_id = pdev->id;
553
- platform_set_drvdata(pdev, pdata);
564
+ pdata->pkg_id = zoneid;
565
+ ida_init(&pdata->ida);
554566
555
- pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,
556
- pdata, NULL);
557
- return PTR_ERR_OR_ZERO(pdata->hwmon_dev);
558
-}
559
-
560
-static int coretemp_remove(struct platform_device *pdev)
561
-{
562
- struct platform_data *pdata = platform_get_drvdata(pdev);
563
- int i;
564
-
565
- for (i = MAX_CORE_DATA - 1; i >= 0; --i)
566
- if (pdata->core_data[i])
567
- coretemp_remove_core(pdata, i);
568
-
569
- return 0;
570
-}
571
-
572
-static struct platform_driver coretemp_driver = {
573
- .driver = {
574
- .name = DRVNAME,
575
- },
576
- .probe = coretemp_probe,
577
- .remove = coretemp_remove,
578
-};
579
-
580
-static struct platform_device *coretemp_device_add(unsigned int cpu)
581
-{
582
- int err, pkgid = topology_logical_package_id(cpu);
583
- struct platform_device *pdev;
584
-
585
- if (pkgid < 0)
586
- return ERR_PTR(-ENOMEM);
587
-
588
- pdev = platform_device_alloc(DRVNAME, pkgid);
589
- if (!pdev)
590
- return ERR_PTR(-ENOMEM);
591
-
592
- err = platform_device_add(pdev);
593
- if (err) {
594
- platform_device_put(pdev);
595
- return ERR_PTR(err);
567
+ pdev = platform_device_alloc(DRVNAME, zoneid);
568
+ if (!pdev) {
569
+ err = -ENOMEM;
570
+ goto err_free_pdata;
596571 }
597572
598
- pkg_devices[pkgid] = pdev;
599
- return pdev;
573
+ err = platform_device_add(pdev);
574
+ if (err)
575
+ goto err_put_dev;
576
+
577
+ platform_set_drvdata(pdev, pdata);
578
+ zone_devices[zoneid] = pdev;
579
+ return 0;
580
+
581
+err_put_dev:
582
+ platform_device_put(pdev);
583
+err_free_pdata:
584
+ kfree(pdata);
585
+ return err;
586
+}
587
+
588
+static void coretemp_device_remove(int zoneid)
589
+{
590
+ struct platform_device *pdev = zone_devices[zoneid];
591
+ struct platform_data *pdata = platform_get_drvdata(pdev);
592
+
593
+ ida_destroy(&pdata->ida);
594
+ kfree(pdata);
595
+ platform_device_unregister(pdev);
600596 }
601597
602598 static int coretemp_cpu_online(unsigned int cpu)
....@@ -620,7 +616,10 @@
620616 if (!cpu_has(c, X86_FEATURE_DTHERM))
621617 return -ENODEV;
622618
623
- if (!pdev) {
619
+ pdata = platform_get_drvdata(pdev);
620
+ if (!pdata->hwmon_dev) {
621
+ struct device *hwmon;
622
+
624623 /* Check the microcode version of the CPU */
625624 if (chk_ucode_version(cpu))
626625 return -EINVAL;
....@@ -631,9 +630,11 @@
631630 * online. So, initialize per-pkg data structures and
632631 * then bring this core online.
633632 */
634
- pdev = coretemp_device_add(cpu);
635
- if (IS_ERR(pdev))
636
- return PTR_ERR(pdev);
633
+ hwmon = hwmon_device_register_with_groups(&pdev->dev, DRVNAME,
634
+ pdata, NULL);
635
+ if (IS_ERR(hwmon))
636
+ return PTR_ERR(hwmon);
637
+ pdata->hwmon_dev = hwmon;
637638
638639 /*
639640 * Check whether pkgtemp support is available.
....@@ -643,7 +644,6 @@
643644 coretemp_add_core(pdev, cpu, 1);
644645 }
645646
646
- pdata = platform_get_drvdata(pdev);
647647 /*
648648 * Check whether a thread sibling is already online. If not add the
649649 * interface for this CPU core.
....@@ -660,25 +660,28 @@
660660 struct platform_device *pdev = coretemp_get_pdev(cpu);
661661 struct platform_data *pd;
662662 struct temp_data *tdata;
663
- int indx, target;
663
+ int i, indx = -1, target;
664664
665
- /*
666
- * Don't execute this on suspend as the device remove locks
667
- * up the machine.
668
- */
665
+ /* No need to tear down any interfaces for suspend */
669666 if (cpuhp_tasks_frozen)
670667 return 0;
671668
672669 /* If the physical CPU device does not exist, just return */
673
- if (!pdev)
674
- return 0;
675
-
676
- /* The core id is too big, just return */
677
- indx = TO_ATTR_NO(cpu);
678
- if (indx > MAX_CORE_DATA - 1)
679
- return 0;
680
-
681670 pd = platform_get_drvdata(pdev);
671
+ if (!pd->hwmon_dev)
672
+ return 0;
673
+
674
+ for (i = 0; i < NUM_REAL_CORES; i++) {
675
+ if (pd->cpu_map[i] == topology_core_id(cpu)) {
676
+ indx = i + BASE_SYSFS_ATTR_NO;
677
+ break;
678
+ }
679
+ }
680
+
681
+ /* Too many cores and this core is not populated, just return */
682
+ if (indx < 0)
683
+ return 0;
684
+
682685 tdata = pd->core_data[indx];
683686
684687 cpumask_clear_cpu(cpu, &pd->cpumask);
....@@ -698,13 +701,14 @@
698701 }
699702
700703 /*
701
- * If all cores in this pkg are offline, remove the device. This
702
- * will invoke the platform driver remove function, which cleans up
703
- * the rest.
704
+ * If all cores in this pkg are offline, remove the interface.
704705 */
706
+ tdata = pd->core_data[PKG_SYSFS_ATTR_NO];
705707 if (cpumask_empty(&pd->cpumask)) {
706
- pkg_devices[topology_logical_package_id(cpu)] = NULL;
707
- platform_device_unregister(pdev);
708
+ if (tdata)
709
+ coretemp_remove_core(pd, PKG_SYSFS_ATTR_NO);
710
+ hwmon_device_unregister(pd->hwmon_dev);
711
+ pd->hwmon_dev = NULL;
708712 return 0;
709713 }
710714
....@@ -712,7 +716,6 @@
712716 * Check whether this core is the target for the package
713717 * interface. We need to assign it to some other cpu.
714718 */
715
- tdata = pd->core_data[PKG_SYSFS_ATTR_NO];
716719 if (tdata && tdata->cpu == cpu) {
717720 target = cpumask_first(&pd->cpumask);
718721 mutex_lock(&tdata->update_lock);
....@@ -722,7 +725,7 @@
722725 return 0;
723726 }
724727 static const struct x86_cpu_id __initconst coretemp_ids[] = {
725
- { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM },
728
+ X86_MATCH_VENDOR_FEATURE(INTEL, X86_FEATURE_DTHERM, NULL),
726729 {}
727730 };
728731 MODULE_DEVICE_TABLE(x86cpu, coretemp_ids);
....@@ -731,7 +734,7 @@
731734
732735 static int __init coretemp_init(void)
733736 {
734
- int err;
737
+ int i, err;
735738
736739 /*
737740 * CPUID.06H.EAX[0] indicates whether the CPU has thermal
....@@ -741,35 +744,41 @@
741744 if (!x86_match_cpu(coretemp_ids))
742745 return -ENODEV;
743746
744
- max_packages = topology_max_packages();
745
- pkg_devices = kcalloc(max_packages, sizeof(struct platform_device *),
747
+ max_zones = topology_max_packages() * topology_max_die_per_package();
748
+ zone_devices = kcalloc(max_zones, sizeof(struct platform_device *),
746749 GFP_KERNEL);
747
- if (!pkg_devices)
750
+ if (!zone_devices)
748751 return -ENOMEM;
749752
750
- err = platform_driver_register(&coretemp_driver);
751
- if (err)
752
- return err;
753
+ for (i = 0; i < max_zones; i++) {
754
+ err = coretemp_device_add(i);
755
+ if (err)
756
+ goto outzone;
757
+ }
753758
754759 err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hwmon/coretemp:online",
755760 coretemp_cpu_online, coretemp_cpu_offline);
756761 if (err < 0)
757
- goto outdrv;
762
+ goto outzone;
758763 coretemp_hp_online = err;
759764 return 0;
760765
761
-outdrv:
762
- platform_driver_unregister(&coretemp_driver);
763
- kfree(pkg_devices);
766
+outzone:
767
+ while (i--)
768
+ coretemp_device_remove(i);
769
+ kfree(zone_devices);
764770 return err;
765771 }
766772 module_init(coretemp_init)
767773
768774 static void __exit coretemp_exit(void)
769775 {
776
+ int i;
777
+
770778 cpuhp_remove_state(coretemp_hp_online);
771
- platform_driver_unregister(&coretemp_driver);
772
- kfree(pkg_devices);
779
+ for (i = 0; i < max_zones; i++)
780
+ coretemp_device_remove(i);
781
+ kfree(zone_devices);
773782 }
774783 module_exit(coretemp_exit)
775784