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