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