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