11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 28a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers * CPU subsystem support 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5024f78462c3da710642a54939888a92e28704653Ben Hutchings#include <linux/kernel.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> 135a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 14fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger#include <linux/slab.h> 159f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings#include <linux/percpu.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17a1bdc7aad8b557176ccecff1da137ebe3090871eBen Dooks#include "base.h" 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 198a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstruct bus_type cpu_subsys = { 20af5ca3f4ec5cc4432a42a73b050dd8898ce8fd00Kay Sievers .name = "cpu", 218a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers .dev_name = "cpu", 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 238a25a2fd126c621f44f3aeaef80d51f00fc11639Kay SieversEXPORT_SYMBOL_GPL(cpu_subsys); 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 258a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic DEFINE_PER_CPU(struct device *, cpu_sys_devices); 26ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_HOTPLUG_CPU 288a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic ssize_t show_online(struct device *dev, 298a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct device_attribute *attr, 304a0b2b4dbe1335b8b9886ba3dc85a145d5d938edAndi Kleen char *buf) 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 328a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct cpu *cpu = container_of(dev, struct cpu, dev); 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 348a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers return sprintf(buf, "%u\n", !!cpu_online(cpu->dev.id)); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 378a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic ssize_t __ref store_online(struct device *dev, 388a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct device_attribute *attr, 398a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers const char *buf, size_t count) 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 418a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct cpu *cpu = container_of(dev, struct cpu, dev); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ssize_t ret; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4451badebdcf394cc5fd574a524b55b3f6085e5e9cGautham R Shenoy cpu_hotplug_driver_lock(); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (buf[0]) { 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case '0': 478a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers ret = cpu_down(cpu->dev.id); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret) 49312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers kobject_uevent(&dev->kobj, KOBJ_OFFLINE); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case '1': 528a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers ret = cpu_up(cpu->dev.id); 53fb69c3907ead36b9e9f41ea6f0d0e0ae10a38a47Nathan Lynch if (!ret) 54312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers kobject_uevent(&dev->kobj, KOBJ_ONLINE); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5951badebdcf394cc5fd574a524b55b3f6085e5e9cGautham R Shenoy cpu_hotplug_driver_unlock(); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret >= 0) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = count; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 658a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic DEVICE_ATTR(online, 0644, show_online, store_online); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 676c847402e1c69c1cfe2bddeadc8391bacbb3d0a5Sam Ravnborgstatic void __cpuinit register_cpu_control(struct cpu *cpu) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 698a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers device_create_file(&cpu->dev, &dev_attr_online); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7176b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyukivoid unregister_cpu(struct cpu *cpu) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 738a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers int logical_cpu = cpu->dev.id; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7576b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); 7676b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki 778a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers device_remove_file(&cpu->dev, &dev_attr_online); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 798a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers device_unregister(&cpu->dev); 80e37d05dad7ff9744efd8ea95a70d389e9a65a6fcMike Travis per_cpu(cpu_sys_devices, logical_cpu) = NULL; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8312633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot 8412633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE 858a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic ssize_t cpu_probe_store(struct device *dev, 868a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct device_attribute *attr, 8767fc233f4fb67907861b4077cea5294035f80dc7Stephen Rothwell const char *buf, 8812633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot size_t count) 8912633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot{ 9012633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot return arch_cpu_probe(buf, count); 9112633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot} 9212633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot 938a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic ssize_t cpu_release_store(struct device *dev, 948a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct device_attribute *attr, 9567fc233f4fb67907861b4077cea5294035f80dc7Stephen Rothwell const char *buf, 9612633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot size_t count) 9712633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot{ 9812633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot return arch_cpu_release(buf, count); 9912633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot} 10012633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot 1018a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); 1028a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store); 10312633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ 10412633e803a2a556f6469e0933d08233d0844a2d9Nathan Fontenot 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* ... !CONFIG_HOTPLUG_CPU */ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void register_cpu_control(struct cpu *cpu) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_HOTPLUG_CPU */ 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#ifdef CONFIG_KEXEC 11251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#include <linux/kexec.h> 11351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 1148a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr, 1154a0b2b4dbe1335b8b9886ba3dc85a145d5d938edAndi Kleen char *buf) 11651be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal{ 1178a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct cpu *cpu = container_of(dev, struct cpu, dev); 11851be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal ssize_t rc; 11951be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal unsigned long long addr; 12051be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal int cpunum; 12151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 1228a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers cpunum = cpu->dev.id; 12351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 12451be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal /* 12551be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * Might be reading other cpu's data based on which cpu read thread 12651be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * has been scheduled. But cpu data (memory) is allocated once during 12751be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * boot up and this data does not change there after. Hence this 12851be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * operation should be safe. No locking required. 12951be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal */ 1303b034b0d084221596bf35c8d893e1d4d5477b9ccVivek Goyal addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum)); 13151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal rc = sprintf(buf, "%Lx\n", addr); 13251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal return rc; 13351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal} 1348a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL); 13551be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#endif 13651be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1389d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis * Print cpu online, possible, present, and system maps 1399d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis */ 140265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen 141265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleenstruct cpu_attr { 1428a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct device_attribute attr; 143265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen const struct cpumask *const * const map; 144265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen}; 145265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen 1468a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic ssize_t show_cpus_attr(struct device *dev, 1478a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct device_attribute *attr, 148265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen char *buf) 1499d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis{ 150265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr); 151265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *(ca->map)); 1529d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1539d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis buf[n++] = '\n'; 1549d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis buf[n] = '\0'; 1559d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis return n; 1569d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis} 1579d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1588a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers#define _CPU_ATTR(name, map) \ 1598a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers { __ATTR(name, 0444, show_cpus_attr, NULL), map } 1609d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1618a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers/* Keep in sync with cpu_subsys_attrs */ 162265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleenstatic struct cpu_attr cpu_attrs[] = { 163265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen _CPU_ATTR(online, &cpu_online_mask), 164265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen _CPU_ATTR(possible, &cpu_possible_mask), 165265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen _CPU_ATTR(present, &cpu_present_mask), 166265d2e2e31c5f6dc1b20ae1653a17fdba706f79eAndi Kleen}; 1679d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 168e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis/* 169e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis * Print values for NR_CPUS and offlined cpus 170e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis */ 1718a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic ssize_t print_cpus_kernel_max(struct device *dev, 1728a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct device_attribute *attr, char *buf) 173e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis{ 1748fd2d2d5aaf086cfa3b2e2e58cab96b7afdc9e51Mike Travis int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); 175e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis return n; 176e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis} 1778a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); 178e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis 179e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */ 180e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travisunsigned int total_cpus; 181e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis 1828a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic ssize_t print_cpus_offline(struct device *dev, 1838a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct device_attribute *attr, char *buf) 184e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis{ 185e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis int n = 0, len = PAGE_SIZE-2; 186e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis cpumask_var_t offline; 187e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis 188e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis /* display offline cpus < nr_cpu_ids */ 189e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis if (!alloc_cpumask_var(&offline, GFP_KERNEL)) 190e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis return -ENOMEM; 191cdc6e3d3968052cebb2f2ddcd742bff29fbd1a90Jan Beulich cpumask_andnot(offline, cpu_possible_mask, cpu_online_mask); 192e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis n = cpulist_scnprintf(buf, len, offline); 193e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis free_cpumask_var(offline); 194e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis 195e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis /* display offline cpus >= nr_cpu_ids */ 196e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis if (total_cpus && nr_cpu_ids < total_cpus) { 197e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis if (n && n < len) 198e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis buf[n++] = ','; 199e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis 200e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis if (nr_cpu_ids == total_cpus-1) 201e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis n += snprintf(&buf[n], len - n, "%d", nr_cpu_ids); 202e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis else 203e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis n += snprintf(&buf[n], len - n, "%d-%d", 204e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis nr_cpu_ids, total_cpus-1); 205e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis } 206e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis 207e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis n += snprintf(&buf[n], len - n, "\n"); 208e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis return n; 209e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis} 2108a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); 211e057d7aea9d8f2a46cd440d8bfb72245d4e72d79Mike Travis 2122885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartmanstatic void cpu_device_release(struct device *dev) 2132885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman{ 2142885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman /* 2152885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * This is an empty function to prevent the driver core from spitting a 2162885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * warning at us. Yes, I know this is directly opposite of what the 2172885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * documentation for the driver core and kobjects say, and the author 2182885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * of this code has already been publically ridiculed for doing 2192885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * something as foolish as this. However, at this point in time, it is 2202885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * the only way to handle the issue of statically allocated cpu 2212885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * devices. The different architectures will have their cpu device 2222885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * code reworked to properly handle this in the near future, so this 2232885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * function will then be changed to correctly free up the memory held 2242885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * by the cpu device. 2252885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * 2262885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * Never copy this way of doing things, or you too will be made fun of 2272885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman * on the linux-kerenl list, you have been warned. 2282885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman */ 2292885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman} 2302885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman 2319d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis/* 232405ae7d381302468ecc803f2148a2ae40a04c999Robert P. J. Day * register_cpu - Setup a sysfs device for a CPU. 23372486f1f8f0a2bc828b9d30cf4690cf2dd6807fcSiddha, Suresh B * @cpu - cpu->hotpluggable field set to 1 will generate a control file in 23472486f1f8f0a2bc828b9d30cf4690cf2dd6807fcSiddha, Suresh B * sysfs for this CPU. 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @num - CPU number to use when creating the device. 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize and register the CPU device. 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23933b5f31bbc4d047d048d8635fccdab38ffe6c287Randy Dunlapint __cpuinit register_cpu(struct cpu *cpu, int num) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 24276b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki 2438a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers cpu->node_id = cpu_to_node(num); 24429bb5d4fd3140a7d5d02d858118c74a45f15c296Greg Kroah-Hartman memset(&cpu->dev, 0x00, sizeof(struct device)); 2458a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers cpu->dev.id = num; 2468a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers cpu->dev.bus = &cpu_subsys; 2472885e25c422fb68208f677f944a45fce8eda2a3cGreg Kroah-Hartman cpu->dev.release = cpu_device_release; 248fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE 249fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger cpu->dev.bus->uevent = arch_cpu_uevent; 250fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger#endif 2518a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers error = device_register(&cpu->dev); 25272486f1f8f0a2bc828b9d30cf4690cf2dd6807fcSiddha, Suresh B if (!error && cpu->hotpluggable) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_cpu_control(cpu); 254ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj if (!error) 2558a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers per_cpu(cpu_sys_devices, num) = &cpu->dev; 25676b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki if (!error) 25776b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki register_cpu_under_node(num, cpu_to_node(num)); 25851be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 25951be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#ifdef CONFIG_KEXEC 26051be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal if (!error) 2618a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers error = device_create_file(&cpu->dev, &dev_attr_crash_notes); 26251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#endif 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2668a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstruct device *get_cpu_device(unsigned cpu) 267ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj{ 268e37d05dad7ff9744efd8ea95a70d389e9a65a6fcMike Travis if (cpu < nr_cpu_ids && cpu_possible(cpu)) 269e37d05dad7ff9744efd8ea95a70d389e9a65a6fcMike Travis return per_cpu(cpu_sys_devices, cpu); 270ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj else 271ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj return NULL; 272ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj} 2738a25a2fd126c621f44f3aeaef80d51f00fc11639Kay SieversEXPORT_SYMBOL_GPL(get_cpu_device); 2748a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers 275fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE 276fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renningerstatic DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); 277fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger#endif 278fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger 2798a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic struct attribute *cpu_root_attrs[] = { 2808a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE 2818a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers &dev_attr_probe.attr, 2828a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers &dev_attr_release.attr, 2838a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers#endif 2848a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers &cpu_attrs[0].attr.attr, 2858a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers &cpu_attrs[1].attr.attr, 2868a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers &cpu_attrs[2].attr.attr, 2878a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers &dev_attr_kernel_max.attr, 2888a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers &dev_attr_offline.attr, 289fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE 290fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger &dev_attr_modalias.attr, 291fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafaThomas Renninger#endif 2928a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers NULL 2938a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers}; 2948a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers 2958a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic struct attribute_group cpu_root_attr_group = { 2968a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers .attrs = cpu_root_attrs, 2978a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers}; 2988a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers 2998a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sieversstatic const struct attribute_group *cpu_root_attr_groups[] = { 3008a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers &cpu_root_attr_group, 3018a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers NULL, 3028a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers}; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3042987557f52b97f679f0c324d8f51b8d66e1f2084Josh Triplettbool cpu_is_hotpluggable(unsigned cpu) 3052987557f52b97f679f0c324d8f51b8d66e1f2084Josh Triplett{ 3067affca3537d74365128e477b40c529d6f2fe86c8Linus Torvalds struct device *dev = get_cpu_device(cpu); 3077affca3537d74365128e477b40c529d6f2fe86c8Linus Torvalds return dev && container_of(dev, struct cpu, dev)->hotpluggable; 3082987557f52b97f679f0c324d8f51b8d66e1f2084Josh Triplett} 3092987557f52b97f679f0c324d8f51b8d66e1f2084Josh TriplettEXPORT_SYMBOL_GPL(cpu_is_hotpluggable); 3102987557f52b97f679f0c324d8f51b8d66e1f2084Josh Triplett 3119f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings#ifdef CONFIG_GENERIC_CPU_DEVICES 3129f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchingsstatic DEFINE_PER_CPU(struct cpu, cpu_devices); 3139f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings#endif 3149f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings 3159f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchingsstatic void __init cpu_dev_register_generic(void) 3169f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings{ 3179f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings#ifdef CONFIG_GENERIC_CPU_DEVICES 3189f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings int i; 3199f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings 3209f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings for_each_possible_cpu(i) { 3219f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings if (register_cpu(&per_cpu(cpu_devices, i), i)) 3229f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings panic("Failed to register CPU device"); 3239f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings } 3249f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings#endif 3259f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings} 3269f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings 327024f78462c3da710642a54939888a92e28704653Ben Hutchingsvoid __init cpu_dev_init(void) 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 329024f78462c3da710642a54939888a92e28704653Ben Hutchings if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups)) 330024f78462c3da710642a54939888a92e28704653Ben Hutchings panic("Failed to register CPU subsystem"); 3318a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers 3329f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings cpu_dev_register_generic(); 3339f13a1fd452f11c18004ba2422a6384b424ec8a9Ben Hutchings 3345c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) 335024f78462c3da710642a54939888a92e28704653Ben Hutchings sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root); 3365c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B#endif 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 338