2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* drivers/base/cpu.c - basic CPU class support
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/sysdev.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/init.h>
|
2006-10-18 13:47:25 +08:00
|
|
|
#include <linux/sched.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/cpu.h>
|
|
|
|
#include <linux/topology.h>
|
|
|
|
#include <linux/device.h>
|
[PATCH] node hotplug: register cpu: remove node struct
With Goto-san's patch, we can add new pgdat/node at runtime. I'm now
considering node-hot-add with cpu + memory on ACPI.
I found acpi container, which describes node, could evaluate cpu before
memory. This means cpu-hot-add occurs before memory hot add.
In most part, cpu-hot-add doesn't depend on node hot add. But register_cpu(),
which creates symbolic link from node to cpu, requires that node should be
onlined before register_cpu(). When a node is onlined, its pgdat should be
there.
This patch-set holds off creating symbolic link from node to cpu
until node is onlined.
This removes node arguments from register_cpu().
Now, register_cpu() requires 'struct node' as its argument. But the array of
struct node is now unified in driver/base/node.c now (By Goto's node hotplug
patch). We can get struct node in generic way. So, this argument is not
necessary now.
This patch also guarantees add cpu under node only when node is onlined. It
is necessary for node-hot-add vs. cpu-hot-add patch following this.
Moreover, register_cpu calculates cpu->node_id by cpu_to_node() without regard
to its 'struct node *root' argument. This patch removes it.
Also modify callers of register_cpu()/unregister_cpu, whose args are changed
by register-cpu-remove-node-struct patch.
[Brice.Goglin@ens-lyon.org: fix it]
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Yasunori Goto <y-goto@jp.fujitsu.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Brice Goglin <Brice.Goglin@ens-lyon.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27 17:53:41 +08:00
|
|
|
#include <linux/node.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-10-14 00:54:41 +08:00
|
|
|
#include "base.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
struct sysdev_class cpu_sysdev_class = {
|
2007-12-20 09:09:39 +08:00
|
|
|
.name = "cpu",
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
EXPORT_SYMBOL(cpu_sysdev_class);
|
|
|
|
|
2008-05-01 19:35:16 +08:00
|
|
|
static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices);
|
2005-10-31 06:59:49 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
2008-07-02 00:48:41 +08:00
|
|
|
static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr,
|
|
|
|
char *buf)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
|
|
|
|
|
|
|
|
return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
|
|
|
|
}
|
|
|
|
|
2008-07-02 00:48:41 +08:00
|
|
|
static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
|
|
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
switch (buf[0]) {
|
|
|
|
case '0':
|
|
|
|
ret = cpu_down(cpu->sysdev.id);
|
|
|
|
if (!ret)
|
2005-11-16 16:00:00 +08:00
|
|
|
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
case '1':
|
2006-03-25 19:08:18 +08:00
|
|
|
ret = cpu_up(cpu->sysdev.id);
|
2005-06-26 05:55:05 +08:00
|
|
|
if (!ret)
|
2005-11-16 16:00:00 +08:00
|
|
|
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret >= 0)
|
|
|
|
ret = count;
|
|
|
|
return ret;
|
|
|
|
}
|
2007-07-31 15:38:16 +08:00
|
|
|
static SYSDEV_ATTR(online, 0644, show_online, store_online);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-03-05 07:09:05 +08:00
|
|
|
static void __cpuinit register_cpu_control(struct cpu *cpu)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
sysdev_create_file(&cpu->sysdev, &attr_online);
|
|
|
|
}
|
[PATCH] node hotplug: register cpu: remove node struct
With Goto-san's patch, we can add new pgdat/node at runtime. I'm now
considering node-hot-add with cpu + memory on ACPI.
I found acpi container, which describes node, could evaluate cpu before
memory. This means cpu-hot-add occurs before memory hot add.
In most part, cpu-hot-add doesn't depend on node hot add. But register_cpu(),
which creates symbolic link from node to cpu, requires that node should be
onlined before register_cpu(). When a node is onlined, its pgdat should be
there.
This patch-set holds off creating symbolic link from node to cpu
until node is onlined.
This removes node arguments from register_cpu().
Now, register_cpu() requires 'struct node' as its argument. But the array of
struct node is now unified in driver/base/node.c now (By Goto's node hotplug
patch). We can get struct node in generic way. So, this argument is not
necessary now.
This patch also guarantees add cpu under node only when node is onlined. It
is necessary for node-hot-add vs. cpu-hot-add patch following this.
Moreover, register_cpu calculates cpu->node_id by cpu_to_node() without regard
to its 'struct node *root' argument. This patch removes it.
Also modify callers of register_cpu()/unregister_cpu, whose args are changed
by register-cpu-remove-node-struct patch.
[Brice.Goglin@ens-lyon.org: fix it]
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Yasunori Goto <y-goto@jp.fujitsu.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Brice Goglin <Brice.Goglin@ens-lyon.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27 17:53:41 +08:00
|
|
|
void unregister_cpu(struct cpu *cpu)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-10-31 06:59:49 +08:00
|
|
|
int logical_cpu = cpu->sysdev.id;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[PATCH] node hotplug: register cpu: remove node struct
With Goto-san's patch, we can add new pgdat/node at runtime. I'm now
considering node-hot-add with cpu + memory on ACPI.
I found acpi container, which describes node, could evaluate cpu before
memory. This means cpu-hot-add occurs before memory hot add.
In most part, cpu-hot-add doesn't depend on node hot add. But register_cpu(),
which creates symbolic link from node to cpu, requires that node should be
onlined before register_cpu(). When a node is onlined, its pgdat should be
there.
This patch-set holds off creating symbolic link from node to cpu
until node is onlined.
This removes node arguments from register_cpu().
Now, register_cpu() requires 'struct node' as its argument. But the array of
struct node is now unified in driver/base/node.c now (By Goto's node hotplug
patch). We can get struct node in generic way. So, this argument is not
necessary now.
This patch also guarantees add cpu under node only when node is onlined. It
is necessary for node-hot-add vs. cpu-hot-add patch following this.
Moreover, register_cpu calculates cpu->node_id by cpu_to_node() without regard
to its 'struct node *root' argument. This patch removes it.
Also modify callers of register_cpu()/unregister_cpu, whose args are changed
by register-cpu-remove-node-struct patch.
[Brice.Goglin@ens-lyon.org: fix it]
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Yasunori Goto <y-goto@jp.fujitsu.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Brice Goglin <Brice.Goglin@ens-lyon.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27 17:53:41 +08:00
|
|
|
unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
sysdev_remove_file(&cpu->sysdev, &attr_online);
|
|
|
|
|
|
|
|
sysdev_unregister(&cpu->sysdev);
|
2008-05-01 19:35:16 +08:00
|
|
|
per_cpu(cpu_sys_devices, logical_cpu) = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else /* ... !CONFIG_HOTPLUG_CPU */
|
|
|
|
static inline void register_cpu_control(struct cpu *cpu)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_HOTPLUG_CPU */
|
|
|
|
|
2006-01-10 12:51:42 +08:00
|
|
|
#ifdef CONFIG_KEXEC
|
|
|
|
#include <linux/kexec.h>
|
|
|
|
|
2008-07-02 00:48:41 +08:00
|
|
|
static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr,
|
|
|
|
char *buf)
|
2006-01-10 12:51:42 +08:00
|
|
|
{
|
|
|
|
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
|
|
|
|
ssize_t rc;
|
|
|
|
unsigned long long addr;
|
|
|
|
int cpunum;
|
|
|
|
|
|
|
|
cpunum = cpu->sysdev.id;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Might be reading other cpu's data based on which cpu read thread
|
|
|
|
* has been scheduled. But cpu data (memory) is allocated once during
|
|
|
|
* boot up and this data does not change there after. Hence this
|
|
|
|
* operation should be safe. No locking required.
|
|
|
|
*/
|
|
|
|
addr = __pa(per_cpu_ptr(crash_notes, cpunum));
|
|
|
|
rc = sprintf(buf, "%Lx\n", addr);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
|
|
|
|
#endif
|
|
|
|
|
2008-04-09 02:43:04 +08:00
|
|
|
/*
|
|
|
|
* Print cpu online, possible, present, and system maps
|
|
|
|
*/
|
|
|
|
static ssize_t print_cpus_map(char *buf, cpumask_t *map)
|
|
|
|
{
|
2008-12-13 18:50:25 +08:00
|
|
|
int n = cpulist_scnprintf(buf, PAGE_SIZE-2, map);
|
2008-04-09 02:43:04 +08:00
|
|
|
|
|
|
|
buf[n++] = '\n';
|
|
|
|
buf[n] = '\0';
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define print_cpus_func(type) \
|
|
|
|
static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \
|
|
|
|
{ \
|
|
|
|
return print_cpus_map(buf, &cpu_##type##_map); \
|
|
|
|
} \
|
2008-05-13 03:21:13 +08:00
|
|
|
static struct sysdev_class_attribute attr_##type##_map = \
|
2008-04-09 02:43:04 +08:00
|
|
|
_SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
|
|
|
|
|
|
|
|
print_cpus_func(online);
|
|
|
|
print_cpus_func(possible);
|
|
|
|
print_cpus_func(present);
|
|
|
|
|
2008-12-16 12:26:48 +08:00
|
|
|
/*
|
|
|
|
* Print values for NR_CPUS and offlined cpus
|
|
|
|
*/
|
|
|
|
static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf)
|
|
|
|
{
|
|
|
|
int n = snprintf(buf, PAGE_SIZE-2, "%d\n", CONFIG_NR_CPUS - 1);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
|
|
|
|
|
|
|
|
/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
|
|
|
|
unsigned int total_cpus;
|
|
|
|
|
|
|
|
static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf)
|
|
|
|
{
|
|
|
|
int n = 0, len = PAGE_SIZE-2;
|
|
|
|
cpumask_var_t offline;
|
|
|
|
|
|
|
|
/* display offline cpus < nr_cpu_ids */
|
|
|
|
if (!alloc_cpumask_var(&offline, GFP_KERNEL))
|
|
|
|
return -ENOMEM;
|
|
|
|
cpumask_complement(offline, cpu_online_mask);
|
|
|
|
n = cpulist_scnprintf(buf, len, offline);
|
|
|
|
free_cpumask_var(offline);
|
|
|
|
|
|
|
|
/* display offline cpus >= nr_cpu_ids */
|
|
|
|
if (total_cpus && nr_cpu_ids < total_cpus) {
|
|
|
|
if (n && n < len)
|
|
|
|
buf[n++] = ',';
|
|
|
|
|
|
|
|
if (nr_cpu_ids == total_cpus-1)
|
|
|
|
n += snprintf(&buf[n], len - n, "%d", nr_cpu_ids);
|
|
|
|
else
|
|
|
|
n += snprintf(&buf[n], len - n, "%d-%d",
|
|
|
|
nr_cpu_ids, total_cpus-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
n += snprintf(&buf[n], len - n, "\n");
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
|
|
|
|
|
2008-05-13 03:21:13 +08:00
|
|
|
static struct sysdev_class_attribute *cpu_state_attr[] = {
|
2008-04-09 02:43:04 +08:00
|
|
|
&attr_online_map,
|
|
|
|
&attr_possible_map,
|
|
|
|
&attr_present_map,
|
2008-12-16 12:26:48 +08:00
|
|
|
&attr_kernel_max,
|
|
|
|
&attr_offline,
|
2008-04-09 02:43:04 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int cpu_states_init(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(cpu_state_attr); i++) {
|
|
|
|
int ret;
|
|
|
|
ret = sysdev_class_create_file(&cpu_sysdev_class,
|
|
|
|
cpu_state_attr[i]);
|
|
|
|
if (!err)
|
|
|
|
err = ret;
|
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2007-02-18 02:13:42 +08:00
|
|
|
* register_cpu - Setup a sysfs device for a CPU.
|
2006-12-07 09:14:10 +08:00
|
|
|
* @cpu - cpu->hotpluggable field set to 1 will generate a control file in
|
|
|
|
* sysfs for this CPU.
|
2005-04-17 06:20:36 +08:00
|
|
|
* @num - CPU number to use when creating the device.
|
|
|
|
*
|
|
|
|
* Initialize and register the CPU device.
|
|
|
|
*/
|
2008-02-06 17:36:28 +08:00
|
|
|
int __cpuinit register_cpu(struct cpu *cpu, int num)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
cpu->node_id = cpu_to_node(num);
|
|
|
|
cpu->sysdev.id = num;
|
|
|
|
cpu->sysdev.cls = &cpu_sysdev_class;
|
|
|
|
|
|
|
|
error = sysdev_register(&cpu->sysdev);
|
[PATCH] node hotplug: register cpu: remove node struct
With Goto-san's patch, we can add new pgdat/node at runtime. I'm now
considering node-hot-add with cpu + memory on ACPI.
I found acpi container, which describes node, could evaluate cpu before
memory. This means cpu-hot-add occurs before memory hot add.
In most part, cpu-hot-add doesn't depend on node hot add. But register_cpu(),
which creates symbolic link from node to cpu, requires that node should be
onlined before register_cpu(). When a node is onlined, its pgdat should be
there.
This patch-set holds off creating symbolic link from node to cpu
until node is onlined.
This removes node arguments from register_cpu().
Now, register_cpu() requires 'struct node' as its argument. But the array of
struct node is now unified in driver/base/node.c now (By Goto's node hotplug
patch). We can get struct node in generic way. So, this argument is not
necessary now.
This patch also guarantees add cpu under node only when node is onlined. It
is necessary for node-hot-add vs. cpu-hot-add patch following this.
Moreover, register_cpu calculates cpu->node_id by cpu_to_node() without regard
to its 'struct node *root' argument. This patch removes it.
Also modify callers of register_cpu()/unregister_cpu, whose args are changed
by register-cpu-remove-node-struct patch.
[Brice.Goglin@ens-lyon.org: fix it]
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Yasunori Goto <y-goto@jp.fujitsu.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Brice Goglin <Brice.Goglin@ens-lyon.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27 17:53:41 +08:00
|
|
|
|
2006-12-07 09:14:10 +08:00
|
|
|
if (!error && cpu->hotpluggable)
|
2005-04-17 06:20:36 +08:00
|
|
|
register_cpu_control(cpu);
|
2005-10-31 06:59:49 +08:00
|
|
|
if (!error)
|
2008-05-01 19:35:16 +08:00
|
|
|
per_cpu(cpu_sys_devices, num) = &cpu->sysdev;
|
[PATCH] node hotplug: register cpu: remove node struct
With Goto-san's patch, we can add new pgdat/node at runtime. I'm now
considering node-hot-add with cpu + memory on ACPI.
I found acpi container, which describes node, could evaluate cpu before
memory. This means cpu-hot-add occurs before memory hot add.
In most part, cpu-hot-add doesn't depend on node hot add. But register_cpu(),
which creates symbolic link from node to cpu, requires that node should be
onlined before register_cpu(). When a node is onlined, its pgdat should be
there.
This patch-set holds off creating symbolic link from node to cpu
until node is onlined.
This removes node arguments from register_cpu().
Now, register_cpu() requires 'struct node' as its argument. But the array of
struct node is now unified in driver/base/node.c now (By Goto's node hotplug
patch). We can get struct node in generic way. So, this argument is not
necessary now.
This patch also guarantees add cpu under node only when node is onlined. It
is necessary for node-hot-add vs. cpu-hot-add patch following this.
Moreover, register_cpu calculates cpu->node_id by cpu_to_node() without regard
to its 'struct node *root' argument. This patch removes it.
Also modify callers of register_cpu()/unregister_cpu, whose args are changed
by register-cpu-remove-node-struct patch.
[Brice.Goglin@ens-lyon.org: fix it]
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Yasunori Goto <y-goto@jp.fujitsu.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Brice Goglin <Brice.Goglin@ens-lyon.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27 17:53:41 +08:00
|
|
|
if (!error)
|
|
|
|
register_cpu_under_node(num, cpu_to_node(num));
|
2006-01-10 12:51:42 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_KEXEC
|
|
|
|
if (!error)
|
|
|
|
error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes);
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2006-03-08 15:53:25 +08:00
|
|
|
struct sys_device *get_cpu_sysdev(unsigned cpu)
|
2005-10-31 06:59:49 +08:00
|
|
|
{
|
2008-05-01 19:35:16 +08:00
|
|
|
if (cpu < nr_cpu_ids && cpu_possible(cpu))
|
|
|
|
return per_cpu(cpu_sys_devices, cpu);
|
2005-10-31 06:59:49 +08:00
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(get_cpu_sysdev);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
int __init cpu_dev_init(void)
|
|
|
|
{
|
2006-06-27 17:54:42 +08:00
|
|
|
int err;
|
|
|
|
|
|
|
|
err = sysdev_class_register(&cpu_sysdev_class);
|
2008-04-09 02:43:04 +08:00
|
|
|
if (!err)
|
|
|
|
err = cpu_states_init();
|
|
|
|
|
2006-06-27 17:54:42 +08:00
|
|
|
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
|
|
|
|
if (!err)
|
|
|
|
err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return err;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|