|
@@ -59,7 +59,6 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
|
|
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
|
|
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
|
|
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
|
|
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
|
|
|
|
|
|
-#define TO_PHYS_ID(cpu) (cpu_data(cpu).phys_proc_id)
|
|
|
|
#define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id)
|
|
#define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id)
|
|
#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
|
|
#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
|
|
|
|
|
|
@@ -104,20 +103,16 @@ struct temp_data {
|
|
/* Platform Data per Physical CPU */
|
|
/* Platform Data per Physical CPU */
|
|
struct platform_data {
|
|
struct platform_data {
|
|
struct device *hwmon_dev;
|
|
struct device *hwmon_dev;
|
|
- u16 phys_proc_id;
|
|
|
|
|
|
+ u16 pkg_id;
|
|
struct cpumask cpumask;
|
|
struct cpumask cpumask;
|
|
struct temp_data *core_data[MAX_CORE_DATA];
|
|
struct temp_data *core_data[MAX_CORE_DATA];
|
|
struct device_attribute name_attr;
|
|
struct device_attribute name_attr;
|
|
};
|
|
};
|
|
|
|
|
|
-struct pdev_entry {
|
|
|
|
- struct list_head list;
|
|
|
|
- struct platform_device *pdev;
|
|
|
|
- u16 phys_proc_id;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-static LIST_HEAD(pdev_list);
|
|
|
|
-static DEFINE_MUTEX(pdev_list_mutex);
|
|
|
|
|
|
+/* Keep track of how many package pointers we allocated in init() */
|
|
|
|
+static int max_packages __read_mostly;
|
|
|
|
+/* Array of package pointers. Serialized by cpu hotplug lock */
|
|
|
|
+static struct platform_device **pkg_devices;
|
|
|
|
|
|
static ssize_t show_label(struct device *dev,
|
|
static ssize_t show_label(struct device *dev,
|
|
struct device_attribute *devattr, char *buf)
|
|
struct device_attribute *devattr, char *buf)
|
|
@@ -127,7 +122,7 @@ static ssize_t show_label(struct device *dev,
|
|
struct temp_data *tdata = pdata->core_data[attr->index];
|
|
struct temp_data *tdata = pdata->core_data[attr->index];
|
|
|
|
|
|
if (tdata->is_pkg_data)
|
|
if (tdata->is_pkg_data)
|
|
- return sprintf(buf, "Physical id %u\n", pdata->phys_proc_id);
|
|
|
|
|
|
+ return sprintf(buf, "Package id %u\n", pdata->pkg_id);
|
|
|
|
|
|
return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
|
|
return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
|
|
}
|
|
}
|
|
@@ -439,18 +434,10 @@ static int chk_ucode_version(unsigned int cpu)
|
|
|
|
|
|
static struct platform_device *coretemp_get_pdev(unsigned int cpu)
|
|
static struct platform_device *coretemp_get_pdev(unsigned int cpu)
|
|
{
|
|
{
|
|
- u16 phys_proc_id = TO_PHYS_ID(cpu);
|
|
|
|
- struct pdev_entry *p;
|
|
|
|
-
|
|
|
|
- mutex_lock(&pdev_list_mutex);
|
|
|
|
|
|
+ int pkgid = topology_logical_package_id(cpu);
|
|
|
|
|
|
- list_for_each_entry(p, &pdev_list, list)
|
|
|
|
- if (p->phys_proc_id == phys_proc_id) {
|
|
|
|
- mutex_unlock(&pdev_list_mutex);
|
|
|
|
- return p->pdev;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- mutex_unlock(&pdev_list_mutex);
|
|
|
|
|
|
+ if (pkgid >= 0 && pkgid < max_packages)
|
|
|
|
+ return pkg_devices[pkgid];
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -561,7 +548,7 @@ static int coretemp_probe(struct platform_device *pdev)
|
|
if (!pdata)
|
|
if (!pdata)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
- pdata->phys_proc_id = pdev->id;
|
|
|
|
|
|
+ pdata->pkg_id = pdev->id;
|
|
platform_set_drvdata(pdev, pdata);
|
|
platform_set_drvdata(pdev, pdata);
|
|
|
|
|
|
pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,
|
|
pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,
|
|
@@ -589,64 +576,26 @@ static struct platform_driver coretemp_driver = {
|
|
.remove = coretemp_remove,
|
|
.remove = coretemp_remove,
|
|
};
|
|
};
|
|
|
|
|
|
-static int coretemp_device_add(unsigned int cpu)
|
|
|
|
|
|
+static struct platform_device *coretemp_device_add(unsigned int cpu)
|
|
{
|
|
{
|
|
- int err;
|
|
|
|
|
|
+ int err, pkgid = topology_logical_package_id(cpu);
|
|
struct platform_device *pdev;
|
|
struct platform_device *pdev;
|
|
- struct pdev_entry *pdev_entry;
|
|
|
|
|
|
|
|
- mutex_lock(&pdev_list_mutex);
|
|
|
|
|
|
+ if (pkgid < 0)
|
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
- pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu));
|
|
|
|
- if (!pdev) {
|
|
|
|
- err = -ENOMEM;
|
|
|
|
- pr_err("Device allocation failed\n");
|
|
|
|
- goto exit;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
|
|
|
|
- if (!pdev_entry) {
|
|
|
|
- err = -ENOMEM;
|
|
|
|
- goto exit_device_put;
|
|
|
|
- }
|
|
|
|
|
|
+ pdev = platform_device_alloc(DRVNAME, pkgid);
|
|
|
|
+ if (!pdev)
|
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
err = platform_device_add(pdev);
|
|
err = platform_device_add(pdev);
|
|
if (err) {
|
|
if (err) {
|
|
- pr_err("Device addition failed (%d)\n", err);
|
|
|
|
- goto exit_device_free;
|
|
|
|
|
|
+ platform_device_put(pdev);
|
|
|
|
+ return ERR_PTR(err);
|
|
}
|
|
}
|
|
|
|
|
|
- pdev_entry->pdev = pdev;
|
|
|
|
- pdev_entry->phys_proc_id = pdev->id;
|
|
|
|
-
|
|
|
|
- list_add_tail(&pdev_entry->list, &pdev_list);
|
|
|
|
- mutex_unlock(&pdev_list_mutex);
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
-exit_device_free:
|
|
|
|
- kfree(pdev_entry);
|
|
|
|
-exit_device_put:
|
|
|
|
- platform_device_put(pdev);
|
|
|
|
-exit:
|
|
|
|
- mutex_unlock(&pdev_list_mutex);
|
|
|
|
- return err;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void coretemp_device_remove(unsigned int cpu)
|
|
|
|
-{
|
|
|
|
- struct pdev_entry *p, *n;
|
|
|
|
- u16 phys_proc_id = TO_PHYS_ID(cpu);
|
|
|
|
-
|
|
|
|
- mutex_lock(&pdev_list_mutex);
|
|
|
|
- list_for_each_entry_safe(p, n, &pdev_list, list) {
|
|
|
|
- if (p->phys_proc_id != phys_proc_id)
|
|
|
|
- continue;
|
|
|
|
- platform_device_unregister(p->pdev);
|
|
|
|
- list_del(&p->list);
|
|
|
|
- kfree(p);
|
|
|
|
- }
|
|
|
|
- mutex_unlock(&pdev_list_mutex);
|
|
|
|
|
|
+ pkg_devices[pkgid] = pdev;
|
|
|
|
+ return pdev;
|
|
}
|
|
}
|
|
|
|
|
|
static int coretemp_cpu_online(unsigned int cpu)
|
|
static int coretemp_cpu_online(unsigned int cpu)
|
|
@@ -654,7 +603,6 @@ static int coretemp_cpu_online(unsigned int cpu)
|
|
struct platform_device *pdev = coretemp_get_pdev(cpu);
|
|
struct platform_device *pdev = coretemp_get_pdev(cpu);
|
|
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
|
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
|
struct platform_data *pdata;
|
|
struct platform_data *pdata;
|
|
- int err;
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
* CPUID.06H.EAX[0] indicates whether the CPU has thermal
|
|
* CPUID.06H.EAX[0] indicates whether the CPU has thermal
|
|
@@ -675,11 +623,10 @@ static int coretemp_cpu_online(unsigned int cpu)
|
|
* online. So, initialize per-pkg data structures and
|
|
* online. So, initialize per-pkg data structures and
|
|
* then bring this core online.
|
|
* then bring this core online.
|
|
*/
|
|
*/
|
|
- err = coretemp_device_add(cpu);
|
|
|
|
- if (err)
|
|
|
|
- return err;
|
|
|
|
|
|
+ pdev = coretemp_device_add(cpu);
|
|
|
|
+ if (IS_ERR(pdev))
|
|
|
|
+ return PTR_ERR(pdev);
|
|
|
|
|
|
- pdev = coretemp_get_pdev(cpu);
|
|
|
|
/*
|
|
/*
|
|
* Check whether pkgtemp support is available.
|
|
* Check whether pkgtemp support is available.
|
|
* If so, add interfaces for pkgtemp.
|
|
* If so, add interfaces for pkgtemp.
|
|
@@ -736,15 +683,16 @@ static int coretemp_cpu_offline(unsigned int cpu)
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * If all cores in this pkg are offline, remove the device.
|
|
|
|
- * coretemp_device_remove calls unregister_platform_device,
|
|
|
|
- * which in turn calls coretemp_remove. This removes the
|
|
|
|
- * pkgtemp entry and does other clean ups.
|
|
|
|
|
|
+ * If all cores in this pkg are offline, remove the device. This
|
|
|
|
+ * will invoke the platform driver remove function, which cleans up
|
|
|
|
+ * the rest.
|
|
*/
|
|
*/
|
|
if (cpumask_empty(&pd->cpumask)) {
|
|
if (cpumask_empty(&pd->cpumask)) {
|
|
- coretemp_device_remove(cpu);
|
|
|
|
|
|
+ pkg_devices[topology_logical_package_id(cpu)] = NULL;
|
|
|
|
+ platform_device_unregister(pdev);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Check whether this core is the target for the package
|
|
* Check whether this core is the target for the package
|
|
* interface. We need to assign it to some other cpu.
|
|
* interface. We need to assign it to some other cpu.
|
|
@@ -778,6 +726,12 @@ static int __init coretemp_init(void)
|
|
if (!x86_match_cpu(coretemp_ids))
|
|
if (!x86_match_cpu(coretemp_ids))
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ max_packages = topology_max_packages();
|
|
|
|
+ pkg_devices = kzalloc(max_packages * sizeof(struct platform_device *),
|
|
|
|
+ GFP_KERNEL);
|
|
|
|
+ if (!pkg_devices)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
err = platform_driver_register(&coretemp_driver);
|
|
err = platform_driver_register(&coretemp_driver);
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
@@ -791,6 +745,7 @@ static int __init coretemp_init(void)
|
|
|
|
|
|
outdrv:
|
|
outdrv:
|
|
platform_driver_unregister(&coretemp_driver);
|
|
platform_driver_unregister(&coretemp_driver);
|
|
|
|
+ kfree(pkg_devices);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
module_init(coretemp_init)
|
|
module_init(coretemp_init)
|
|
@@ -799,6 +754,7 @@ static void __exit coretemp_exit(void)
|
|
{
|
|
{
|
|
cpuhp_remove_state(coretemp_hp_online);
|
|
cpuhp_remove_state(coretemp_hp_online);
|
|
platform_driver_unregister(&coretemp_driver);
|
|
platform_driver_unregister(&coretemp_driver);
|
|
|
|
+ kfree(pkg_devices);
|
|
}
|
|
}
|
|
module_exit(coretemp_exit)
|
|
module_exit(coretemp_exit)
|
|
|
|
|