X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fbase%2Fcpu.c;h=dd712b24ec91900f3b75506af6ecf6467f7ba160;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=6ef3069b57107f2e12c5d2c7f238b77f5dacd97c;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 6ef3069b5..dd712b24e 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -9,12 +9,15 @@ #include #include +#include "base.h" struct sysdev_class cpu_sysdev_class = { set_kset_name("cpu"), }; EXPORT_SYMBOL(cpu_sysdev_class); +static struct sys_device *cpu_sys_devices[NR_CPUS]; + #ifdef CONFIG_HOTPLUG_CPU static ssize_t show_online(struct sys_device *dev, char *buf) { @@ -33,10 +36,12 @@ static ssize_t store_online(struct sys_device *dev, const char *buf, case '0': ret = cpu_down(cpu->sysdev.id); if (!ret) - kobject_hotplug(&dev->kobj, KOBJ_OFFLINE); + kobject_uevent(&dev->kobj, KOBJ_OFFLINE); break; case '1': ret = cpu_up(cpu->sysdev.id); + if (!ret) + kobject_uevent(&dev->kobj, KOBJ_ONLINE); break; default: ret = -EINVAL; @@ -54,6 +59,7 @@ static void __devinit register_cpu_control(struct cpu *cpu) } void unregister_cpu(struct cpu *cpu, struct node *root) { + int logical_cpu = cpu->sysdev.id; if (root) sysfs_remove_link(&root->sysdev.kobj, @@ -61,7 +67,7 @@ void unregister_cpu(struct cpu *cpu, struct node *root) sysdev_remove_file(&cpu->sysdev, &attr_online); sysdev_unregister(&cpu->sysdev); - + cpu_sys_devices[logical_cpu] = NULL; return; } #else /* ... !CONFIG_HOTPLUG_CPU */ @@ -70,6 +76,31 @@ static inline void register_cpu_control(struct cpu *cpu) } #endif /* CONFIG_HOTPLUG_CPU */ +#ifdef CONFIG_KEXEC +#include + +static ssize_t show_crash_notes(struct sys_device *dev, char *buf) +{ + 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 + /* * register_cpu - Setup a driverfs device for a CPU. * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to @@ -93,10 +124,24 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root) kobject_name(&cpu->sysdev.kobj)); if (!error && !cpu->no_control) register_cpu_control(cpu); + if (!error) + cpu_sys_devices[num] = &cpu->sysdev; + +#ifdef CONFIG_KEXEC + if (!error) + error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes); +#endif return error; } - +struct sys_device *get_cpu_sysdev(unsigned cpu) +{ + if (cpu < NR_CPUS) + return cpu_sys_devices[cpu]; + else + return NULL; +} +EXPORT_SYMBOL_GPL(get_cpu_sysdev); int __init cpu_dev_init(void) {