]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/hwmon/pkgtemp.c
x86/hwmon: fix initialization of pkgtemp
[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         struct cpuinfo_x86 *c = &cpu_data(cpu);
288
289         if (!cpu_has(c, X86_FEATURE_PTS))
290                 return 0;
291
292         mutex_lock(&pdev_list_mutex);
293
294 #ifdef CONFIG_SMP
295         /* Only keep the first entry in each package */
296         list_for_each_entry(pdev_entry, &pdev_list, list) {
297                 if (c->phys_proc_id == pdev_entry->phys_proc_id) {
298                         err = 0;        /* Not an error */
299                         goto exit;
300                 }
301         }
302 #endif
303
304         pdev = platform_device_alloc(DRVNAME, cpu);
305         if (!pdev) {
306                 err = -ENOMEM;
307                 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
308                 goto exit;
309         }
310
311         pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
312         if (!pdev_entry) {
313                 err = -ENOMEM;
314                 goto exit_device_put;
315         }
316
317         err = platform_device_add(pdev);
318         if (err) {
319                 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
320                        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
334 exit_device_free:
335         kfree(pdev_entry);
336 exit_device_put:
337         platform_device_put(pdev);
338 exit:
339         mutex_unlock(&pdev_list_mutex);
340         return err;
341 }
342
343 #ifdef CONFIG_HOTPLUG_CPU
344 static void pkgtemp_device_remove(unsigned int cpu)
345 {
346         struct pdev_entry *p;
347         unsigned int i;
348         int err;
349
350         mutex_lock(&pdev_list_mutex);
351         list_for_each_entry(p, &pdev_list, list) {
352                 if (p->cpu != cpu)
353                         continue;
354
355                 platform_device_unregister(p->pdev);
356                 list_del(&p->list);
357                 mutex_unlock(&pdev_list_mutex);
358                 kfree(p);
359                 for_each_cpu(i, cpu_core_mask(cpu)) {
360                         if (i != cpu) {
361                                 err = pkgtemp_device_add(i);
362                                 if (!err)
363                                         break;
364                         }
365                 }
366                 return;
367         }
368         mutex_unlock(&pdev_list_mutex);
369 }
370
371 static int __cpuinit pkgtemp_cpu_callback(struct notifier_block *nfb,
372                                  unsigned long action, void *hcpu)
373 {
374         unsigned int cpu = (unsigned long) hcpu;
375
376         switch (action) {
377         case CPU_ONLINE:
378         case CPU_DOWN_FAILED:
379                 pkgtemp_device_add(cpu);
380                 break;
381         case CPU_DOWN_PREPARE:
382                 pkgtemp_device_remove(cpu);
383                 break;
384         }
385         return NOTIFY_OK;
386 }
387
388 static struct notifier_block pkgtemp_cpu_notifier __refdata = {
389         .notifier_call = pkgtemp_cpu_callback,
390 };
391 #endif                          /* !CONFIG_HOTPLUG_CPU */
392
393 static int __init pkgtemp_init(void)
394 {
395         int i, err = -ENODEV;
396         struct pdev_entry *p, *n;
397
398         /* quick check if we run Intel */
399         if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
400                 goto exit;
401
402         err = platform_driver_register(&pkgtemp_driver);
403         if (err)
404                 goto exit;
405
406         for_each_online_cpu(i) {
407                 err = pkgtemp_device_add(i);
408                 if (err)
409                         goto exit_devices_unreg;
410         }
411         if (list_empty(&pdev_list)) {
412                 err = -ENODEV;
413                 goto exit_driver_unreg;
414         }
415
416 #ifdef CONFIG_HOTPLUG_CPU
417         register_hotcpu_notifier(&pkgtemp_cpu_notifier);
418 #endif
419         return 0;
420
421 exit_devices_unreg:
422         mutex_lock(&pdev_list_mutex);
423         list_for_each_entry_safe(p, n, &pdev_list, list) {
424                 platform_device_unregister(p->pdev);
425                 list_del(&p->list);
426                 kfree(p);
427         }
428         mutex_unlock(&pdev_list_mutex);
429 exit_driver_unreg:
430         platform_driver_unregister(&pkgtemp_driver);
431 exit:
432         return err;
433 }
434
435 static void __exit pkgtemp_exit(void)
436 {
437         struct pdev_entry *p, *n;
438 #ifdef CONFIG_HOTPLUG_CPU
439         unregister_hotcpu_notifier(&pkgtemp_cpu_notifier);
440 #endif
441         mutex_lock(&pdev_list_mutex);
442         list_for_each_entry_safe(p, n, &pdev_list, list) {
443                 platform_device_unregister(p->pdev);
444                 list_del(&p->list);
445                 kfree(p);
446         }
447         mutex_unlock(&pdev_list_mutex);
448         platform_driver_unregister(&pkgtemp_driver);
449 }
450
451 MODULE_AUTHOR("Fenghua Yu <fenghua.yu@intel.com>");
452 MODULE_DESCRIPTION("Intel processor package temperature monitor");
453 MODULE_LICENSE("GPL");
454
455 module_init(pkgtemp_init)
456 module_exit(pkgtemp_exit)