xref: /openbmc/linux/drivers/base/cpu.c (revision e1367daf)
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
19e1367dafSLi Shaohua #ifndef __HAVE_ARCH_SMP_PREPARE_CPU
20e1367dafSLi Shaohua #define smp_prepare_cpu(cpu) (0)
21e1367dafSLi Shaohua #endif
22e1367dafSLi Shaohua 
231da177e4SLinus Torvalds static ssize_t show_online(struct sys_device *dev, char *buf)
241da177e4SLinus Torvalds {
251da177e4SLinus Torvalds 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds 	return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
281da177e4SLinus Torvalds }
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds static ssize_t store_online(struct sys_device *dev, const char *buf,
311da177e4SLinus Torvalds 			    size_t count)
321da177e4SLinus Torvalds {
331da177e4SLinus Torvalds 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
341da177e4SLinus Torvalds 	ssize_t ret;
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds 	switch (buf[0]) {
371da177e4SLinus Torvalds 	case '0':
381da177e4SLinus Torvalds 		ret = cpu_down(cpu->sysdev.id);
391da177e4SLinus Torvalds 		if (!ret)
401da177e4SLinus Torvalds 			kobject_hotplug(&dev->kobj, KOBJ_OFFLINE);
411da177e4SLinus Torvalds 		break;
421da177e4SLinus Torvalds 	case '1':
43e1367dafSLi Shaohua 		ret = smp_prepare_cpu(cpu->sysdev.id);
44e1367dafSLi Shaohua 		if (ret == 0)
451da177e4SLinus Torvalds 			ret = cpu_up(cpu->sysdev.id);
461da177e4SLinus Torvalds 		break;
471da177e4SLinus Torvalds 	default:
481da177e4SLinus Torvalds 		ret = -EINVAL;
491da177e4SLinus Torvalds 	}
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds 	if (ret >= 0)
521da177e4SLinus Torvalds 		ret = count;
531da177e4SLinus Torvalds 	return ret;
541da177e4SLinus Torvalds }
551da177e4SLinus Torvalds static SYSDEV_ATTR(online, 0600, show_online, store_online);
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds static void __devinit register_cpu_control(struct cpu *cpu)
581da177e4SLinus Torvalds {
591da177e4SLinus Torvalds 	sysdev_create_file(&cpu->sysdev, &attr_online);
601da177e4SLinus Torvalds }
611da177e4SLinus Torvalds void unregister_cpu(struct cpu *cpu, struct node *root)
621da177e4SLinus Torvalds {
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds 	if (root)
651da177e4SLinus Torvalds 		sysfs_remove_link(&root->sysdev.kobj,
661da177e4SLinus Torvalds 				  kobject_name(&cpu->sysdev.kobj));
671da177e4SLinus Torvalds 	sysdev_remove_file(&cpu->sysdev, &attr_online);
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds 	sysdev_unregister(&cpu->sysdev);
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds 	return;
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds #else /* ... !CONFIG_HOTPLUG_CPU */
741da177e4SLinus Torvalds static inline void register_cpu_control(struct cpu *cpu)
751da177e4SLinus Torvalds {
761da177e4SLinus Torvalds }
771da177e4SLinus Torvalds #endif /* CONFIG_HOTPLUG_CPU */
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds /*
801da177e4SLinus Torvalds  * register_cpu - Setup a driverfs device for a CPU.
811da177e4SLinus Torvalds  * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to
821da177e4SLinus Torvalds  *		  generate a control file in sysfs for this CPU.
831da177e4SLinus Torvalds  * @num - CPU number to use when creating the device.
841da177e4SLinus Torvalds  *
851da177e4SLinus Torvalds  * Initialize and register the CPU device.
861da177e4SLinus Torvalds  */
871da177e4SLinus Torvalds int __devinit register_cpu(struct cpu *cpu, int num, struct node *root)
881da177e4SLinus Torvalds {
891da177e4SLinus Torvalds 	int error;
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds 	cpu->node_id = cpu_to_node(num);
921da177e4SLinus Torvalds 	cpu->sysdev.id = num;
931da177e4SLinus Torvalds 	cpu->sysdev.cls = &cpu_sysdev_class;
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds 	error = sysdev_register(&cpu->sysdev);
961da177e4SLinus Torvalds 	if (!error && root)
971da177e4SLinus Torvalds 		error = sysfs_create_link(&root->sysdev.kobj,
981da177e4SLinus Torvalds 					  &cpu->sysdev.kobj,
991da177e4SLinus Torvalds 					  kobject_name(&cpu->sysdev.kobj));
1001da177e4SLinus Torvalds 	if (!error && !cpu->no_control)
1011da177e4SLinus Torvalds 		register_cpu_control(cpu);
1021da177e4SLinus Torvalds 	return error;
1031da177e4SLinus Torvalds }
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds int __init cpu_dev_init(void)
1081da177e4SLinus Torvalds {
1091da177e4SLinus Torvalds 	return sysdev_class_register(&cpu_sysdev_class);
1101da177e4SLinus Torvalds }
111