aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2011-05-20 10:28:06 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2011-05-21 10:22:10 -0400
commit5e99c2f1e0c86d27ed2a5261442126cd0935bc69 (patch)
treed18e443f9baee186c6c26b344cfdd0d166d82278
parent199e0de7f5df31a4fc485d4aaaf8a07718252ace (diff)
hwmon: Remove pkgtemp driver
After the merge of pkgtemp functionality into the coretemp driver, the pkgtemp driver is no longer necessary. Remove it. Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Acked-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--Documentation/hwmon/pkgtemp36
-rw-r--r--drivers/hwmon/Kconfig7
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/pkgtemp.c444
4 files changed, 0 insertions, 488 deletions
diff --git a/Documentation/hwmon/pkgtemp b/Documentation/hwmon/pkgtemp
deleted file mode 100644
index c8e1fb0fadd3..000000000000
--- a/Documentation/hwmon/pkgtemp
+++ /dev/null
@@ -1,36 +0,0 @@
1Kernel driver pkgtemp
2======================
3
4Supported chips:
5 * Intel family
6 Prefix: 'pkgtemp'
7 CPUID:
8 Datasheet: Intel 64 and IA-32 Architectures Software Developer's Manual
9 Volume 3A: System Programming Guide
10
11Author: Fenghua Yu
12
13Description
14-----------
15
16This driver permits reading package level temperature sensor embedded inside
17Intel CPU package. The sensors can be in core, uncore, memory controller, or
18other components in a package. The feature is first implemented in Intel Sandy
19Bridge platform.
20
21Temperature is measured in degrees Celsius and measurement resolution is
221 degree C. Valid temperatures are from 0 to TjMax degrees C, because the actual
23value of temperature register is in fact a delta from TjMax.
24
25Temperature known as TjMax is the maximum junction temperature of package.
26We get this from MSR_IA32_TEMPERATURE_TARGET. If the MSR is not accessible,
27we define TjMax as 100 degrees Celsius. At this temperature, protection
28mechanism will perform actions to forcibly cool down the package. Alarm
29may be raised, if the temperature grows enough (more than TjMax) to trigger
30the Out-Of-Spec bit. Following table summarizes the exported sysfs files:
31
32temp1_input - Package temperature (in millidegrees Celsius).
33temp1_max - All cooling devices should be turned on.
34temp1_crit - Maximum junction temperature (in millidegrees Celsius).
35temp1_crit_alarm - Set when Out-of-spec bit is set, never clears.
36 Correct CPU operation is no longer guaranteed.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4abd3735a76e..43221beb9e97 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -408,13 +408,6 @@ config SENSORS_CORETEMP
408 sensor inside your CPU. Most of the family 6 CPUs 408 sensor inside your CPU. Most of the family 6 CPUs
409 are supported. Check Documentation/hwmon/coretemp for details. 409 are supported. Check Documentation/hwmon/coretemp for details.
410 410
411config SENSORS_PKGTEMP
412 tristate "Intel processor package temperature sensor"
413 depends on X86 && EXPERIMENTAL
414 help
415 If you say yes here you get support for the package level temperature
416 sensor inside your CPU. Check documentation/driver for details.
417
418config SENSORS_IBMAEM 411config SENSORS_IBMAEM
419 tristate "IBM Active Energy Manager temperature/power sensors and control" 412 tristate "IBM Active Energy Manager temperature/power sensors and control"
420 select IPMI_SI 413 select IPMI_SI
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 21c9b17abad5..28e8d52f6379 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -40,7 +40,6 @@ obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
40obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o 40obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
41obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o 41obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
42obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o 42obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
43obj-$(CONFIG_SENSORS_PKGTEMP) += pkgtemp.o
44obj-$(CONFIG_SENSORS_DME1737) += dme1737.o 43obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
45obj-$(CONFIG_SENSORS_DS620) += ds620.o 44obj-$(CONFIG_SENSORS_DS620) += ds620.o
46obj-$(CONFIG_SENSORS_DS1621) += ds1621.o 45obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
diff --git a/drivers/hwmon/pkgtemp.c b/drivers/hwmon/pkgtemp.c
deleted file mode 100644
index 21c817d98123..000000000000
--- a/drivers/hwmon/pkgtemp.c
+++ /dev/null
@@ -1,444 +0,0 @@
1/*
2 * pkgtemp.c - Linux kernel module for processor package hardware monitoring
3 *
4 * Copyright (C) 2010 Fenghua Yu <fenghua.yu@intel.com>
5 *
6 * Inspired from many hwmon drivers especially coretemp.
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.
21 */
22
23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/slab.h>
28#include <linux/jiffies.h>
29#include <linux/hwmon.h>
30#include <linux/sysfs.h>
31#include <linux/hwmon-sysfs.h>
32#include <linux/err.h>
33#include <linux/mutex.h>
34#include <linux/list.h>
35#include <linux/platform_device.h>
36#include <linux/cpu.h>
37#include <asm/msr.h>
38#include <asm/processor.h>
39#include <asm/smp.h>
40
41#define DRVNAME "pkgtemp"
42
43enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL, SHOW_NAME };
44
45/*
46 * Functions declaration
47 */
48
49static struct pkgtemp_data *pkgtemp_update_device(struct device *dev);
50
51struct pkgtemp_data {
52 struct device *hwmon_dev;
53 struct mutex update_lock;
54 const char *name;
55 u32 id;
56 u16 phys_proc_id;
57 char valid; /* zero until following fields are valid */
58 unsigned long last_updated; /* in jiffies */
59 int temp;
60 int tjmax;
61 int ttarget;
62 u8 alarm;
63};
64
65/*
66 * Sysfs stuff
67 */
68
69static ssize_t show_name(struct device *dev, struct device_attribute
70 *devattr, char *buf)
71{
72 int ret;
73 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
74 struct pkgtemp_data *data = dev_get_drvdata(dev);
75
76 if (attr->index == SHOW_NAME)
77 ret = sprintf(buf, "%s\n", data->name);
78 else /* show label */
79 ret = sprintf(buf, "physical id %d\n",
80 data->phys_proc_id);
81 return ret;
82}
83
84static ssize_t show_alarm(struct device *dev, struct device_attribute
85 *devattr, char *buf)
86{
87 struct pkgtemp_data *data = pkgtemp_update_device(dev);
88 /* read the Out-of-spec log, never clear */
89 return sprintf(buf, "%d\n", data->alarm);
90}
91
92static ssize_t show_temp(struct device *dev,
93 struct device_attribute *devattr, char *buf)
94{
95 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
96 struct pkgtemp_data *data = pkgtemp_update_device(dev);
97 int err = 0;
98
99 if (attr->index == SHOW_TEMP)
100 err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN;
101 else if (attr->index == SHOW_TJMAX)
102 err = sprintf(buf, "%d\n", data->tjmax);
103 else
104 err = sprintf(buf, "%d\n", data->ttarget);
105 return err;
106}
107
108static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, SHOW_TEMP);
109static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, SHOW_TJMAX);
110static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, SHOW_TTARGET);
111static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
112static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
113static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
114
115static struct attribute *pkgtemp_attributes[] = {
116 &sensor_dev_attr_name.dev_attr.attr,
117 &sensor_dev_attr_temp1_label.dev_attr.attr,
118 &dev_attr_temp1_crit_alarm.attr,
119 &sensor_dev_attr_temp1_input.dev_attr.attr,
120 &sensor_dev_attr_temp1_crit.dev_attr.attr,
121 NULL
122};
123
124static const struct attribute_group pkgtemp_group = {
125 .attrs = pkgtemp_attributes,
126};
127
128static struct pkgtemp_data *pkgtemp_update_device(struct device *dev)
129{
130 struct pkgtemp_data *data = dev_get_drvdata(dev);
131 unsigned int cpu;
132 int err;
133
134 mutex_lock(&data->update_lock);
135
136 if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
137 u32 eax, edx;
138
139 data->valid = 0;
140 cpu = data->id;
141 err = rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_STATUS,
142 &eax, &edx);
143 if (!err) {
144 data->alarm = (eax >> 5) & 1;
145 data->temp = data->tjmax - (((eax >> 16)
146 & 0x7f) * 1000);
147 data->valid = 1;
148 } else
149 dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax);
150
151 data->last_updated = jiffies;
152 }
153
154 mutex_unlock(&data->update_lock);
155 return data;
156}
157
158static int get_tjmax(int cpu, struct device *dev)
159{
160 int default_tjmax = 100000;
161 int err;
162 u32 eax, edx;
163 u32 val;
164
165 /* IA32_TEMPERATURE_TARGET contains the TjMax value */
166 err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
167 if (!err) {
168 val = (eax >> 16) & 0xff;
169 if ((val > 80) && (val < 120)) {
170 dev_info(dev, "TjMax is %d C.\n", val);
171 return val * 1000;
172 }
173 }
174 dev_warn(dev, "Unable to read TjMax from CPU.\n");
175 return default_tjmax;
176}
177
178static int __devinit pkgtemp_probe(struct platform_device *pdev)
179{
180 struct pkgtemp_data *data;
181 int err;
182 u32 eax, edx;
183#ifdef CONFIG_SMP
184 struct cpuinfo_x86 *c = &cpu_data(pdev->id);
185#endif
186
187 data = kzalloc(sizeof(struct pkgtemp_data), GFP_KERNEL);
188 if (!data) {
189 err = -ENOMEM;
190 dev_err(&pdev->dev, "Out of memory\n");
191 goto exit;
192 }
193
194 data->id = pdev->id;
195#ifdef CONFIG_SMP
196 data->phys_proc_id = c->phys_proc_id;
197#endif
198 data->name = "pkgtemp";
199 mutex_init(&data->update_lock);
200
201 /* test if we can access the THERM_STATUS MSR */
202 err = rdmsr_safe_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_STATUS,
203 &eax, &edx);
204 if (err) {
205 dev_err(&pdev->dev,
206 "Unable to access THERM_STATUS MSR, giving up\n");
207 goto exit_free;
208 }
209
210 data->tjmax = get_tjmax(data->id, &pdev->dev);
211 platform_set_drvdata(pdev, data);
212
213 err = rdmsr_safe_on_cpu(data->id, MSR_IA32_TEMPERATURE_TARGET,
214 &eax, &edx);
215 if (err) {
216 dev_warn(&pdev->dev, "Unable to read"
217 " IA32_TEMPERATURE_TARGET MSR\n");
218 } else {
219 data->ttarget = data->tjmax - (((eax >> 8) & 0xff) * 1000);
220 err = device_create_file(&pdev->dev,
221 &sensor_dev_attr_temp1_max.dev_attr);
222 if (err)
223 goto exit_free;
224 }
225
226 err = sysfs_create_group(&pdev->dev.kobj, &pkgtemp_group);
227 if (err)
228 goto exit_dev;
229
230 data->hwmon_dev = hwmon_device_register(&pdev->dev);
231 if (IS_ERR(data->hwmon_dev)) {
232 err = PTR_ERR(data->hwmon_dev);
233 dev_err(&pdev->dev, "Class registration failed (%d)\n",
234 err);
235 goto exit_class;
236 }
237
238 return 0;
239
240exit_class:
241 sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
242exit_dev:
243 device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
244exit_free:
245 kfree(data);
246exit:
247 return err;
248}
249
250static int __devexit pkgtemp_remove(struct platform_device *pdev)
251{
252 struct pkgtemp_data *data = platform_get_drvdata(pdev);
253
254 hwmon_device_unregister(data->hwmon_dev);
255 sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
256 device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
257 platform_set_drvdata(pdev, NULL);
258 kfree(data);
259 return 0;
260}
261
262static struct platform_driver pkgtemp_driver = {
263 .driver = {
264 .owner = THIS_MODULE,
265 .name = DRVNAME,
266 },
267 .probe = pkgtemp_probe,
268 .remove = __devexit_p(pkgtemp_remove),
269};
270
271struct pdev_entry {
272 struct list_head list;
273 struct platform_device *pdev;
274 unsigned int cpu;
275#ifdef CONFIG_SMP
276 u16 phys_proc_id;
277#endif
278};
279
280static LIST_HEAD(pdev_list);
281static DEFINE_MUTEX(pdev_list_mutex);
282
283static int __cpuinit pkgtemp_device_add(unsigned int cpu)
284{
285 int err;
286 struct platform_device *pdev;
287 struct pdev_entry *pdev_entry;
288 struct cpuinfo_x86 *c = &cpu_data(cpu);
289
290 if (!cpu_has(c, X86_FEATURE_PTS))
291 return 0;
292
293 mutex_lock(&pdev_list_mutex);
294
295#ifdef CONFIG_SMP
296 /* Only keep the first entry in each package */
297 list_for_each_entry(pdev_entry, &pdev_list, list) {
298 if (c->phys_proc_id == pdev_entry->phys_proc_id) {
299 err = 0; /* Not an error */
300 goto exit;
301 }
302 }
303#endif
304
305 pdev = platform_device_alloc(DRVNAME, cpu);
306 if (!pdev) {
307 err = -ENOMEM;
308 pr_err("Device allocation failed\n");
309 goto exit;
310 }
311
312 pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
313 if (!pdev_entry) {
314 err = -ENOMEM;
315 goto exit_device_put;
316 }
317
318 err = platform_device_add(pdev);
319 if (err) {
320 pr_err("Device addition failed (%d)\n", err);
321 goto exit_device_free;
322 }
323
324#ifdef CONFIG_SMP
325 pdev_entry->phys_proc_id = c->phys_proc_id;
326#endif
327 pdev_entry->pdev = pdev;
328 pdev_entry->cpu = cpu;
329 list_add_tail(&pdev_entry->list, &pdev_list);
330 mutex_unlock(&pdev_list_mutex);
331
332 return 0;
333
334exit_device_free:
335 kfree(pdev_entry);
336exit_device_put:
337 platform_device_put(pdev);
338exit:
339 mutex_unlock(&pdev_list_mutex);
340 return err;
341}
342
343static void __cpuinit pkgtemp_device_remove(unsigned int cpu)
344{
345 struct pdev_entry *p;
346 unsigned int i;
347 int err;
348
349 mutex_lock(&pdev_list_mutex);
350 list_for_each_entry(p, &pdev_list, list) {
351 if (p->cpu != cpu)
352 continue;
353
354 platform_device_unregister(p->pdev);
355 list_del(&p->list);
356 mutex_unlock(&pdev_list_mutex);
357 kfree(p);
358 for_each_cpu(i, cpu_core_mask(cpu)) {
359 if (i != cpu) {
360 err = pkgtemp_device_add(i);
361 if (!err)
362 break;
363 }
364 }
365 return;
366 }
367 mutex_unlock(&pdev_list_mutex);
368}
369
370static int __cpuinit pkgtemp_cpu_callback(struct notifier_block *nfb,
371 unsigned long action, void *hcpu)
372{
373 unsigned int cpu = (unsigned long) hcpu;
374
375 switch (action) {
376 case CPU_ONLINE:
377 case CPU_DOWN_FAILED:
378 pkgtemp_device_add(cpu);
379 break;
380 case CPU_DOWN_PREPARE:
381 pkgtemp_device_remove(cpu);
382 break;
383 }
384 return NOTIFY_OK;
385}
386
387static struct notifier_block pkgtemp_cpu_notifier __refdata = {
388 .notifier_call = pkgtemp_cpu_callback,
389};
390
391static int __init pkgtemp_init(void)
392{
393 int i, err = -ENODEV;
394
395 /* quick check if we run Intel */
396 if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
397 goto exit;
398
399 err = platform_driver_register(&pkgtemp_driver);
400 if (err)
401 goto exit;
402
403 for_each_online_cpu(i)
404 pkgtemp_device_add(i);
405
406#ifndef CONFIG_HOTPLUG_CPU
407 if (list_empty(&pdev_list)) {
408 err = -ENODEV;
409 goto exit_driver_unreg;
410 }
411#endif
412
413 register_hotcpu_notifier(&pkgtemp_cpu_notifier);
414 return 0;
415
416#ifndef CONFIG_HOTPLUG_CPU
417exit_driver_unreg:
418 platform_driver_unregister(&pkgtemp_driver);
419#endif
420exit:
421 return err;
422}
423
424static void __exit pkgtemp_exit(void)
425{
426 struct pdev_entry *p, *n;
427
428 unregister_hotcpu_notifier(&pkgtemp_cpu_notifier);
429 mutex_lock(&pdev_list_mutex);
430 list_for_each_entry_safe(p, n, &pdev_list, list) {
431 platform_device_unregister(p->pdev);
432 list_del(&p->list);
433 kfree(p);
434 }
435 mutex_unlock(&pdev_list_mutex);
436 platform_driver_unregister(&pkgtemp_driver);
437}
438
439MODULE_AUTHOR("Fenghua Yu <fenghua.yu@intel.com>");
440MODULE_DESCRIPTION("Intel processor package temperature monitor");
441MODULE_LICENSE("GPL");
442
443module_init(pkgtemp_init)
444module_exit(pkgtemp_exit)