cpu.c revision 6c847402e1c69c1cfe2bddeadc8391bacbb3d0a5
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * drivers/base/cpu.c - basic CPU class support 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sysdev.h> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 8f6a570333e554b48ad589e7137c77c57809eee81Al Viro#include <linux/sched.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cpu.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/topology.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h> 1276b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki#include <linux/node.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14a1bdc7aad8b557176ccecff1da137ebe3090871eBen Dooks#include "base.h" 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sysdev_class cpu_sysdev_class = { 17af5ca3f4ec5cc4432a42a73b050dd8898ce8fd00Kay Sievers .name = "cpu", 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(cpu_sysdev_class); 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Rajstatic struct sys_device *cpu_sys_devices[NR_CPUS]; 22ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_HOTPLUG_CPU 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_online(struct sys_device *dev, char *buf) 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cpu *cpu = container_of(dev, struct cpu, sysdev); 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 316c847402e1c69c1cfe2bddeadc8391bacbb3d0a5Sam Ravnborgstatic ssize_t __ref store_online(struct sys_device *dev, const char *buf, 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cpu *cpu = container_of(dev, struct cpu, sysdev); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ssize_t ret; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (buf[0]) { 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case '0': 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = cpu_down(cpu->sysdev.id); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret) 41312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers kobject_uevent(&dev->kobj, KOBJ_OFFLINE); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case '1': 4434f361ade2fb4a869f6a7714d01c04ce4cfa75d9Ashok Raj ret = cpu_up(cpu->sysdev.id); 45fb69c3907ead36b9e9f41ea6f0d0e0ae10a38a47Nathan Lynch if (!ret) 46312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers kobject_uevent(&dev->kobj, KOBJ_ONLINE); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret >= 0) 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = count; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 569eb3ff40376e505eafb927b4a4cbccc928df68ecUlrich Drepperstatic SYSDEV_ATTR(online, 0644, show_online, store_online); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 586c847402e1c69c1cfe2bddeadc8391bacbb3d0a5Sam Ravnborgstatic void __cpuinit register_cpu_control(struct cpu *cpu) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysdev_create_file(&cpu->sysdev, &attr_online); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6276b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyukivoid unregister_cpu(struct cpu *cpu) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 64ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj int logical_cpu = cpu->sysdev.id; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6676b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); 6776b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysdev_remove_file(&cpu->sysdev, &attr_online); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysdev_unregister(&cpu->sysdev); 71ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj cpu_sys_devices[logical_cpu] = NULL; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* ... !CONFIG_HOTPLUG_CPU */ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void register_cpu_control(struct cpu *cpu) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_HOTPLUG_CPU */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8051be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#ifdef CONFIG_KEXEC 8151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#include <linux/kexec.h> 8251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 8351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyalstatic ssize_t show_crash_notes(struct sys_device *dev, char *buf) 8451be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal{ 8551be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal struct cpu *cpu = container_of(dev, struct cpu, sysdev); 8651be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal ssize_t rc; 8751be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal unsigned long long addr; 8851be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal int cpunum; 8951be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 9051be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal cpunum = cpu->sysdev.id; 9151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 9251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal /* 9351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * Might be reading other cpu's data based on which cpu read thread 9451be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * has been scheduled. But cpu data (memory) is allocated once during 9551be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * boot up and this data does not change there after. Hence this 9651be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * operation should be safe. No locking required. 9751be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal */ 9851be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal addr = __pa(per_cpu_ptr(crash_notes, cpunum)); 9951be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal rc = sprintf(buf, "%Lx\n", addr); 10051be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal return rc; 10151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal} 10251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyalstatic SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); 10351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#endif 10451be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 106405ae7d381302468ecc803f2148a2ae40a04c999Robert P. J. Day * register_cpu - Setup a sysfs device for a CPU. 10772486f1f8f0a2bc828b9d30cf4690cf2dd6807fcSiddha, Suresh B * @cpu - cpu->hotpluggable field set to 1 will generate a control file in 10872486f1f8f0a2bc828b9d30cf4690cf2dd6807fcSiddha, Suresh B * sysfs for this CPU. 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @num - CPU number to use when creating the device. 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize and register the CPU device. 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11333b5f31bbc4d047d048d8635fccdab38ffe6c287Randy Dunlapint __cpuinit register_cpu(struct cpu *cpu, int num) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu->node_id = cpu_to_node(num); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu->sysdev.id = num; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu->sysdev.cls = &cpu_sysdev_class; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = sysdev_register(&cpu->sysdev); 12176b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki 12272486f1f8f0a2bc828b9d30cf4690cf2dd6807fcSiddha, Suresh B if (!error && cpu->hotpluggable) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_cpu_control(cpu); 124ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj if (!error) 125ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj cpu_sys_devices[num] = &cpu->sysdev; 12676b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki if (!error) 12776b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki register_cpu_under_node(num, cpu_to_node(num)); 12851be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 12951be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#ifdef CONFIG_KEXEC 13051be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal if (!error) 13151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes); 13251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#endif 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 136a29d642a4aa99c5234314ab2523281139226c231Andrew Mortonstruct sys_device *get_cpu_sysdev(unsigned cpu) 137ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj{ 138ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj if (cpu < NR_CPUS) 139ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj return cpu_sys_devices[cpu]; 140ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj else 141ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj return NULL; 142ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj} 143ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok RajEXPORT_SYMBOL_GPL(get_cpu_sysdev); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init cpu_dev_init(void) 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1475c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B int err; 1485c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B 1495c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B err = sysdev_class_register(&cpu_sysdev_class); 1505c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) 1515c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B if (!err) 1525c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class); 1535c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B#endif 1545c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B 1555c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B return err; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 157