11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * drivers/base/cpu.c - basic CPU class support 31da177e4SLinus Torvalds */ 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds #include <linux/sysdev.h> 61da177e4SLinus Torvalds #include <linux/module.h> 71da177e4SLinus Torvalds #include <linux/init.h> 81da177e4SLinus Torvalds #include <linux/cpu.h> 91da177e4SLinus Torvalds #include <linux/topology.h> 101da177e4SLinus Torvalds #include <linux/device.h> 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds struct sysdev_class cpu_sysdev_class = { 141da177e4SLinus Torvalds set_kset_name("cpu"), 151da177e4SLinus Torvalds }; 161da177e4SLinus Torvalds EXPORT_SYMBOL(cpu_sysdev_class); 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds #ifdef CONFIG_HOTPLUG_CPU 1952a119feSAshok Raj int __attribute__((weak)) smp_prepare_cpu (int cpu) 2052a119feSAshok Raj { 2152a119feSAshok Raj return 0; 2252a119feSAshok Raj } 23e1367dafSLi Shaohua 241da177e4SLinus Torvalds static ssize_t show_online(struct sys_device *dev, char *buf) 251da177e4SLinus Torvalds { 261da177e4SLinus Torvalds struct cpu *cpu = container_of(dev, struct cpu, sysdev); 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); 291da177e4SLinus Torvalds } 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds static ssize_t store_online(struct sys_device *dev, const char *buf, 321da177e4SLinus Torvalds size_t count) 331da177e4SLinus Torvalds { 341da177e4SLinus Torvalds struct cpu *cpu = container_of(dev, struct cpu, sysdev); 351da177e4SLinus Torvalds ssize_t ret; 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds switch (buf[0]) { 381da177e4SLinus Torvalds case '0': 391da177e4SLinus Torvalds ret = cpu_down(cpu->sysdev.id); 401da177e4SLinus Torvalds if (!ret) 411da177e4SLinus Torvalds kobject_hotplug(&dev->kobj, KOBJ_OFFLINE); 421da177e4SLinus Torvalds break; 431da177e4SLinus Torvalds case '1': 44e1367dafSLi Shaohua ret = smp_prepare_cpu(cpu->sysdev.id); 4552a119feSAshok Raj if (!ret) 461da177e4SLinus Torvalds ret = cpu_up(cpu->sysdev.id); 471da177e4SLinus Torvalds break; 481da177e4SLinus Torvalds default: 491da177e4SLinus Torvalds ret = -EINVAL; 501da177e4SLinus Torvalds } 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds if (ret >= 0) 531da177e4SLinus Torvalds ret = count; 541da177e4SLinus Torvalds return ret; 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds static SYSDEV_ATTR(online, 0600, show_online, store_online); 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds static void __devinit register_cpu_control(struct cpu *cpu) 591da177e4SLinus Torvalds { 601da177e4SLinus Torvalds sysdev_create_file(&cpu->sysdev, &attr_online); 611da177e4SLinus Torvalds } 621da177e4SLinus Torvalds void unregister_cpu(struct cpu *cpu, struct node *root) 631da177e4SLinus Torvalds { 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds if (root) 661da177e4SLinus Torvalds sysfs_remove_link(&root->sysdev.kobj, 671da177e4SLinus Torvalds kobject_name(&cpu->sysdev.kobj)); 681da177e4SLinus Torvalds sysdev_remove_file(&cpu->sysdev, &attr_online); 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds sysdev_unregister(&cpu->sysdev); 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds return; 731da177e4SLinus Torvalds } 741da177e4SLinus Torvalds #else /* ... !CONFIG_HOTPLUG_CPU */ 751da177e4SLinus Torvalds static inline void register_cpu_control(struct cpu *cpu) 761da177e4SLinus Torvalds { 771da177e4SLinus Torvalds } 781da177e4SLinus Torvalds #endif /* CONFIG_HOTPLUG_CPU */ 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds /* 811da177e4SLinus Torvalds * register_cpu - Setup a driverfs device for a CPU. 821da177e4SLinus Torvalds * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to 831da177e4SLinus Torvalds * generate a control file in sysfs for this CPU. 841da177e4SLinus Torvalds * @num - CPU number to use when creating the device. 851da177e4SLinus Torvalds * 861da177e4SLinus Torvalds * Initialize and register the CPU device. 871da177e4SLinus Torvalds */ 881da177e4SLinus Torvalds int __devinit register_cpu(struct cpu *cpu, int num, struct node *root) 891da177e4SLinus Torvalds { 901da177e4SLinus Torvalds int error; 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds cpu->node_id = cpu_to_node(num); 931da177e4SLinus Torvalds cpu->sysdev.id = num; 941da177e4SLinus Torvalds cpu->sysdev.cls = &cpu_sysdev_class; 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds error = sysdev_register(&cpu->sysdev); 971da177e4SLinus Torvalds if (!error && root) 981da177e4SLinus Torvalds error = sysfs_create_link(&root->sysdev.kobj, 991da177e4SLinus Torvalds &cpu->sysdev.kobj, 1001da177e4SLinus Torvalds kobject_name(&cpu->sysdev.kobj)); 1011da177e4SLinus Torvalds if (!error && !cpu->no_control) 1021da177e4SLinus Torvalds register_cpu_control(cpu); 1031da177e4SLinus Torvalds return error; 1041da177e4SLinus Torvalds } 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds int __init cpu_dev_init(void) 1091da177e4SLinus Torvalds { 1101da177e4SLinus Torvalds return sysdev_class_register(&cpu_sysdev_class); 1111da177e4SLinus Torvalds } 112