]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/hwmon/pkgtemp.c
f7ddee5fe9d5b17d7b90fd6b91d17249f4ff8ede
[net-next-2.6.git] / drivers / hwmon / pkgtemp.c
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 #include <linux/module.h>
24 #include <linux/delay.h>
25 #include <linux/init.h>
26 #include <linux/slab.h>
27 #include <linux/jiffies.h>
28 #include <linux/hwmon.h>
29 #include <linux/sysfs.h>
30 #include <linux/hwmon-sysfs.h>
31 #include <linux/err.h>
32 #include <linux/mutex.h>
33 #include <linux/list.h>
34 #include <linux/platform_device.h>
35 #include <linux/cpu.h>
36 #include <linux/pci.h>
37 #include <asm/msr.h>
38 #include <asm/processor.h>
39
40 #define DRVNAME "pkgtemp"
41
42 enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL, SHOW_NAME };
43
44 /*
45  * Functions declaration
46  */
47
48 static struct pkgtemp_data *pkgtemp_update_device(struct device *dev);
49
50 struct pkgtemp_data {
51         struct device *hwmon_dev;
52         struct mutex update_lock;
53         const char *name;
54         u32 id;
55         u16 phys_proc_id;
56         char valid;             /* zero until following fields are valid */
57         unsigned long last_updated;     /* in jiffies */
58         int temp;
59         int tjmax;
60         int ttarget;
61         u8 alarm;
62 };
63
64 /*
65  * Sysfs stuff
66  */
67
68 static ssize_t show_name(struct device *dev, struct device_attribute
69                           *devattr, char *buf)
70 {
71         int ret;
72         struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
73         struct pkgtemp_data *data = dev_get_drvdata(dev);
74
75         if (attr->index == SHOW_NAME)
76                 ret = sprintf(buf, "%s\n", data->name);
77         else    /* show label */
78                 ret = sprintf(buf, "physical id %d\n",
79                               data->phys_proc_id);
80         return ret;
81 }
82
83 static ssize_t show_alarm(struct device *dev, struct device_attribute
84                           *devattr, char *buf)
85 {
86         struct pkgtemp_data *data = pkgtemp_update_device(dev);
87         /* read the Out-of-spec log, never clear */
88         return sprintf(buf, "%d\n", data->alarm);
89 }
90
91 static ssize_t show_temp(struct device *dev,
92                          struct device_attribute *devattr, char *buf)
93 {
94         struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
95         struct pkgtemp_data *data = pkgtemp_update_device(dev);
96         int err = 0;
97
98         if (attr->index == SHOW_TEMP)
99                 err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN;
100         else if (attr->index == SHOW_TJMAX)
101                 err = sprintf(buf, "%d\n", data->tjmax);
102         else
103                 err = sprintf(buf, "%d\n", data->ttarget);
104         return err;
105 }
106
107 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, SHOW_TEMP);
108 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, SHOW_TJMAX);
109 static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, SHOW_TTARGET);
110 static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
111 static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
112 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
113
114 static struct attribute *pkgtemp_attributes[] = {
115         &sensor_dev_attr_name.dev_attr.attr,
116         &sensor_dev_attr_temp1_label.dev_attr.attr,
117         &dev_attr_temp1_crit_alarm.attr,
118         &sensor_dev_attr_temp1_input.dev_attr.attr,
119         &sensor_dev_attr_temp1_crit.dev_attr.attr,
120         NULL
121 };
122
123 static const struct attribute_group pkgtemp_group = {
124         .attrs = pkgtemp_attributes,
125 };
126
127 static struct pkgtemp_data *pkgtemp_update_device(struct device *dev)
128 {
129         struct pkgtemp_data *data = dev_get_drvdata(dev);
130         unsigned int cpu;
131         int err;
132
133         mutex_lock(&data->update_lock);
134
135         if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
136                 u32 eax, edx;
137
138                 data->valid = 0;
139                 cpu = data->id;
140                 err = rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_STATUS,
141                                    &eax, &edx);
142                 if (!err) {
143                         data->alarm = (eax >> 5) & 1;
144                         data->temp = data->tjmax - (((eax >> 16)
145                                                         & 0x7f) * 1000);
146                         data->valid = 1;
147                 } else
148                         dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax);
149
150                 data->last_updated = jiffies;
151         }
152
153         mutex_unlock(&data->update_lock);
154         return data;
155 }
156
157 static int get_tjmax(int cpu, struct device *dev)
158 {
159         int default_tjmax = 100000;
160         int err;
161         u32 eax, edx;
162         u32 val;
163
164         /* IA32_TEMPERATURE_TARGET contains the TjMax value */
165         err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
166         if (!err) {
167                 val = (eax >> 16) & 0xff;
168                 if ((val > 80) && (val < 120)) {
169                         dev_info(dev, "TjMax is %d C.\n", val);
170                         return val * 1000;
171                 }
172         }
173         dev_warn(dev, "Unable to read TjMax from CPU.\n");
174         return default_tjmax;
175 }
176
177 static int __devinit pkgtemp_probe(struct platform_device *pdev)
178 {
179         struct pkgtemp_data *data;
180         int err;
181         u32 eax, edx;
182 #ifdef CONFIG_SMP
183         struct cpuinfo_x86 *c = &cpu_data(pdev->id);
184 #endif
185
186         data = kzalloc(sizeof(struct pkgtemp_data), GFP_KERNEL);
187         if (!data) {
188                 err = -ENOMEM;
189                 dev_err(&pdev->dev, "Out of memory\n");
190                 goto exit;
191         }
192
193         data->id = pdev->id;
194 #ifdef CONFIG_SMP
195         data->phys_proc_id = c->phys_proc_id;
196 #endif
197         data->name = "pkgtemp";
198         mutex_init(&data->update_lock);
199
200         /* test if we can access the THERM_STATUS MSR */
201         err = rdmsr_safe_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_STATUS,
202                                 &eax, &edx);
203         if (err) {
204                 dev_err(&pdev->dev,
205                         "Unable to access THERM_STATUS MSR, giving up\n");
206                 goto exit_free;
207         }
208
209         data->tjmax = get_tjmax(data->id, &pdev->dev);
210         platform_set_drvdata(pdev, data);
211
212         err = rdmsr_safe_on_cpu(data->id, MSR_IA32_TEMPERATURE_TARGET,
213                                 &eax, &edx);
214         if (err) {
215                 dev_warn(&pdev->dev, "Unable to read"
216                                 " IA32_TEMPERATURE_TARGET MSR\n");
217         } else {
218                 data->ttarget = data->tjmax - (((eax >> 8) & 0xff) * 1000);
219                 err = device_create_file(&pdev->dev,
220                                 &sensor_dev_attr_temp1_max.dev_attr);
221                 if (err)
222                         goto exit_free;
223         }
224
225         err = sysfs_create_group(&pdev->dev.kobj, &pkgtemp_group);
226         if (err)
227                 goto exit_dev;
228
229         data->hwmon_dev = hwmon_device_register(&pdev->dev);
230         if (IS_ERR(data->hwmon_dev)) {
231                 err = PTR_ERR(data->hwmon_dev);
232                 dev_err(&pdev->dev, "Class registration failed (%d)\n",
233                         err);
234                 goto exit_class;
235         }
236
237         return 0;
238
239 exit_class:
240         sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
241 exit_dev:
242         device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
243 exit_free:
244         kfree(data);
245 exit:
246         return err;
247 }
248
249 static int __devexit pkgtemp_remove(struct platform_device *pdev)
250 {
251         struct pkgtemp_data *data = platform_get_drvdata(pdev);
252
253         hwmon_device_unregister(data->hwmon_dev);
254         sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
255         device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
256         platform_set_drvdata(pdev, NULL);
257         kfree(data);
258         return 0;
259 }
260
261 static struct platform_driver pkgtemp_driver = {
262         .driver = {
263                 .owner = THIS_MODULE,
264                 .name = DRVNAME,
265         },
266         .probe = pkgtemp_probe,
267         .remove = __devexit_p(pkgtemp_remove),
268 };
269
270 struct pdev_entry {
271         struct list_head list;
272         struct platform_device *pdev;
273         unsigned int cpu;
274 #ifdef CONFIG_SMP
275         u16 phys_proc_id;
276 #endif
277 };
278
279 static LIST_HEAD(pdev_list);
280 static DEFINE_MUTEX(pdev_list_mutex);
281
282 static int __cpuinit pkgtemp_device_add(unsigned int cpu)
283 {
284         int err;
285         struct platform_device *pdev;
286         struct pdev_entry *pdev_entry;
287 #ifdef CONFIG_SMP
288         struct cpuinfo_x86 *c = &cpu_data(cpu);
289 #endif
290
291         mutex_lock(&pdev_list_mutex);
292
293 #ifdef CONFIG_SMP
294         /* Only keep the first entry in each package */
295         list_for_each_entry(pdev_entry, &pdev_list, list) {
296                 if (c->phys_proc_id == pdev_entry->phys_proc_id) {
297                         err = 0;        /* Not an error */
298                         goto exit;
299                 }
300         }
301 #endif
302
303         pdev = platform_device_alloc(DRVNAME, cpu);
304         if (!pdev) {
305                 err = -ENOMEM;
306                 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
307                 goto exit;
308         }
309
310         pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
311         if (!pdev_entry) {
312                 err = -ENOMEM;
313                 goto exit_device_put;
314         }
315
316         err = platform_device_add(pdev);
317         if (err) {
318                 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
319                        err);
320                 goto exit_device_free;
321         }
322
323 #ifdef CONFIG_SMP
324         pdev_entry->phys_proc_id = c->phys_proc_id;
325 #endif
326         pdev_entry->pdev = pdev;
327         pdev_entry->cpu = cpu;
328         list_add_tail(&pdev_entry->list, &pdev_list);
329         mutex_unlock(&pdev_list_mutex);
330
331         return 0;
332
333 exit_device_free:
334         kfree(pdev_entry);
335 exit_device_put:
336         platform_device_put(pdev);
337 exit:
338         mutex_unlock(&pdev_list_mutex);
339         return err;
340 }
341
342 #ifdef CONFIG_HOTPLUG_CPU
343 static void 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
370 static 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
387 static struct notifier_block pkgtemp_cpu_notifier __refdata = {
388         .notifier_call = pkgtemp_cpu_callback,
389 };
390 #endif                          /* !CONFIG_HOTPLUG_CPU */
391
392 static int __init pkgtemp_init(void)
393 {
394         int i, err = -ENODEV;
395         struct pdev_entry *p, *n;
396
397         /* quick check if we run Intel */
398         if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
399                 goto exit;
400
401         err = platform_driver_register(&pkgtemp_driver);
402         if (err)
403                 goto exit;
404
405         for_each_online_cpu(i) {
406                 struct cpuinfo_x86 *c = &cpu_data(i);
407
408                 if (!cpu_has(c, X86_FEATURE_PTS))
409                         continue;
410
411                 err = pkgtemp_device_add(i);
412                 if (err)
413                         goto exit_devices_unreg;
414         }
415         if (list_empty(&pdev_list)) {
416                 err = -ENODEV;
417                 goto exit_driver_unreg;
418         }
419
420 #ifdef CONFIG_HOTPLUG_CPU
421         register_hotcpu_notifier(&pkgtemp_cpu_notifier);
422 #endif
423         return 0;
424
425 exit_devices_unreg:
426         mutex_lock(&pdev_list_mutex);
427         list_for_each_entry_safe(p, n, &pdev_list, list) {
428                 platform_device_unregister(p->pdev);
429                 list_del(&p->list);
430                 kfree(p);
431         }
432         mutex_unlock(&pdev_list_mutex);
433 exit_driver_unreg:
434         platform_driver_unregister(&pkgtemp_driver);
435 exit:
436         return err;
437 }
438
439 static void __exit pkgtemp_exit(void)
440 {
441         struct pdev_entry *p, *n;
442 #ifdef CONFIG_HOTPLUG_CPU
443         unregister_hotcpu_notifier(&pkgtemp_cpu_notifier);
444 #endif
445         mutex_lock(&pdev_list_mutex);
446         list_for_each_entry_safe(p, n, &pdev_list, list) {
447                 platform_device_unregister(p->pdev);
448                 list_del(&p->list);
449                 kfree(p);
450         }
451         mutex_unlock(&pdev_list_mutex);
452         platform_driver_unregister(&pkgtemp_driver);
453 }
454
455 MODULE_AUTHOR("Fenghua Yu <fenghua.yu@intel.com>");
456 MODULE_DESCRIPTION("Intel processor package temperature monitor");
457 MODULE_LICENSE("GPL");
458
459 module_init(pkgtemp_init)
460 module_exit(pkgtemp_exit)