aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-11-22 12:42:06 -0500
committerGuenter Roeck <linux@roeck-us.net>2016-12-10 00:54:13 -0500
commit712668460594294d74c13f2a023398a597fbe95f (patch)
treea58b1e0c9d064ed691bc38c9c362a115244eca04
parent2195c31b127def509c806fe8a9d3b4092a28ce31 (diff)
hwmon: (coretemp) Simplify package management
Keeping track of the per package platform devices requires an extra object, which is held in a linked list. The maximum number of packages is known at init() time. So the extra object and linked list management can be replaced by an array of platform device pointers in which the per package devices pointers can be stored. Lookup becomes a simple array lookup instead of a list walk. The mutex protecting the list can be removed as well because the array is only accessed from cpu hotplug callbacks which are already serialized. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/coretemp.c120
1 files changed, 38 insertions, 82 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index c364bfd92d23..3ac4c03ba77b 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -59,7 +59,6 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
59#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) 59#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
60#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) 60#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
61 61
62#define TO_PHYS_ID(cpu) (cpu_data(cpu).phys_proc_id)
63#define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id) 62#define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id)
64#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO) 63#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
65 64
@@ -104,20 +103,16 @@ struct temp_data {
104/* Platform Data per Physical CPU */ 103/* Platform Data per Physical CPU */
105struct platform_data { 104struct platform_data {
106 struct device *hwmon_dev; 105 struct device *hwmon_dev;
107 u16 phys_proc_id; 106 u16 pkg_id;
108 struct cpumask cpumask; 107 struct cpumask cpumask;
109 struct temp_data *core_data[MAX_CORE_DATA]; 108 struct temp_data *core_data[MAX_CORE_DATA];
110 struct device_attribute name_attr; 109 struct device_attribute name_attr;
111}; 110};
112 111
113struct pdev_entry { 112/* Keep track of how many package pointers we allocated in init() */
114 struct list_head list; 113static int max_packages __read_mostly;
115 struct platform_device *pdev; 114/* Array of package pointers. Serialized by cpu hotplug lock */
116 u16 phys_proc_id; 115static struct platform_device **pkg_devices;
117};
118
119static LIST_HEAD(pdev_list);
120static DEFINE_MUTEX(pdev_list_mutex);
121 116
122static ssize_t show_label(struct device *dev, 117static ssize_t show_label(struct device *dev,
123 struct device_attribute *devattr, char *buf) 118 struct device_attribute *devattr, char *buf)
@@ -127,7 +122,7 @@ static ssize_t show_label(struct device *dev,
127 struct temp_data *tdata = pdata->core_data[attr->index]; 122 struct temp_data *tdata = pdata->core_data[attr->index];
128 123
129 if (tdata->is_pkg_data) 124 if (tdata->is_pkg_data)
130 return sprintf(buf, "Physical id %u\n", pdata->phys_proc_id); 125 return sprintf(buf, "Package id %u\n", pdata->pkg_id);
131 126
132 return sprintf(buf, "Core %u\n", tdata->cpu_core_id); 127 return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
133} 128}
@@ -439,18 +434,10 @@ static int chk_ucode_version(unsigned int cpu)
439 434
440static struct platform_device *coretemp_get_pdev(unsigned int cpu) 435static struct platform_device *coretemp_get_pdev(unsigned int cpu)
441{ 436{
442 u16 phys_proc_id = TO_PHYS_ID(cpu); 437 int pkgid = topology_logical_package_id(cpu);
443 struct pdev_entry *p;
444
445 mutex_lock(&pdev_list_mutex);
446 438
447 list_for_each_entry(p, &pdev_list, list) 439 if (pkgid >= 0 && pkgid < max_packages)
448 if (p->phys_proc_id == phys_proc_id) { 440 return pkg_devices[pkgid];
449 mutex_unlock(&pdev_list_mutex);
450 return p->pdev;
451 }
452
453 mutex_unlock(&pdev_list_mutex);
454 return NULL; 441 return NULL;
455} 442}
456 443
@@ -561,7 +548,7 @@ static int coretemp_probe(struct platform_device *pdev)
561 if (!pdata) 548 if (!pdata)
562 return -ENOMEM; 549 return -ENOMEM;
563 550
564 pdata->phys_proc_id = pdev->id; 551 pdata->pkg_id = pdev->id;
565 platform_set_drvdata(pdev, pdata); 552 platform_set_drvdata(pdev, pdata);
566 553
567 pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME, 554 pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,
@@ -589,64 +576,26 @@ static struct platform_driver coretemp_driver = {
589 .remove = coretemp_remove, 576 .remove = coretemp_remove,
590}; 577};
591 578
592static int coretemp_device_add(unsigned int cpu) 579static struct platform_device *coretemp_device_add(unsigned int cpu)
593{ 580{
594 int err; 581 int err, pkgid = topology_logical_package_id(cpu);
595 struct platform_device *pdev; 582 struct platform_device *pdev;
596 struct pdev_entry *pdev_entry;
597 583
598 mutex_lock(&pdev_list_mutex); 584 if (pkgid < 0)
585 return ERR_PTR(-ENOMEM);
599 586
600 pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu)); 587 pdev = platform_device_alloc(DRVNAME, pkgid);
601 if (!pdev) { 588 if (!pdev)
602 err = -ENOMEM; 589 return ERR_PTR(-ENOMEM);
603 pr_err("Device allocation failed\n");
604 goto exit;
605 }
606
607 pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
608 if (!pdev_entry) {
609 err = -ENOMEM;
610 goto exit_device_put;
611 }
612 590
613 err = platform_device_add(pdev); 591 err = platform_device_add(pdev);
614 if (err) { 592 if (err) {
615 pr_err("Device addition failed (%d)\n", err); 593 platform_device_put(pdev);
616 goto exit_device_free; 594 return ERR_PTR(err);
617 } 595 }
618 596
619 pdev_entry->pdev = pdev; 597 pkg_devices[pkgid] = pdev;
620 pdev_entry->phys_proc_id = pdev->id; 598 return pdev;
621
622 list_add_tail(&pdev_entry->list, &pdev_list);
623 mutex_unlock(&pdev_list_mutex);
624
625 return 0;
626
627exit_device_free:
628 kfree(pdev_entry);
629exit_device_put:
630 platform_device_put(pdev);
631exit:
632 mutex_unlock(&pdev_list_mutex);
633 return err;
634}
635
636static void coretemp_device_remove(unsigned int cpu)
637{
638 struct pdev_entry *p, *n;
639 u16 phys_proc_id = TO_PHYS_ID(cpu);
640
641 mutex_lock(&pdev_list_mutex);
642 list_for_each_entry_safe(p, n, &pdev_list, list) {
643 if (p->phys_proc_id != phys_proc_id)
644 continue;
645 platform_device_unregister(p->pdev);
646 list_del(&p->list);
647 kfree(p);
648 }
649 mutex_unlock(&pdev_list_mutex);
650} 599}
651 600
652static int coretemp_cpu_online(unsigned int cpu) 601static int coretemp_cpu_online(unsigned int cpu)
@@ -654,7 +603,6 @@ static int coretemp_cpu_online(unsigned int cpu)
654 struct platform_device *pdev = coretemp_get_pdev(cpu); 603 struct platform_device *pdev = coretemp_get_pdev(cpu);
655 struct cpuinfo_x86 *c = &cpu_data(cpu); 604 struct cpuinfo_x86 *c = &cpu_data(cpu);
656 struct platform_data *pdata; 605 struct platform_data *pdata;
657 int err;
658 606
659 /* 607 /*
660 * CPUID.06H.EAX[0] indicates whether the CPU has thermal 608 * CPUID.06H.EAX[0] indicates whether the CPU has thermal
@@ -675,11 +623,10 @@ static int coretemp_cpu_online(unsigned int cpu)
675 * online. So, initialize per-pkg data structures and 623 * online. So, initialize per-pkg data structures and
676 * then bring this core online. 624 * then bring this core online.
677 */ 625 */
678 err = coretemp_device_add(cpu); 626 pdev = coretemp_device_add(cpu);
679 if (err) 627 if (IS_ERR(pdev))
680 return err; 628 return PTR_ERR(pdev);
681 629
682 pdev = coretemp_get_pdev(cpu);
683 /* 630 /*
684 * Check whether pkgtemp support is available. 631 * Check whether pkgtemp support is available.
685 * If so, add interfaces for pkgtemp. 632 * If so, add interfaces for pkgtemp.
@@ -736,15 +683,16 @@ static int coretemp_cpu_offline(unsigned int cpu)
736 } 683 }
737 684
738 /* 685 /*
739 * If all cores in this pkg are offline, remove the device. 686 * If all cores in this pkg are offline, remove the device. This
740 * coretemp_device_remove calls unregister_platform_device, 687 * will invoke the platform driver remove function, which cleans up
741 * which in turn calls coretemp_remove. This removes the 688 * the rest.
742 * pkgtemp entry and does other clean ups.
743 */ 689 */
744 if (cpumask_empty(&pd->cpumask)) { 690 if (cpumask_empty(&pd->cpumask)) {
745 coretemp_device_remove(cpu); 691 pkg_devices[topology_logical_package_id(cpu)] = NULL;
692 platform_device_unregister(pdev);
746 return 0; 693 return 0;
747 } 694 }
695
748 /* 696 /*
749 * Check whether this core is the target for the package 697 * Check whether this core is the target for the package
750 * interface. We need to assign it to some other cpu. 698 * interface. We need to assign it to some other cpu.
@@ -778,6 +726,12 @@ static int __init coretemp_init(void)
778 if (!x86_match_cpu(coretemp_ids)) 726 if (!x86_match_cpu(coretemp_ids))
779 return -ENODEV; 727 return -ENODEV;
780 728
729 max_packages = topology_max_packages();
730 pkg_devices = kzalloc(max_packages * sizeof(struct platform_device *),
731 GFP_KERNEL);
732 if (!pkg_devices)
733 return -ENOMEM;
734
781 err = platform_driver_register(&coretemp_driver); 735 err = platform_driver_register(&coretemp_driver);
782 if (err) 736 if (err)
783 return err; 737 return err;
@@ -791,6 +745,7 @@ static int __init coretemp_init(void)
791 745
792outdrv: 746outdrv:
793 platform_driver_unregister(&coretemp_driver); 747 platform_driver_unregister(&coretemp_driver);
748 kfree(pkg_devices);
794 return err; 749 return err;
795} 750}
796module_init(coretemp_init) 751module_init(coretemp_init)
@@ -799,6 +754,7 @@ static void __exit coretemp_exit(void)
799{ 754{
800 cpuhp_remove_state(coretemp_hp_online); 755 cpuhp_remove_state(coretemp_hp_online);
801 platform_driver_unregister(&coretemp_driver); 756 platform_driver_unregister(&coretemp_driver);
757 kfree(pkg_devices);
802} 758}
803module_exit(coretemp_exit) 759module_exit(coretemp_exit)
804 760