Commit b7f523b5 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://ldm.bkbits.net/linux-2.5-core

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 201be7ab 6508e77c
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/cpufreq.h>
#include <asm/leds.h> #include <asm/leds.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -66,13 +65,6 @@ int suspend(void) ...@@ -66,13 +65,6 @@ int suspend(void)
*/ */
device_resume(RESUME_POWER_ON); device_resume(RESUME_POWER_ON);
/*
* Restore the CPU frequency settings.
*/
#ifdef CONFIG_CPU_FREQ
cpufreq_restore();
#endif
/* /*
* Resume LDM devices. * Resume LDM devices.
*/ */
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/sysdev.h>
#include <linux/module.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/smp.h> #include <asm/smp.h>
...@@ -460,9 +463,6 @@ void __init setup_local_APIC (void) ...@@ -460,9 +463,6 @@ void __init setup_local_APIC (void)
#ifdef CONFIG_PM #ifdef CONFIG_PM
#include <linux/device.h>
#include <linux/module.h>
static struct { static struct {
/* 'active' is true if the local APIC was enabled by us and /* 'active' is true if the local APIC was enabled by us and
not the BIOS; this signifies that we are also responsible not the BIOS; this signifies that we are also responsible
...@@ -484,13 +484,11 @@ static struct { ...@@ -484,13 +484,11 @@ static struct {
unsigned int apic_thmr; unsigned int apic_thmr;
} apic_pm_state; } apic_pm_state;
static int lapic_suspend(struct device *dev, u32 state, u32 level) static int lapic_suspend(struct sys_device *dev, u32 state)
{ {
unsigned int l, h; unsigned int l, h;
unsigned long flags; unsigned long flags;
if (level != SUSPEND_POWER_DOWN)
return 0;
if (!apic_pm_state.active) if (!apic_pm_state.active)
return 0; return 0;
...@@ -517,13 +515,11 @@ static int lapic_suspend(struct device *dev, u32 state, u32 level) ...@@ -517,13 +515,11 @@ static int lapic_suspend(struct device *dev, u32 state, u32 level)
return 0; return 0;
} }
static int lapic_resume(struct device *dev, u32 level) static int lapic_resume(struct sys_device *dev)
{ {
unsigned int l, h; unsigned int l, h;
unsigned long flags; unsigned long flags;
if (level != RESUME_POWER_ON)
return 0;
if (!apic_pm_state.active) if (!apic_pm_state.active)
return 0; return 0;
...@@ -557,38 +553,37 @@ static int lapic_resume(struct device *dev, u32 level) ...@@ -557,38 +553,37 @@ static int lapic_resume(struct device *dev, u32 level)
return 0; return 0;
} }
static struct device_driver lapic_driver = {
.name = "lapic", static struct sysdev_class lapic_sysclass = {
.bus = &system_bus_type, set_kset_name("lapic"),
.resume = lapic_resume, .resume = lapic_resume,
.suspend = lapic_suspend, .suspend = lapic_suspend,
}; };
/* not static, needed by child devices */ static struct sys_device device_lapic = {
struct sys_device device_lapic = {
.name = "lapic",
.id = 0, .id = 0,
.dev = { .cls = &lapic_sysclass,
.name = "lapic",
.driver = &lapic_driver,
},
}; };
EXPORT_SYMBOL(device_lapic);
static void __init apic_pm_activate(void) static void __init apic_pm_activate(void)
{ {
apic_pm_state.active = 1; apic_pm_state.active = 1;
} }
static int __init init_lapic_devicefs(void) static int __init init_lapic_sysfs(void)
{ {
int error;
if (!cpu_has_apic) if (!cpu_has_apic)
return 0; return 0;
/* XXX: remove suspend/resume procs if !apic_pm_state.active? */ /* XXX: remove suspend/resume procs if !apic_pm_state.active? */
driver_register(&lapic_driver);
return sys_device_register(&device_lapic); error = sysdev_class_register(&lapic_sysclass);
if (!error)
error = sys_device_register(&device_lapic);
return error;
} }
device_initcall(init_lapic_devicefs); device_initcall(init_lapic_sysfs);
#else /* CONFIG_PM */ #else /* CONFIG_PM */
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/cpu.h>
#include <asm/mtrr.h> #include <asm/mtrr.h>
...@@ -546,6 +547,58 @@ static void init_other_cpus(void) ...@@ -546,6 +547,58 @@ static void init_other_cpus(void)
} }
} }
struct mtrr_value {
mtrr_type ltype;
unsigned long lbase;
unsigned int lsize;
};
static struct mtrr_value * mtrr_state;
static int mtrr_save(struct sys_device * sysdev, u32 state)
{
int i;
int size = num_var_ranges * sizeof(struct mtrr_value);
mtrr_state = kmalloc(size,GFP_KERNEL);
if (mtrr_state)
memset(mtrr_state,0,size);
else
return -ENOMEM;
for (i = 0; i < num_var_ranges; i++) {
mtrr_if->get(i,
&mtrr_state[i].lbase,
&mtrr_state[i].lsize,
&mtrr_state[i].ltype);
}
return 0;
}
static int mtrr_restore(struct sys_device * sysdev)
{
int i;
for (i = 0; i < num_var_ranges; i++) {
if (mtrr_state[i].lsize)
set_mtrr(i,
mtrr_state[i].lbase,
mtrr_state[i].lsize,
mtrr_state[i].ltype);
}
kfree(mtrr_state);
return 0;
}
static struct sysdev_driver mtrr_sysdev_driver = {
.save = mtrr_save,
.restore = mtrr_restore,
};
/** /**
* mtrr_init - initialie mtrrs on the boot CPU * mtrr_init - initialie mtrrs on the boot CPU
* *
...@@ -630,8 +683,11 @@ static int __init mtrr_init(void) ...@@ -630,8 +683,11 @@ static int __init mtrr_init(void)
set_num_var_ranges(); set_num_var_ranges();
init_table(); init_table();
init_other_cpus(); init_other_cpus();
return sysdev_driver_register(&cpu_sysdev_class,
&mtrr_sysdev_driver);
} }
return mtrr_if ? -ENXIO : 0; return -ENXIO;
} }
char *mtrr_strings[MTRR_NUM_TYPES] = char *mtrr_strings[MTRR_NUM_TYPES] =
...@@ -645,5 +701,5 @@ char *mtrr_strings[MTRR_NUM_TYPES] = ...@@ -645,5 +701,5 @@ char *mtrr_strings[MTRR_NUM_TYPES] =
"write-back", /* 6 */ "write-back", /* 6 */
}; };
core_initcall(mtrr_init); subsys_initcall(mtrr_init);
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/device.h> #include <linux/sysdev.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -238,35 +238,31 @@ void mask_and_ack_8259A(unsigned int irq) ...@@ -238,35 +238,31 @@ void mask_and_ack_8259A(unsigned int irq)
} }
} }
static int i8259A_resume(struct device *dev, u32 level) static int i8259A_resume(struct sys_device *dev)
{ {
if (level == RESUME_POWER_ON)
init_8259A(0); init_8259A(0);
return 0; return 0;
} }
static struct device_driver i8259A_driver = { static struct sysdev_class i8259_sysdev_class = {
.name = "pic", set_kset_name("i8259"),
.bus = &system_bus_type,
.resume = i8259A_resume, .resume = i8259A_resume,
}; };
static struct sys_device device_i8259A = { static struct sys_device device_i8259A = {
.name = "pic",
.id = 0, .id = 0,
.dev = { .cls = &i8259_sysdev_class,
.name = "i8259A PIC",
.driver = &i8259A_driver,
},
}; };
static int __init init_8259A_devicefs(void) static int __init i8259A_init_sysfs(void)
{ {
driver_register(&i8259A_driver); int error = sysdev_class_register(&i8259_sysdev_class);
return sys_device_register(&device_i8259A); if (!error)
error = sys_device_register(&device_i8259A);
return error;
} }
device_initcall(init_8259A_devicefs); device_initcall(i8259A_init_sysfs);
void init_8259A(int auto_eoi) void init_8259A(int auto_eoi)
{ {
...@@ -385,35 +381,31 @@ static void setup_timer(void) ...@@ -385,35 +381,31 @@ static void setup_timer(void)
spin_unlock_irqrestore(&i8253_lock, flags); spin_unlock_irqrestore(&i8253_lock, flags);
} }
static int timer_resume(struct device *dev, u32 level) static int timer_resume(struct sys_device *dev)
{ {
if (level == RESUME_POWER_ON)
setup_timer(); setup_timer();
return 0; return 0;
} }
static struct device_driver timer_driver = { static struct sysdev_class timer_sysclass = {
.name = "timer", set_kset_name("timer"),
.bus = &system_bus_type,
.resume = timer_resume, .resume = timer_resume,
}; };
static struct sys_device device_timer = { static struct sys_device device_timer = {
.name = "timer",
.id = 0, .id = 0,
.dev = { .cls = &timer_sysclass,
.name = "timer",
.driver = &timer_driver,
},
}; };
static int __init init_timer_devicefs(void) static int __init init_timer_sysfs(void)
{ {
driver_register(&timer_driver); int error = sysdev_class_register(&timer_sysclass);
return sys_device_register(&device_timer); if (!error)
error = sys_device_register(&device_timer);
return error;
} }
device_initcall(init_timer_devicefs); device_initcall(init_timer_sysfs);
void __init init_IRQ(void) void __init init_IRQ(void)
{ {
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sysdev.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/mtrr.h> #include <asm/mtrr.h>
...@@ -180,53 +181,48 @@ void enable_lapic_nmi_watchdog(void) ...@@ -180,53 +181,48 @@ void enable_lapic_nmi_watchdog(void)
#ifdef CONFIG_PM #ifdef CONFIG_PM
#include <linux/device.h>
static int nmi_pm_active; /* nmi_active before suspend */ static int nmi_pm_active; /* nmi_active before suspend */
static int lapic_nmi_suspend(struct device *dev, u32 state, u32 level) static int lapic_nmi_suspend(struct sys_device *dev, u32 state)
{ {
if (level != SUSPEND_POWER_DOWN)
return 0;
nmi_pm_active = nmi_active; nmi_pm_active = nmi_active;
disable_lapic_nmi_watchdog(); disable_lapic_nmi_watchdog();
return 0; return 0;
} }
static int lapic_nmi_resume(struct device *dev, u32 level) static int lapic_nmi_resume(struct sys_device *dev)
{ {
if (level != RESUME_POWER_ON)
return 0;
if (nmi_pm_active > 0) if (nmi_pm_active > 0)
enable_lapic_nmi_watchdog(); enable_lapic_nmi_watchdog();
return 0; return 0;
} }
static struct device_driver lapic_nmi_driver = {
.name = "lapic_nmi", static struct sysdev_class nmi_sysclass = {
.bus = &system_bus_type, set_kset_name("lapic_nmi"),
.resume = lapic_nmi_resume, .resume = lapic_nmi_resume,
.suspend = lapic_nmi_suspend, .suspend = lapic_nmi_suspend,
}; };
static struct sys_device device_lapic_nmi = { static struct sys_device device_lapic_nmi = {
.name = "lapic_nmi",
.id = 0, .id = 0,
.dev = { .cls = &nmi_sysclass,
.name = "lapic_nmi",
.driver = &lapic_nmi_driver,
.parent = &device_lapic.dev,
},
}; };
static int __init init_lapic_nmi_devicefs(void) static int __init init_lapic_nmi_sysfs(void)
{ {
int error;
if (nmi_active == 0) if (nmi_active == 0)
return 0; return 0;
driver_register(&lapic_nmi_driver);
return sys_device_register(&device_lapic_nmi); error = sysdev_class_register(&nmi_sysclass);
if (!error)
error = sys_device_register(&device_lapic_nmi);
return error;
} }
/* must come after the local APIC's device_initcall() */ /* must come after the local APIC's device_initcall() */
late_initcall(init_lapic_nmi_devicefs); late_initcall(init_lapic_nmi_sysfs);
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h> #include <linux/sysdev.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -278,18 +278,22 @@ unsigned long get_cmos_time(void) ...@@ -278,18 +278,22 @@ unsigned long get_cmos_time(void)
return retval; return retval;
} }
static struct sysdev_class rtc_sysclass = {
set_kset_name("rtc"),
};
/* XXX this driverfs stuff should probably go elsewhere later -john */ /* XXX this driverfs stuff should probably go elsewhere later -john */
static struct sys_device device_i8253 = { static struct sys_device device_i8253 = {
.name = "rtc",
.id = 0, .id = 0,
.dev = { .cls = &rtc_sysclass,
.name = "i8253 Real Time Clock",
},
}; };
static int time_init_device(void) static int time_init_device(void)
{ {
return sys_device_register(&device_i8253); int error = sysdev_class_register(&rtc_sysclass);
if (!error)
error = sys_device_register(&device_i8253);
return error;
} }
device_initcall(time_init_device); device_initcall(time_init_device);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/oprofile.h> #include <linux/oprofile.h>
#include <linux/device.h> #include <linux/sysdev.h>
#include <asm/nmi.h> #include <asm/nmi.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/apic.h> #include <asm/apic.h>
...@@ -31,53 +31,48 @@ static int nmi_enabled = 0; ...@@ -31,53 +31,48 @@ static int nmi_enabled = 0;
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int nmi_suspend(struct device *dev, u32 state, u32 level) static int nmi_suspend(struct sys_device *dev, u32 state)
{ {
if (level != SUSPEND_POWER_DOWN)
return 0;
if (nmi_enabled == 1) if (nmi_enabled == 1)
nmi_stop(); nmi_stop();
return 0; return 0;
} }
static int nmi_resume(struct device *dev, u32 level) static int nmi_resume(struct sys_device *dev)
{ {
if (level != RESUME_POWER_ON)
return 0;
if (nmi_enabled == 1) if (nmi_enabled == 1)
nmi_start(); nmi_start();
return 0; return 0;
} }
static struct device_driver nmi_driver = { static struct sysdev_class oprofile_sysclass = {
.name = "oprofile", set_kset_name("oprofile"),
.bus = &system_bus_type,
.resume = nmi_resume, .resume = nmi_resume,
.suspend = nmi_suspend, .suspend = nmi_suspend,
}; };
static struct device device_nmi = { static struct sys_device device_oprofile = {
.name = "oprofile", .id = 0,
.bus_id = "oprofile", .cls = &oprofile_sysclass,
.driver = &nmi_driver,
.parent = &device_lapic.dev,
}; };
static int __init init_driverfs(void) static int __init init_driverfs(void)
{ {
driver_register(&nmi_driver); int error;
return device_register(&device_nmi); if (!(error = sysdev_class_register(&oprofile_sysclass)))
error = sys_device_register(&device_oprofile);
return error;
} }
static void __exit exit_driverfs(void) static void __exit exit_driverfs(void)
{ {
device_unregister(&device_nmi); sys_device_unregister(&device_oprofile);
driver_unregister(&nmi_driver); sysdev_class_unregister(&oprofile_sysclass);
} }
#else #else
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/device.h> #include <linux/sysdev.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -413,35 +413,31 @@ static void setup_timer(void) ...@@ -413,35 +413,31 @@ static void setup_timer(void)
outb(LATCH >> 8 , 0x40); /* MSB */ outb(LATCH >> 8 , 0x40); /* MSB */
} }
static int timer_resume(struct device *dev, u32 level) static int timer_resume(struct sys_device *dev)
{ {
if (level == RESUME_POWER_ON)
setup_timer(); setup_timer();
return 0; return 0;
} }
static struct device_driver timer_driver = { static struct sysdev_class timer_sysclass = {
.name = "timer", set_kset_name("timer"),
.bus = &system_bus_type,
.resume = timer_resume, .resume = timer_resume,
}; };
static struct sys_device device_timer = { static struct sys_device device_timer = {
.name = "timer",
.id = 0, .id = 0,
.dev = { .cls &timer_sysclass,
.name = "timer",
.driver = &timer_driver,
},
}; };
static int __init init_timer_devicefs(void) static int __init init_timer_sysfs(void)
{ {
driver_register(&timer_driver); int error = sysdev_class_register(&timer_sysclass);
return sys_device_register(&device_timer); if (!error)
error = sys_device_register(&device_timer);
return error;
} }
device_initcall(init_timer_devicefs); device_initcall(init_timer_sysfs);
void __init init_IRQ(void) void __init init_IRQ(void)
{ {
......
...@@ -2,23 +2,18 @@ ...@@ -2,23 +2,18 @@
* drivers/base/cpu.c - basic CPU class support * drivers/base/cpu.c - basic CPU class support
*/ */
#include <linux/device.h> #include <linux/sysdev.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/topology.h> #include <linux/topology.h>
struct class cpu_class = { struct sysdev_class cpu_sysdev_class = {
.name = "cpu", set_kset_name("cpu"),
}; };
struct device_driver cpu_driver = {
.name = "cpu",
.bus = &system_bus_type,
};
/* /*
* register_cpu - Setup a driverfs device for a CPU. * register_cpu - Setup a driverfs device for a CPU.
* @num - CPU number to use when creating the device. * @num - CPU number to use when creating the device.
...@@ -27,42 +22,15 @@ struct device_driver cpu_driver = { ...@@ -27,42 +22,15 @@ struct device_driver cpu_driver = {
*/ */
int __init register_cpu(struct cpu *cpu, int num, struct node *root) int __init register_cpu(struct cpu *cpu, int num, struct node *root)
{ {
int retval;
cpu->node_id = cpu_to_node(num); cpu->node_id = cpu_to_node(num);
cpu->sysdev.name = "cpu";
cpu->sysdev.id = num; cpu->sysdev.id = num;
if (root) cpu->sysdev.cls = &cpu_sysdev_class;
cpu->sysdev.root = &root->sysroot; return sys_device_register(&cpu->sysdev);
snprintf(cpu->sysdev.dev.name, DEVICE_NAME_SIZE, "CPU %u", num);
cpu->sysdev.dev.driver = &cpu_driver;
retval = sys_device_register(&cpu->sysdev);
if (retval)
return retval;
memset(&cpu->sysdev.class_dev, 0x00, sizeof(struct class_device));
cpu->sysdev.class_dev.dev = &cpu->sysdev.dev;
cpu->sysdev.class_dev.class = &cpu_class;
snprintf(cpu->sysdev.class_dev.class_id, BUS_ID_SIZE, "cpu%d", num);
retval = class_device_register(&cpu->sysdev.class_dev);
if (retval) {
sys_device_unregister(&cpu->sysdev);
return retval;
}
return 0;
} }
int __init cpu_dev_init(void) int __init cpu_dev_init(void)
{ {
int error; return sysdev_class_register(&cpu_sysdev_class);
error = class_register(&cpu_class);
if (error)
goto out;
error = driver_register(&cpu_driver);
if (error)
class_unregister(&cpu_class);
out:
return error;
} }
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
* drivers/base/memblk.c - basic Memory Block class support * drivers/base/memblk.c - basic Memory Block class support
*/ */
#include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/memblk.h> #include <linux/memblk.h>
...@@ -10,8 +9,8 @@ ...@@ -10,8 +9,8 @@
#include <linux/topology.h> #include <linux/topology.h>
static struct class memblk_class = { static struct sysdev_class memblk_class = {
.name = "memblk", set_kset_name("memblk"),
}; };
...@@ -29,27 +28,23 @@ static struct device_driver memblk_driver = { ...@@ -29,27 +28,23 @@ static struct device_driver memblk_driver = {
*/ */
int __init register_memblk(struct memblk *memblk, int num, struct node *root) int __init register_memblk(struct memblk *memblk, int num, struct node *root)
{ {
int error;
memblk->node_id = memblk_to_node(num); memblk->node_id = memblk_to_node(num);
memblk->sysdev.name = "memblk"; memblk->sysdev.cls = &memblk_class,
memblk->sysdev.id = num; memblk->sysdev.id = num;
if (root)
memblk->sysdev.root = &root->sysroot; error = sys_device_register(&memblk->sysdev);
snprintf(memblk->sysdev.dev.name, DEVICE_NAME_SIZE, "Memory Block %u", num); if (!error)
memblk->sysdev.dev.driver = &memblk_driver; error = sysfs_create_link(&root->sysdev.kobj,
return sys_device_register(&memblk->sysdev); &memblk->sysdev,kobj,
memblk->sysdev.kobj.name);
return error;
} }
int __init register_memblk_type(void) int __init register_memblk_type(void)
{ {
int error; return sysdev_class_register(&memblk_class);
error = class_register(&memblk_class);
if (!error) {
error = driver_register(&memblk_driver);
if (error)
class_unregister(&memblk_class);
}
return error;
} }
postcore_initcall(register_memblk_type); postcore_initcall(register_memblk_type);
...@@ -9,15 +9,8 @@ ...@@ -9,15 +9,8 @@
#include <linux/node.h> #include <linux/node.h>
#include <linux/topology.h> #include <linux/topology.h>
static struct sysdev_class node_class = {
static struct class node_class = { set_kset_name("node"),
.name = "node",
};
static struct device_driver node_driver = {
.name = "node",
.bus = &system_bus_type,
}; };
...@@ -26,7 +19,7 @@ static ssize_t node_read_cpumap(struct device * dev, char * buf) ...@@ -26,7 +19,7 @@ static ssize_t node_read_cpumap(struct device * dev, char * buf)
struct node *node_dev = to_node(to_root(dev)); struct node *node_dev = to_node(to_root(dev));
return sprintf(buf,"%lx\n",node_dev->cpumap); return sprintf(buf,"%lx\n",node_dev->cpumap);
} }
static DEVICE_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL); static SYSDEV_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL);
#define K(x) ((x) << (PAGE_SHIFT - 10)) #define K(x) ((x) << (PAGE_SHIFT - 10))
static ssize_t node_read_meminfo(struct device * dev, char * buf) static ssize_t node_read_meminfo(struct device * dev, char * buf)
...@@ -52,7 +45,7 @@ static ssize_t node_read_meminfo(struct device * dev, char * buf) ...@@ -52,7 +45,7 @@ static ssize_t node_read_meminfo(struct device * dev, char * buf)
nid, K(i.freeram-i.freehigh)); nid, K(i.freeram-i.freehigh));
} }
#undef K #undef K
static DEVICE_ATTR(meminfo,S_IRUGO,node_read_meminfo,NULL); static SYSDEV_ATTR(meminfo,S_IRUGO,node_read_meminfo,NULL);
/* /*
...@@ -66,17 +59,13 @@ int __init register_node(struct node *node, int num, struct node *parent) ...@@ -66,17 +59,13 @@ int __init register_node(struct node *node, int num, struct node *parent)
int error; int error;
node->cpumap = node_to_cpumask(num); node->cpumap = node_to_cpumask(num);
node->sysroot.id = num; node->sysdev.id = num;
if (parent) node->sysdev.cls = &node_class;
node->sysroot.dev.parent = &parent->sysroot.sysdev; error = sys_device_register(&node->sysdev);
snprintf(node->sysroot.dev.name, DEVICE_NAME_SIZE, "Node %u", num);
snprintf(node->sysroot.dev.bus_id, BUS_ID_SIZE, "node%u", num);
node->sysroot.dev.driver = &node_driver;
node->sysroot.dev.bus = &system_bus_type;
error = sys_register_root(&node->sysroot);
if (!error){ if (!error){
device_create_file(&node->sysroot.dev, &dev_attr_cpumap); sys_device_create_file(&node->sysroot.dev, &attr_cpumap);
device_create_file(&node->sysroot.dev, &dev_attr_meminfo); sys_device_create_file(&node->sysroot.dev, &attr_meminfo);
} }
return error; return error;
} }
...@@ -84,14 +73,6 @@ int __init register_node(struct node *node, int num, struct node *parent) ...@@ -84,14 +73,6 @@ int __init register_node(struct node *node, int num, struct node *parent)
int __init register_node_type(void) int __init register_node_type(void)
{ {
int error; return sysdev_class_register(&node_class);
error = class_register(&node_class);
if (!error) {
error = driver_register(&node_driver);
if (error)
class_unregister(&node_class);
}
return error;
} }
postcore_initcall(register_node_type); postcore_initcall(register_node_type);
...@@ -21,6 +21,21 @@ ...@@ -21,6 +21,21 @@
extern struct subsystem devices_subsys; extern struct subsystem devices_subsys;
/**
* We handle system devices differently - we suspend and shut them
* down first and resume them first. That way, we do anything stupid like
* shutting down the interrupt controller before any devices..
*
* Note that there are not different stages for power management calls -
* they only get one called once when interrupts are disabled.
*/
extern int sysdev_shutdown(void);
extern int sysdev_save(u32 state);
extern int sysdev_suspend(u32 state);
extern int sysdev_resume(void);
extern int sysdev_restore(void);
/** /**
* device_suspend - suspend/remove all devices on the device ree * device_suspend - suspend/remove all devices on the device ree
* @state: state we're entering * @state: state we're entering
...@@ -50,6 +65,21 @@ int device_suspend(u32 state, u32 level) ...@@ -50,6 +65,21 @@ int device_suspend(u32 state, u32 level)
} }
} }
up_write(&devices_subsys.rwsem); up_write(&devices_subsys.rwsem);
/*
* Make sure system devices are suspended.
*/
switch(level) {
case SUSPEND_SAVE_STATE:
sysdev_save(state);
break;
case SUSPEND_POWER_DOWN:
sysdev_suspend(state);
break;
default:
break;
}
return error; return error;
} }
...@@ -65,6 +95,17 @@ void device_resume(u32 level) ...@@ -65,6 +95,17 @@ void device_resume(u32 level)
{ {
struct list_head * node; struct list_head * node;
switch (level) {
case RESUME_POWER_ON:
sysdev_resume();
break;
case RESUME_RESTORE_STATE:
sysdev_restore();
break;
default:
break;
}
down_write(&devices_subsys.rwsem); down_write(&devices_subsys.rwsem);
list_for_each_prev(node,&devices_subsys.kset.list) { list_for_each_prev(node,&devices_subsys.kset.list) {
struct device * dev = to_dev(node); struct device * dev = to_dev(node);
...@@ -98,6 +139,8 @@ void device_shutdown(void) ...@@ -98,6 +139,8 @@ void device_shutdown(void)
pr_debug("Ignored.\n"); pr_debug("Ignored.\n");
} }
up_write(&devices_subsys.rwsem); up_write(&devices_subsys.rwsem);
sysdev_shutdown();
} }
EXPORT_SYMBOL(device_suspend); EXPORT_SYMBOL(device_suspend);
......
...@@ -12,9 +12,9 @@ ...@@ -12,9 +12,9 @@
* add themselves as children of the system bus. * add themselves as children of the system bus.
*/ */
#undef DEBUG #define DEBUG
#include <linux/device.h> #include <linux/sysdev.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -22,130 +22,435 @@ ...@@ -22,130 +22,435 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
/* The default system device parent. */
static struct device system_bus = { extern struct subsystem devices_subsys;
.name = "System Bus",
.bus_id = "sys", #define to_sysdev(k) container_of(k,struct sys_device,kobj)
#define to_sysdev_attr(a) container_of(a,struct sysdev_attribute,attr)
static ssize_t
sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
{
struct sys_device * sysdev = to_sysdev(kobj);
struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
if (sysdev_attr->show)
return sysdev_attr->show(sysdev,buffer);
return 0;
}
static ssize_t
sysdev_store(struct kobject * kobj, struct attribute * attr,
const char * buffer, size_t count)
{
struct sys_device * sysdev = to_sysdev(kobj);
struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
if (sysdev_attr->store)
return sysdev_attr->store(sysdev,buffer,count);
return 0;
}
static struct sysfs_ops sysfs_ops = {
.show = sysdev_show,
.store = sysdev_store,
};
static struct kobj_type ktype_sysdev = {
.sysfs_ops = &sysfs_ops,
}; };
/*
* declare system_subsys
*/
decl_subsys(system,&ktype_sysdev,NULL);
int sysdev_class_register(struct sysdev_class * cls)
{
pr_debug("Registering sysdev class '%s'\n",cls->kset.kobj.name);
INIT_LIST_HEAD(&cls->drivers);
cls->kset.subsys = &system_subsys;
kset_set_kset_s(cls,system_subsys);
return kset_register(&cls->kset);
}
void sysdev_class_unregister(struct sysdev_class * cls)
{
pr_debug("Unregistering sysdev class '%s'\n",cls->kset.kobj.name);
kset_unregister(&cls->kset);
}
EXPORT_SYMBOL(sysdev_class_register);
EXPORT_SYMBOL(sysdev_class_unregister);
static LIST_HEAD(global_drivers);
/** /**
* sys_register_root - add a subordinate system root * sysdev_driver_register - Register auxillary driver
* @root: new root * @cls: Device class driver belongs to.
* * @drv: Driver.
* This is for NUMA-like systems so they can accurately
* represent the topology of the entire system.
* As boards are discovered, a new struct sys_root should
* be allocated and registered.
* The discovery mechanism should initialize the id field
* of the struture, as well as much of the embedded device
* structure as possible, inlcuding the name, the bus_id
* and parent fields.
* *
* This simply calls device_register on the embedded device. * If @cls is valid, then @drv is inserted into @cls->drivers to be
* On success, it will use the struct @root->sysdev * called on each operation on devices of that class. The refcount
* device to create a pseudo-parent for system devices * of @cls is incremented.
* on that board. * Otherwise, @drv is inserted into global_drivers, and called for
* each device.
*/
int sysdev_driver_register(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
down_write(&system_subsys.rwsem);
if (cls && kset_get(&cls->kset))
list_add_tail(&drv->entry,&cls->drivers);
else
list_add_tail(&drv->entry,&global_drivers);
up_write(&system_subsys.rwsem);
return 0;
}
/**
* sysdev_driver_unregister - Remove an auxillary driver.
* @cls: Class driver belongs to.
* @drv: Driver.
*/
void sysdev_driver_unregister(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
down_write(&system_subsys.rwsem);
list_del_init(&drv->entry);
if (cls)
kset_put(&cls->kset);
up_write(&system_subsys.rwsem);
}
/**
* sys_device_register - add a system device to the tree
* @sysdev: device in question
* *
* The platform code can then use @root to specifiy the
* controlling board when discovering and registering
* system devices.
*/ */
int sys_register_root(struct sys_root * root) int sys_device_register(struct sys_device * sysdev)
{ {
int error = 0; int error;
struct sysdev_class * cls = sysdev->cls;
if (!root) if (!cls)
return -EINVAL; return -EINVAL;
if (!root->dev.parent) /* Make sure the kset is set */
root->dev.parent = &system_bus; sysdev->kobj.kset = &cls->kset;
/* set the kobject name */
snprintf(sysdev->kobj.name,KOBJ_NAME_LEN,"%s%d",
cls->kset.kobj.name,sysdev->id);
pr_debug("Registering sys device '%s'\n",sysdev->kobj.name);
pr_debug("Registering system board %d\n",root->id); /* Register the object */
error = kobject_register(&sysdev->kobj);
error = device_register(&root->dev);
if (!error) { if (!error) {
strlcpy(root->sysdev.bus_id,"sys",BUS_ID_SIZE); struct sysdev_driver * drv;
strlcpy(root->sysdev.name,"System Bus",DEVICE_NAME_SIZE);
root->sysdev.parent = &root->dev; down_read(&system_subsys.rwsem);
error = device_register(&root->sysdev); /* Generic notification is implicit, because it's that
}; * code that should have called us.
*/
/* Notify global drivers */
list_for_each_entry(drv,&global_drivers,entry) {
if (drv->add)
drv->add(sysdev);
}
/* Notify class auxillary drivers */
list_for_each_entry(drv,&cls->drivers,entry) {
if (drv->add)
drv->add(sysdev);
}
up_read(&system_subsys.rwsem);
}
return error; return error;
} }
void sys_device_unregister(struct sys_device * sysdev)
{
struct sysdev_driver * drv;
down_read(&system_subsys.rwsem);
list_for_each_entry(drv,&global_drivers,entry) {
if (drv->remove)
drv->remove(sysdev);
}
list_for_each_entry(drv,&sysdev->cls->drivers,entry) {
if (drv->remove)
drv->remove(sysdev);
}
up_read(&system_subsys.rwsem);
kobject_unregister(&sysdev->kobj);
}
/** /**
* sys_unregister_root - remove subordinate root from tree * sysdev_shutdown - Shut down all system devices.
* @root: subordinate root in question. *
* Loop over each class of system devices, and the devices in each
* of those classes. For each device, we call the shutdown method for
* each driver registered for the device - the globals, the auxillaries,
* and the class driver.
* *
* We only decrement the reference count on @root->sysdev * Note: The list is iterated in reverse order, so that we shut down
* and @root->dev. * child devices before we shut down thier parents. The list ordering
* If both are 0, they will be cleaned up by the core. * is guaranteed by virtue of the fact that child devices are registered
* after their parents.
*/ */
void sys_unregister_root(struct sys_root *root)
void sysdev_shutdown(void)
{ {
device_unregister(&root->sysdev); struct sysdev_class * cls;
device_unregister(&root->dev);
pr_debug("Shutting Down System Devices\n");
down_write(&system_subsys.rwsem);
list_for_each_entry_reverse(cls,&system_subsys.kset.list,
kset.kobj.entry) {
struct sys_device * sysdev;
pr_debug("Shutting down type '%s':\n",cls->kset.kobj.name);
list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
struct sysdev_driver * drv;
pr_debug(" %s\n",sysdev->kobj.name);
/* Call global drivers first. */
list_for_each_entry(drv,&global_drivers,entry) {
if (drv->shutdown)
drv->shutdown(sysdev);
}
/* Call auxillary drivers next. */
list_for_each_entry(drv,&cls->drivers,entry) {
if (drv->shutdown)
drv->shutdown(sysdev);
}
/* Now call the generic one */
if (cls->shutdown)
cls->shutdown(sysdev);
}
}
up_write(&system_subsys.rwsem);
} }
/** /**
* sys_device_register - add a system device to the tree * sysdev_save - Save system device state
* @sysdev: device in question * @state: Power state we're entering.
* *
* The hardest part about this is getting the ancestry right. * This is called when the system is going to sleep, but before interrupts
* If the device has a parent - super! We do nothing. * have been disabled. This allows system device drivers to allocate and
* If the device doesn't, but @dev->root is set, then we're * save device state, including sleeping during the process..
* dealing with a NUMA like architecture where each root */
* has a system pseudo-bus to foster the device.
* If not, then we fallback to system_bus (at the top of int sysdev_save(u32 state)
* this file). {
struct sysdev_class * cls;
pr_debug("Saving System Device State\n");
down_write(&system_subsys.rwsem);
list_for_each_entry_reverse(cls,&system_subsys.kset.list,
kset.kobj.entry) {
struct sys_device * sysdev;
pr_debug("Saving state for type '%s':\n",cls->kset.kobj.name);
list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
struct sysdev_driver * drv;
pr_debug(" %s\n",sysdev->kobj.name);
list_for_each_entry(drv,&global_drivers,entry) {
if (drv->save)
drv->save(sysdev,state);
}
list_for_each_entry(drv,&cls->drivers,entry) {
if (drv->save)
drv->save(sysdev,state);
}
if (cls->save)
cls->save(sysdev,state);
}
}
up_write(&system_subsys.rwsem);
return 0;
}
/**
* sysdev_suspend - Suspend all system devices.
* @state: Power state to enter.
* *
* One way or another, we call device_register() on it and * We perform an almost identical operation as sys_device_shutdown()
* are done. * above, though calling ->suspend() instead.
* *
* The caller is also responsible for initializing the bus_id * Note: Interrupts are disabled when called, so we can't sleep when
* and name fields of @sysdev->dev. * trying to get the subsystem's rwsem. If that happens, print a nasty
* warning and return an error.
*/ */
int sys_device_register(struct sys_device * sysdev)
int sysdev_suspend(u32 state)
{ {
if (!sysdev) struct sysdev_class * cls;
return -EINVAL;
if (!sysdev->dev.parent) { pr_debug("Suspending System Devices\n");
if (sysdev->root)
sysdev->dev.parent = &sysdev->root->sysdev; if (!down_write_trylock(&system_subsys.rwsem)) {
else printk("%s: Cannot acquire semaphore; Failing\n",__FUNCTION__);
sysdev->dev.parent = &system_bus; return -EFAULT;
} }
/* make sure bus type is set */ list_for_each_entry_reverse(cls,&system_subsys.kset.list,
if (!sysdev->dev.bus) kset.kobj.entry) {
sysdev->dev.bus = &system_bus_type; struct sys_device * sysdev;
/* construct bus_id */ pr_debug("Suspending type '%s':\n",cls->kset.kobj.name);
snprintf(sysdev->dev.bus_id,BUS_ID_SIZE,"%s%u",sysdev->name,sysdev->id);
pr_debug("Registering system device %s\n", sysdev->dev.bus_id); list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
struct sysdev_driver * drv;
pr_debug(" %s\n",sysdev->kobj.name);
return device_register(&sysdev->dev); /* Call global drivers first. */
list_for_each_entry(drv,&global_drivers,entry) {
if (drv->suspend)
drv->suspend(sysdev,state);
}
/* Call auxillary drivers next. */
list_for_each_entry(drv,&cls->drivers,entry) {
if (drv->suspend)
drv->suspend(sysdev,state);
}
/* Now call the generic one */
if (cls->suspend)
cls->suspend(sysdev,state);
}
}
up_write(&system_subsys.rwsem);
return 0;
} }
void sys_device_unregister(struct sys_device * sysdev)
/**
* sysdev_resume - Bring system devices back to life.
*
* Similar to sys_device_suspend(), but we iterate the list forwards
* to guarantee that parent devices are resumed before their children.
*
* Note: Interrupts are disabled when called.
*/
int sysdev_resume(void)
{ {
if (sysdev) struct sysdev_class * cls;
device_unregister(&sysdev->dev);
pr_debug("Resuming System Devices\n");
if(!down_write_trylock(&system_subsys.rwsem))
return -EFAULT;
list_for_each_entry(cls,&system_subsys.kset.list,kset.kobj.entry) {
struct sys_device * sysdev;
pr_debug("Resuming type '%s':\n",cls->kset.kobj.name);
list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
struct sysdev_driver * drv;
pr_debug(" %s\n",sysdev->kobj.name);
/* First, call the class-specific one */
if (cls->resume)
cls->resume(sysdev);
/* Call auxillary drivers next. */
list_for_each_entry(drv,&cls->drivers,entry) {
if (drv->resume)
drv->resume(sysdev);
}
/* Call global drivers. */
list_for_each_entry(drv,&global_drivers,entry) {
if (drv->resume)
drv->resume(sysdev);
}
}
}
up_write(&system_subsys.rwsem);
return 0;
}
/**
* sysdev_restore - Restore system device state
*
* This is called during a suspend/resume cycle last, after interrupts
* have been re-enabled. This is intended for auxillary drivers, etc,
* that may sleep when restoring state.
*/
int sysdev_restore(void)
{
struct sysdev_class * cls;
down_write(&system_subsys.rwsem);
pr_debug("Restoring System Device State\n");
list_for_each_entry(cls,&system_subsys.kset.list,kset.kobj.entry) {
struct sys_device * sysdev;
pr_debug("Restoring state for type '%s':\n",cls->kset.kobj.name);
list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
struct sysdev_driver * drv;
pr_debug(" %s\n",sysdev->kobj.name);
if (cls->restore)
cls->restore(sysdev);
list_for_each_entry(drv,&cls->drivers,entry) {
if (drv->restore)
drv->restore(sysdev);
}
list_for_each_entry(drv,&global_drivers,entry) {
if (drv->restore)
drv->restore(sysdev);
}
}
}
up_write(&system_subsys.rwsem);
return 0;
} }
struct bus_type system_bus_type = {
.name = "system",
};
int __init sys_bus_init(void) int __init sys_bus_init(void)
{ {
bus_register(&system_bus_type); system_subsys.kset.kobj.parent = &devices_subsys.kset.kobj;
return device_register(&system_bus); return subsystem_register(&system_subsys);
} }
EXPORT_SYMBOL(system_bus_type);
EXPORT_SYMBOL(sys_device_register); EXPORT_SYMBOL(sys_device_register);
EXPORT_SYMBOL(sys_device_unregister); EXPORT_SYMBOL(sys_device_unregister);
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
#include <linux/hdreg.h> /* HDIO_GETGEO */ #include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/device.h> #include <linux/sysdev.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -48,12 +48,14 @@ ...@@ -48,12 +48,14 @@
#define PRINT_WARN(x...) printk(KERN_WARNING XPRAM_NAME " warning:" x) #define PRINT_WARN(x...) printk(KERN_WARNING XPRAM_NAME " warning:" x)
#define PRINT_ERR(x...) printk(KERN_ERR XPRAM_NAME " error:" x) #define PRINT_ERR(x...) printk(KERN_ERR XPRAM_NAME " error:" x)
static struct sysdev_class xpram_sysclass = {
set_kset_name("xpram"),
};
static struct sys_device xpram_sys_device = { static struct sys_device xpram_sys_device = {
.name = "S/390 expanded memory RAM disk", .id = 0,
.dev = { .cls = &xpram_sysclass,
.name = "S/390 expanded memory RAM disk",
.bus_id = "xpram",
},
}; };
typedef struct { typedef struct {
...@@ -485,6 +487,7 @@ static void __exit xpram_exit(void) ...@@ -485,6 +487,7 @@ static void __exit xpram_exit(void)
unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
devfs_remove("slram"); devfs_remove("slram");
sys_device_unregister(&xpram_sys_device); sys_device_unregister(&xpram_sys_device);
sysdev_class_unregister(&xpram_sys_class);
} }
static int __init xpram_init(void) static int __init xpram_init(void)
...@@ -502,9 +505,15 @@ static int __init xpram_init(void) ...@@ -502,9 +505,15 @@ static int __init xpram_init(void)
rc = xpram_setup_sizes(xpram_pages); rc = xpram_setup_sizes(xpram_pages);
if (rc) if (rc)
return rc; return rc;
rc = sys_device_register(&xpram_sys_device); rc = sysdev_class_register(&xpram_sysclass);
if (rc) if (rc)
return rc; return rc;
rc = sys_device_register(&xpram_sys_device);
if (rc) {
sysdev_class_unregister(&xpram_syclass);
return rc;
}
rc = xpram_setup_blkdev(); rc = xpram_setup_blkdev();
if (rc) if (rc)
sys_device_unregister(&xpram_sys_device); sys_device_unregister(&xpram_sys_device);
......
...@@ -84,7 +84,7 @@ static int fill_read_buffer(struct file * file, struct sysfs_buffer * buffer) ...@@ -84,7 +84,7 @@ static int fill_read_buffer(struct file * file, struct sysfs_buffer * buffer)
ssize_t count; ssize_t count;
if (!buffer->page) if (!buffer->page)
buffer->page = (char *) __get_free_page(GFP_KERNEL); buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
if (!buffer->page) if (!buffer->page)
return -ENOMEM; return -ENOMEM;
...@@ -174,7 +174,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char * buf, size_t count) ...@@ -174,7 +174,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char * buf, size_t count)
int error; int error;
if (!buffer->page) if (!buffer->page)
buffer->page = (char *)__get_free_page(GFP_KERNEL); buffer->page = (char *)get_zeroed_page(GFP_KERNEL);
if (!buffer->page) if (!buffer->page)
return -ENOMEM; return -ENOMEM;
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#ifndef _LINUX_CPU_H_ #ifndef _LINUX_CPU_H_
#define _LINUX_CPU_H_ #define _LINUX_CPU_H_
#include <linux/device.h> #include <linux/sysdev.h>
#include <linux/node.h> #include <linux/node.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
...@@ -29,8 +29,6 @@ struct cpu { ...@@ -29,8 +29,6 @@ struct cpu {
}; };
extern int register_cpu(struct cpu *, int, struct node *); extern int register_cpu(struct cpu *, int, struct node *);
extern struct class cpu_class;
struct notifier_block; struct notifier_block;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -48,6 +46,7 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb) ...@@ -48,6 +46,7 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb)
{ {
} }
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
extern struct sysdev_class cpu_sysdev_class;
/* Stop CPUs going up and down. */ /* Stop CPUs going up and down. */
extern struct semaphore cpucontrol; extern struct semaphore cpucontrol;
......
...@@ -205,10 +205,6 @@ struct freq_attr { ...@@ -205,10 +205,6 @@ struct freq_attr {
int cpufreq_set_policy(struct cpufreq_policy *policy); int cpufreq_set_policy(struct cpufreq_policy *policy);
int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
#ifdef CONFIG_PM
int cpufreq_restore(void);
#endif
/* the proc_intf.c needs this */ /* the proc_intf.c needs this */
int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor); int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor);
......
...@@ -351,30 +351,6 @@ extern int (*platform_notify_remove)(struct device * dev); ...@@ -351,30 +351,6 @@ extern int (*platform_notify_remove)(struct device * dev);
extern struct device * get_device(struct device * dev); extern struct device * get_device(struct device * dev);
extern void put_device(struct device * dev); extern void put_device(struct device * dev);
/* drivers/base/sys.c */
struct sys_root {
u32 id;
struct device dev;
struct device sysdev;
};
extern int sys_register_root(struct sys_root *);
extern void sys_unregister_root(struct sys_root *);
struct sys_device {
char * name;
u32 id;
struct sys_root * root;
struct device dev;
struct class_device class_dev;
};
extern int sys_device_register(struct sys_device *);
extern void sys_device_unregister(struct sys_device *);
extern struct bus_type system_bus_type;
/* drivers/base/platform.c */ /* drivers/base/platform.c */
......
...@@ -118,6 +118,14 @@ static inline struct kobj_type * get_ktype(struct kobject * k) ...@@ -118,6 +118,14 @@ static inline struct kobj_type * get_ktype(struct kobject * k)
extern struct kobject * kset_find_obj(struct kset *, const char *); extern struct kobject * kset_find_obj(struct kset *, const char *);
/**
* Use this when initializing an embedded kset with no other
* fields to initialize.
*/
#define set_kset_name(str) .kset = { .kobj = { .name = str } }
struct subsystem { struct subsystem {
struct kset kset; struct kset kset;
struct rw_semaphore rwsem; struct rw_semaphore rwsem;
......
...@@ -309,6 +309,20 @@ static inline void list_splice_init(struct list_head *list, ...@@ -309,6 +309,20 @@ static inline void list_splice_init(struct list_head *list,
pos = list_entry(pos->member.next, typeof(*pos), member), \ pos = list_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next)) prefetch(pos->member.next))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member), \
prefetch(pos->member.prev); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member), \
prefetch(pos->member.prev))
/** /**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop counter. * @pos: the type * to use as a loop counter.
......
...@@ -19,11 +19,11 @@ ...@@ -19,11 +19,11 @@
#ifndef _LINUX_NODE_H_ #ifndef _LINUX_NODE_H_
#define _LINUX_NODE_H_ #define _LINUX_NODE_H_
#include <linux/device.h> #include <linux/sysdev.h>
struct node { struct node {
unsigned long cpumap; /* Bitmap of CPUs on the Node */ unsigned long cpumap; /* Bitmap of CPUs on the Node */
struct sys_root sysroot; struct sys_device sysdev;
}; };
extern int register_node(struct node *, int, struct node *); extern int register_node(struct node *, int, struct node *);
......
/**
* System devices follow a slightly different driver model.
* They don't need to do dynammic driver binding, can't be probed,
* and don't reside on any type of peripheral bus.
* So, we represent and treat them a little differently.
*
* We still have a notion of a driver for a system device, because we still
* want to perform basic operations on these devices.
*
* We also support auxillary drivers binding to devices of a certain class.
*
* This allows configurable drivers to register themselves for devices of
* a certain type. And, it allows class definitions to reside in generic
* code while arch-specific code can register specific drivers.
*
* Auxillary drivers registered with a NULL cls are registered as drivers
* for all system devices, and get notification calls for each device.
*/
#ifndef _SYSDEV_H_
#define _SYSDEV_H_
#include <linux/kobject.h>
struct sys_device;
struct sysdev_class {
struct list_head drivers;
/* Default operations for these types of devices */
int (*shutdown)(struct sys_device *);
int (*save)(struct sys_device *, u32 state);
int (*suspend)(struct sys_device *, u32 state);
int (*resume)(struct sys_device *);
int (*restore)(struct sys_device *);
struct kset kset;
};
extern int sysdev_class_register(struct sysdev_class *);
extern void sysdev_class_unregister(struct sysdev_class *);
/**
* Auxillary system device drivers.
*/
struct sysdev_driver {
struct list_head entry;
int (*add)(struct sys_device *);
int (*remove)(struct sys_device *);
int (*shutdown)(struct sys_device *);
int (*save)(struct sys_device *, u32 state);
int (*suspend)(struct sys_device *, u32 state);
int (*resume)(struct sys_device *);
int (*restore)(struct sys_device *);
};
extern int sysdev_driver_register(struct sysdev_class *, struct sysdev_driver *);
extern void sysdev_driver_unregister(struct sysdev_class *, struct sysdev_driver *);
/**
* sys_devices can be simplified a lot from regular devices, because they're
* simply not as versatile.
*/
struct sys_device {
u32 id;
struct sysdev_class * cls;
struct kobject kobj;
};
extern int sys_device_register(struct sys_device *);
extern void sys_device_unregister(struct sys_device *);
struct sysdev_attribute {
struct attribute attr;
ssize_t (*show)(struct sys_device *, char *);
ssize_t (*store)(struct sys_device *, const char *, size_t);
};
#define SYSDEV_ATTR(_name,_mode,_show,_store) \
struct sysdev_attribute attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
};
extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
#endif /* _SYSDEV_H_ */
...@@ -49,8 +49,6 @@ static DECLARE_RWSEM (cpufreq_notifier_rwsem); ...@@ -49,8 +49,6 @@ static DECLARE_RWSEM (cpufreq_notifier_rwsem);
static LIST_HEAD(cpufreq_governor_list); static LIST_HEAD(cpufreq_governor_list);
static DECLARE_MUTEX (cpufreq_governor_sem); static DECLARE_MUTEX (cpufreq_governor_sem);
static struct class_interface cpufreq_interface;
static int cpufreq_cpu_get(unsigned int cpu) static int cpufreq_cpu_get(unsigned int cpu)
{ {
if (cpu >= NR_CPUS) if (cpu >= NR_CPUS)
...@@ -113,24 +111,8 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, ...@@ -113,24 +111,8 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
EXPORT_SYMBOL_GPL(cpufreq_parse_governor); EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
/* forward declarations */
static int cpufreq_add_dev (struct class_device * dev);
static void cpufreq_remove_dev (struct class_device * dev);
/* drivers/base/cpu.c */ /* drivers/base/cpu.c */
extern struct device_class cpu_devclass; extern struct sysdev_class cpu_sysdev_class;
static struct class_interface cpufreq_interface = {
.class = &cpu_class,
.add = &cpufreq_add_dev,
.remove = &cpufreq_remove_dev,
};
static inline int to_cpu_nr (struct class_device *dev)
{
struct sys_device * cpu_sys_dev = container_of(dev->dev, struct sys_device, dev);
return (cpu_sys_dev->id);
}
/** /**
...@@ -331,9 +313,9 @@ static struct kobj_type ktype_cpufreq = { ...@@ -331,9 +313,9 @@ static struct kobj_type ktype_cpufreq = {
* *
* Adds the cpufreq interface for a CPU device. * Adds the cpufreq interface for a CPU device.
*/ */
static int cpufreq_add_dev (struct class_device * class_dev) static int cpufreq_add_dev (struct sys_device * sys_dev)
{ {
unsigned int cpu = to_cpu_nr(class_dev); unsigned int cpu = sys_dev->id;
int ret = 0; int ret = 0;
struct cpufreq_policy new_policy; struct cpufreq_policy new_policy;
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
...@@ -358,14 +340,12 @@ static int cpufreq_add_dev (struct class_device * class_dev) ...@@ -358,14 +340,12 @@ static int cpufreq_add_dev (struct class_device * class_dev)
memcpy(&new_policy, memcpy(&new_policy,
policy, policy,
sizeof(struct cpufreq_policy)); sizeof(struct cpufreq_policy));
class_set_devdata(class_dev, policy);
up(&cpufreq_driver_sem); up(&cpufreq_driver_sem);
init_MUTEX(&policy->lock); init_MUTEX(&policy->lock);
/* prepare interface data */ /* prepare interface data */
policy->kobj.parent = &class_dev->kobj; policy->kobj.parent = &sys_dev->kobj;
policy->kobj.ktype = &ktype_cpufreq; policy->kobj.ktype = &ktype_cpufreq;
// policy->dev = dev->dev;
strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN);
ret = kobject_register(&policy->kobj); ret = kobject_register(&policy->kobj);
...@@ -396,12 +376,12 @@ static int cpufreq_add_dev (struct class_device * class_dev) ...@@ -396,12 +376,12 @@ static int cpufreq_add_dev (struct class_device * class_dev)
* *
* Removes the cpufreq interface for a CPU device. * Removes the cpufreq interface for a CPU device.
*/ */
static void cpufreq_remove_dev (struct class_device * class_dev) static int cpufreq_remove_dev (struct sys_device * sys_dev)
{ {
unsigned int cpu = to_cpu_nr(class_dev); unsigned int cpu = sys_dev->id;
if (!kobject_get(&cpufreq_driver->policy[cpu].kobj)) if (!kobject_get(&cpufreq_driver->policy[cpu].kobj))
return; return -EFAULT;
down(&cpufreq_driver_sem); down(&cpufreq_driver_sem);
if ((cpufreq_driver->target) && if ((cpufreq_driver->target) &&
...@@ -421,9 +401,17 @@ static void cpufreq_remove_dev (struct class_device * class_dev) ...@@ -421,9 +401,17 @@ static void cpufreq_remove_dev (struct class_device * class_dev)
up(&cpufreq_driver_sem); up(&cpufreq_driver_sem);
kobject_put(&cpufreq_driver->policy[cpu].kobj); kobject_put(&cpufreq_driver->policy[cpu].kobj);
return; return 0;
} }
static int cpufreq_restore(struct sys_device *);
static struct sysdev_driver cpufreq_sysdev_driver = {
.add = cpufreq_add_dev,
.remove = cpufreq_remove_dev,
.restore = cpufreq_restore,
};
/********************************************************************* /*********************************************************************
* NOTIFIER LISTS INTERFACE * * NOTIFIER LISTS INTERFACE *
...@@ -843,7 +831,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) ...@@ -843,7 +831,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
memset(cpufreq_driver->policy, 0, NR_CPUS * sizeof(struct cpufreq_policy)); memset(cpufreq_driver->policy, 0, NR_CPUS * sizeof(struct cpufreq_policy));
return class_interface_register(&cpufreq_interface); return sysdev_driver_register(&cpu_sysdev_class,&cpufreq_sysdev_driver);
} }
EXPORT_SYMBOL_GPL(cpufreq_register_driver); EXPORT_SYMBOL_GPL(cpufreq_register_driver);
...@@ -861,7 +849,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) ...@@ -861,7 +849,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
if (!cpufreq_driver || (driver != cpufreq_driver)) if (!cpufreq_driver || (driver != cpufreq_driver))
return -EINVAL; return -EINVAL;
class_interface_unregister(&cpufreq_interface); sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver);
down(&cpufreq_driver_sem); down(&cpufreq_driver_sem);
kfree(cpufreq_driver->policy); kfree(cpufreq_driver->policy);
...@@ -874,41 +862,34 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); ...@@ -874,41 +862,34 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
#ifdef CONFIG_PM #ifdef CONFIG_PM
/** /**
* cpufreq_restore - restore the CPU clock frequency after resume * cpufreq_restore - restore the CPU clock frequency after resume
* *
* Restore the CPU clock frequency so that our idea of the current * Restore the CPU clock frequency so that our idea of the current
* frequency reflects the actual hardware. * frequency reflects the actual hardware.
*/ */
int cpufreq_restore(void) static int cpufreq_restore(struct sys_device * sysdev)
{ {
struct cpufreq_policy policy; int cpu = sysdev->id;
unsigned int i;
unsigned int ret = 0; unsigned int ret = 0;
struct cpufreq_policy policy;
if (in_interrupt()) if (cpu_online(cpu) && cpufreq_cpu_get(cpu)) {
panic("cpufreq_restore() called from interrupt context!");
if (!try_module_get(cpufreq_driver->owner))
goto error_out;
for (i=0;i<NR_CPUS;i++) {
if (!cpu_online(i) || !cpufreq_cpu_get(i))
continue;
down(&cpufreq_driver_sem); down(&cpufreq_driver_sem);
memcpy(&policy, &cpufreq_driver->policy[i], sizeof(struct cpufreq_policy)); memcpy(&policy, &cpufreq_driver->policy[cpu],
sizeof(struct cpufreq_policy));
up(&cpufreq_driver_sem); up(&cpufreq_driver_sem);
ret += cpufreq_set_policy(&policy); ret = cpufreq_set_policy(&policy);
cpufreq_cpu_put(cpu);
cpufreq_cpu_put(i);
} }
module_put(cpufreq_driver->owner);
error_out:
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(cpufreq_restore);
#else #else
#define cpufreq_restore() do {} while (0) static int cpufreq_restore(struct sys_device * sysdev)
{
return 0;
}
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment