at v2.6.39 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#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)