Allow subsystems to avoid using sysdevs for defining "core" PM callbacks
Subsystems (12)
Re: [PATCH 9/10] sh: Use struct syscore_ops instead of sysdev class and sysdev
In reply to Paul MundtQuoted 14 lines · Paul Mundt
Quoted 13 lines · R. J. Wysocki
From: Rafael J. Wysocki <[email protected]>
Convert the SuperH clocks framework and shared interrupt handling code to using struct
syscore_opsinstead of a sysdev classes and sysdevs for power managment.This reduces the code size significantly and simplifies it. The optimizations causing things not to be restored after creating a hibernation image are removed, but they might lead to undesirable effects during resume from hibernation (e.g. the clocks would be left as the boot kernel set them, which might be not the same way as the hibernated kernel had seen them before the hibernation).
Quoted 7 lines
Quoted 4 lines
This also is necessary for removing sysdevs from the kernel entirely in the future.
Signed-off-by Rafael J. Wysocki <[email protected]>This misses the use of the sysdev class by the userimask code, though I'm open to suggestions for alternatives.
For now, I'd simply move the sysdev class definition to userimask.c, like in the patch below. The current goal is to eliminate the suspend/resume and shutdown operations from sysdevs (and sysdev drivers), the next step will be to replace the remaining sysdevs with alternative mechanisms.
Thanks,
Rafael
---
From: Rafael J. Wysocki <[email protected]>
Subject: Drivers / sh: Use struct syscore_ops instead of sysdev class and sysdev (v2)
Convert the SuperH clocks framework and shared interrupt handling code to using struct syscore_ops instead of a sysdev classes and sysdevs for power managment.
This reduces the code size significantly and simplifies it. The optimizations causing things not to be restored after creating a hibernation image are removed, but they might lead to undesirable effects during resume from hibernation (e.g. the clocks would be left as the boot kernel set them, which might be not the same way as the hibernated kernel had seen them before the hibernation).
This also is necessary for removing sysdevs from the kernel entirely in the future.
--- drivers/sh/clk/core.c | 68 +++++++-------------------- drivers/sh/intc/core.c | 108 ++++++++++++++------------------------------ drivers/sh/intc/internals.h | 5 -- drivers/sh/intc/userimask.c | 9 +++ 4 files changed, 63 insertions(+), 127 deletions(-)
drivers/sh/clk/core.c +18 -50
@@ -21,7 +21,7 @@#include <linux/module.h> #include <linux/mutex.h> #include <linux/list.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/seq_file.h> #include <linux/err.h> #include <linux/io.h>
@@ -630,68 +630,36 @@ long clk_round_parent(struct clk *clk, uEXPORT_SYMBOL_GPL (clk_round_parent);#ifdef CONFIG_PM -static int clks_sysdev_suspend (struct sys_device *dev,pm_message_t state) +static void clks_core_resume (void ) { -static pm_message_t prev_state;struct clk *clkp; -switch (state.event) { -case PM_EVENT_ON : -/* Resumeing from hibernation */ -if (prev_state.event !=PM_EVENT_FREEZE ) -break ; - -list_for_each_entry (clkp, &clock_list, node) { -if (likely (clkp->ops)) { -unsigned long rate = clkp->rate; - -if (likely (clkp->ops->set_parent)) - clkp->ops->set_parent (clkp, - clkp->parent); -if (likely (clkp->ops->set_rate)) - clkp->ops->set_rate (clkp, rate); -else if (likely (clkp->ops->recalc)) - clkp->rate = clkp->ops->recalc (clkp); - } +list_for_each_entry (clkp, &clock_list, node) { +if (likely (clkp->ops)) { +unsigned long rate = clkp->rate; + +if (likely (clkp->ops->set_parent)) + clkp->ops->set_parent (clkp, + clkp->parent); +if (likely (clkp->ops->set_rate)) + clkp->ops->set_rate (clkp, rate); +else if (likely (clkp->ops->recalc)) + clkp->rate = clkp->ops->recalc (clkp); } -break ; -case PM_EVENT_FREEZE : -break ; -case PM_EVENT_SUSPEND : -break ; } - - prev_state = state; -return 0 ; -} - -static int clks_sysdev_resume (struct sys_device *dev) -{ -return clks_sysdev_suspend (dev,PMSG_ON ); } -static struct sysdev_class clks_sysdev_class = { - .name ="clks" , -}; - -static struct sysdev_driver clks_sysdev_driver = { - .suspend = clks_sysdev_suspend, - .resume = clks_sysdev_resume, -}; - -static struct sys_device clks_sysdev_dev = { - .cls = &clks_sysdev_class, +static struct syscore_ops clks_syscore_ops = { + .resume = clks_core_resume, }; -static int __init clk_sysdev_init (void ) +static int __init clk_syscore_init (void ) { -sysdev_class_register (&clks_sysdev_class); -sysdev_driver_register (&clks_sysdev_class, &clks_sysdev_driver); -sysdev_register (&clks_sysdev_dev); +register_syscore_ops (&clks_syscore_ops);return 0 ; } -subsys_initcall (clk_sysdev_init); +subsys_initcall (clk_syscore_init);#endif /*
drivers/sh/intc/core.c +35 -73
150 lines not on this page · raw message
drivers/sh/intc/internals.h +1 -4
@@ -4,7 +4,7 @@#include <linux/kernel.h> #include <linux/types.h> #include <linux/radix-tree.h> -#include <linux/sysdev.h> +#include <linux/module.h> #define _INTC_MK (fn, mode, addr_e, addr_d, width, shift) \ ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
@@ -51,9 +51,7 @@ struct intc_subgroup_entry {struct intc_desc_int {struct list_head list; -struct sys_device sysdev;struct radix_tree_root tree; -pm_message_t state;raw_spinlock_t lock;unsigned int index;unsigned long *reg;
@@ -158,7 +156,6 @@ void _intc_enable(struct irq_data *data,extern struct list_head intc_list;extern raw_spinlock_t intc_big_lock;extern unsigned int nr_intc_controllers; -extern struct sysdev_class intc_sysdev_class;unsigned int intc_get_dfl_prio_level (void );unsigned int intc_get_prio_level (unsigned int irq);
drivers/sh/intc/userimask.c +9 -0
@@ -57,12 +57,21 @@ store_intc_userimask(struct sysdev_class static SYSDEV_CLASS_ATTR(userimask, S_IRUSR | S_IWUSR, show_intc_userimask, store_intc_userimask); +static struct sysdev_class intc_sysdev_class = { + .name ="intc" , +};static int __init userimask_sysdev_init (void ) { +int error; +if (unlikely (!uimask))return -ENXIO ; + error =sysdev_class_register (&intc_sysdev_class); +if (error) +return error; +return sysdev_class_create_file (&intc_sysdev_class, &attr_userimask); }late_initcall (userimask_sysdev_init);
Re: [PATCH 9/10] sh: Use struct syscore_ops instead of sysdev class and sysdev
In reply to R. J. WysockiQuoted 13 lines · R. J. Wysocki
From: Rafael J. Wysocki <[email protected]>
Convert the SuperH clocks framework and shared interrupt handling code to using struct
syscore_opsinstead of a sysdev classes and sysdevs for power managment.This reduces the code size significantly and simplifies it. The optimizations causing things not to be restored after creating a hibernation image are removed, but they might lead to undesirable effects during resume from hibernation (e.g. the clocks would be left as the boot kernel set them, which might be not the same way as the hibernated kernel had seen them before the hibernation).
Quoted 4 lines
This also is necessary for removing sysdevs from the kernel entirely in the future.
Signed-off-by Rafael J. Wysocki <[email protected]>
This misses the use of the sysdev class by the userimask code, though I'm open to suggestions for alternatives.
PATCH 9/10 sh: Use struct syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
Convert the SuperH clocks framework and shared interrupt handling code to using struct syscore_ops instead of a sysdev classes and sysdevs for power managment.
This reduces the code size significantly and simplifies it. The optimizations causing things not to be restored after creating a hibernation image are removed, but they might lead to undesirable effects during resume from hibernation (e.g. the clocks would be left as the boot kernel set them, which might be not the same way as the hibernated kernel had seen them before the hibernation).
This also is necessary for removing sysdevs from the kernel entirely in the future.
--- drivers/sh/clk/core.c | 68 +++++++-------------------- drivers/sh/intc/core.c | 108 ++++++++++++++------------------------------ drivers/sh/intc/internals.h | 2 3 files changed, 53 insertions(+), 125 deletions(-)
drivers/sh/clk/core.c +18 -50
@@ -21,7 +21,7 @@#include <linux/module.h> #include <linux/mutex.h> #include <linux/list.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/seq_file.h> #include <linux/err.h> #include <linux/io.h>
@@ -630,68 +630,36 @@ long clk_round_parent(struct clk *clk, uEXPORT_SYMBOL_GPL (clk_round_parent);#ifdef CONFIG_PM -static int clks_sysdev_suspend (struct sys_device *dev,pm_message_t state) +static void clks_core_resume (void ) { -static pm_message_t prev_state;struct clk *clkp; -switch (state.event) { -case PM_EVENT_ON : -/* Resumeing from hibernation */ -if (prev_state.event !=PM_EVENT_FREEZE ) -break ; - -list_for_each_entry (clkp, &clock_list, node) { -if (likely (clkp->ops)) { -unsigned long rate = clkp->rate; - -if (likely (clkp->ops->set_parent)) - clkp->ops->set_parent (clkp, - clkp->parent); -if (likely (clkp->ops->set_rate)) - clkp->ops->set_rate (clkp, rate); -else if (likely (clkp->ops->recalc)) - clkp->rate = clkp->ops->recalc (clkp); - } +list_for_each_entry (clkp, &clock_list, node) { +if (likely (clkp->ops)) { +unsigned long rate = clkp->rate; + +if (likely (clkp->ops->set_parent)) + clkp->ops->set_parent (clkp, + clkp->parent); +if (likely (clkp->ops->set_rate)) + clkp->ops->set_rate (clkp, rate); +else if (likely (clkp->ops->recalc)) + clkp->rate = clkp->ops->recalc (clkp); } -break ; -case PM_EVENT_FREEZE : -break ; -case PM_EVENT_SUSPEND : -break ; } - - prev_state = state; -return 0 ; -} - -static int clks_sysdev_resume (struct sys_device *dev) -{ -return clks_sysdev_suspend (dev,PMSG_ON ); } -static struct sysdev_class clks_sysdev_class = { - .name ="clks" , -}; - -static struct sysdev_driver clks_sysdev_driver = { - .suspend = clks_sysdev_suspend, - .resume = clks_sysdev_resume, -}; - -static struct sys_device clks_sysdev_dev = { - .cls = &clks_sysdev_class, +static struct syscore_ops clks_syscore_ops = { + .resume = clks_core_resume, }; -static int __init clk_sysdev_init (void ) +static int __init clk_syscore_init (void ) { -sysdev_class_register (&clks_sysdev_class); -sysdev_driver_register (&clks_sysdev_class, &clks_sysdev_driver); -sysdev_register (&clks_sysdev_dev); +register_syscore_ops (&clks_syscore_ops);return 0 ; } -subsys_initcall (clk_sysdev_init); +subsys_initcall (clk_syscore_init);#endif /*
drivers/sh/intc/core.c +35 -73
150 lines not on this page · raw message
drivers/sh/intc/internals.h +0 -2
@@ -51,9 +51,7 @@ struct intc_subgroup_entry {struct intc_desc_int {struct list_head list; -struct sys_device sysdev;struct radix_tree_root tree; -pm_message_t state;raw_spinlock_t lock;unsigned int index;unsigned long *reg;
PATCH 10/10 ARM: Use struct syscore_ops instead of sysdevs for PM in timer and leds
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
Convert arch/arm/kernel/time.c and arch/arm/kernel/leds.c to using struct syscore_ops for power management instead of sysdev classes and sysdevs.
This simplifies the code in arch/arm/kernel/time.c quite a bit and is necessary for removing sysdevs from the kernel entirely in future.
--- arch/arm/include/asm/mach/time.h | 1 - arch/arm/kernel/leds.c | 28 ++++++++++++++++------------ arch/arm/kernel/time.c | 33 +++++++++++---------------------- 3 files changed, 27 insertions(+), 35 deletions(-)
Index: linux-2.6/arch/arm/kernel/time.c =================================--- linux-2.6.orig/arch/arm/kernel/time.c +++ linux-2.6/arch/arm/kernel/time.c
@@ -21,7 +21,7 @@
#include <linux/timex.h>
#include <linux/errno.h>
#include <linux/profile.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/timer.h>
#include <linux/irq.h>
@@ -117,48 +117,37 @@ void timer_tick(void)
#endif
#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
-static int timer_suspend(struct sys_device *dev, pm_message_t state) +static int timer_suspend(void)
{
- struct sys_timer *timer = container_of(dev, struct sys_timer, dev);
-
- if (timer->suspend != NULL)
+ if (system_timer->suspend)
timer->suspend();
return 0;
}
-static int timer_resume(struct sys_device *dev)
+static void timer_resume(void)
{
- struct sys_timer *timer = container_of(dev, struct sys_timer, dev);
-
- if (timer->resume != NULL)
- timer->resume();
-
- return 0;
+ if (system_timer->resume)
+ system_timer->resume();
}
#else
#define timer_suspend NULL
#define timer_resume NULL
#endif
-static struct sysdev_class timer_sysclass = {
- .name = "timer",
+static struct syscore_ops timer_syscore_ops = {
.suspend = timer_suspend,
.resume = timer_resume,
};
-static int __init timer_init_sysfs(void)
+static int __init timer_init_syscore_ops(void)
{
- int ret = sysdev_class_register(&timer_sysclass);
- if (ret = 0) {
- system_timer->dev.cls = &timer_sysclass;
- ret = sysdev_register(&system_timer->dev);
- }
+ register_syscore_ops(&timer_syscore_ops);
- return ret;
+ return 0;
}
-device_initcall(timer_init_sysfs);
+device_initcall(timer_init_syscore_ops);
void __init time_init(void)
{
Index: linux-2.6/arch/arm/include/asm/mach/time.h =================================--- linux-2.6.orig/arch/arm/include/asm/mach/time.h +++ linux-2.6/arch/arm/include/asm/mach/time.h
@@ -34,7 +34,6 @@
* timer interrupt which may be pending.
*/
struct sys_timer {
- struct sys_device dev;
void (*init)(void);
void (*suspend)(void);
void (*resume)(void);
Index: linux-2.6/arch/arm/kernel/leds.c =================================--- linux-2.6.orig/arch/arm/kernel/leds.c +++ linux-2.6/arch/arm/kernel/leds.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <asm/leds.h>
@@ -69,36 +70,37 @@ static ssize_t leds_store(struct sys_dev
static SYSDEV_ATTR(event, 0200, NULL, leds_store);
-static int leds_suspend(struct sys_device *dev, pm_message_t state) +static struct sysdev_class leds_sysclass = {
+ .name = "leds",
+};
+
+static struct sys_device leds_device = {
+ .id = 0,
+ .cls = &leds_sysclass,
+};
+
+static int leds_suspend(void)
{
leds_event(led_stop);
return 0;
}
-static int leds_resume(struct sys_device *dev)
+static void leds_resume(void)
{
leds_event(led_start);
- return 0;
}
-static int leds_shutdown(struct sys_device *dev)
+static void leds_shutdown(void)
{
leds_event(led_halted);
- return 0;
}
-static struct sysdev_class leds_sysclass = {
- .name = "leds",
+static struct syscore_ops leds_syscore_ops = {
.shutdown = leds_shutdown,
.suspend = leds_suspend,
.resume = leds_resume,
};
-static struct sys_device leds_device = {
- .id = 0,
- .cls = &leds_sysclass,
-};
-
static int __init leds_init(void)
{
int ret;
@@ -107,6 +109,8 @@ static int __init leds_init(void)
ret = sysdev_register(&leds_device);
if (ret = 0)
ret = sysdev_create_file(&leds_device, &attr_event);
+ if (ret = 0)
+ register_syscore_ops(&leds_syscore_ops);
return ret;
}
Re: [PATCH 10/10] ARM: Use struct syscore_ops instead of sysdevs for PM in timer and leds
Review
Quoted 10 lines · Rafael J. Wysocki
#if defined(CONFIG_PM)&& !defined(CONFIG_GENERIC_CLOCKEVENTS)(quoted diff) +2
-4-static int timer_suspend(struct sys_device *dev, pm_message_t state) +static int timer_suspend(void) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - - if (timer->suspend != NULL) + if (system_timer->suspend) timer->suspend();
Shouldn't this be system_timer->suspend() ?
Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
[Update] Re: [PATCH 10/10] ARM: Use struct syscore_ops instead of sysdevs for PM in timer and leds
Quoted 13 lines · Stephen Boyd
Review
Quoted 10 lines · Rafael J. Wysocki
#if defined(CONFIG_PM)&& !defined(CONFIG_GENERIC_CLOCKEVENTS)(quoted diff) +2
-4-static int timer_suspend(struct sys_device *dev, pm_message_t state) +static int timer_suspend(void) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - - if (timer->suspend != NULL) + if (system_timer->suspend) timer->suspend();Shouldn't this be
system_timer->suspend()?
Indeed, thanks a lot!
I must have forgotten to test it with CONFIG_GENERIC_CLOCKEVENTS unset.
Updated patch follows.
---
From: Rafael J. Wysocki <[email protected]>
Subject: ARM: Use struct syscore_ops instead of sysdevs for PM in timer and leds
Convert arch/arm/kernel/time.c and arch/arm/kernel/leds.c to using struct syscore_ops for power management instead of sysdev classes and sysdevs.
This simplifies the code in arch/arm/kernel/time.c quite a bit and is necessary for removing sysdevs from the kernel entirely in future.
--- arch/arm/include/asm/mach/time.h | 1 - arch/arm/kernel/leds.c | 28 ++++++++++++++++------------ arch/arm/kernel/time.c | 35 ++++++++++++----------------------- 3 files changed, 28 insertions(+), 36 deletions(-)
arch/arm/kernel/time.c +12 -23
@@ -21,7 +21,7 @@#include <linux/timex.h> #include <linux/errno.h> #include <linux/profile.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/timer.h> #include <linux/irq.h>
@@ -117,48 +117,37 @@ void timer_tick(void)#endif #if defined(CONFIG_PM ) && !defined(CONFIG_GENERIC_CLOCKEVENTS ) -static int timer_suspend (struct sys_device *dev,pm_message_t state) +static int timer_suspend (void ) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - -if (timer->suspend !=NULL ) - timer->suspend (); +if (system_timer->suspend) + system_timer->suspend ();return 0 ; } -static int timer_resume (struct sys_device *dev) +static void timer_resume (void ) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - -if (timer->resume !=NULL ) - timer->resume (); - -return 0 ; +if (system_timer->resume) + system_timer->resume (); }#else #define timer_suspend NULL#define timer_resume NULL#endif -static struct sysdev_class timer_sysclass = { - .name ="timer" , +static struct syscore_ops timer_syscore_ops = { .suspend = timer_suspend, .resume = timer_resume, }; -static int __init timer_init_sysfs (void ) +static int __init timer_init_syscore_ops (void ) { -int ret =sysdev_class_register (&timer_sysclass); -if (ret ==0 ) { - system_timer->dev.cls = &timer_sysclass; - ret =sysdev_register (&system_timer->dev); - } +register_syscore_ops (&timer_syscore_ops); -return ret; +return 0 ; } -device_initcall (timer_init_sysfs); +device_initcall (timer_init_syscore_ops);void __init time_init (void ) {
arch/arm/include/asm/mach/time.h +0 -1
@@ -34,7 +34,6 @@* timer interrupt which may be pending. */ struct sys_timer { -struct sys_device dev;void (*init)(void );void (*suspend)(void );void (*resume)(void );
arch/arm/kernel/leds.c +16 -12
@@ -10,6 +10,7 @@#include <linux/module.h> #include <linux/init.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <asm/leds.h>
@@ -69,36 +70,37 @@ static ssize_t leds_store(struct sys_dev static SYSDEV_ATTR(event, 0200, NULL, leds_store); -static int leds_suspend (struct sys_device *dev,pm_message_t state) +static struct sysdev_class leds_sysclass = { + .name ="leds" , +}; + +static struct sys_device leds_device = { + .id =0 , + .cls = &leds_sysclass, +}; + +static int leds_suspend (void ) {leds_event (led_stop);return 0 ; } -static int leds_resume (struct sys_device *dev) +static void leds_resume (void ) {leds_event (led_start); -return 0 ; } -static int leds_shutdown (struct sys_device *dev) +static void leds_shutdown (void ) {leds_event (led_halted); -return 0 ; } -static struct sysdev_class leds_sysclass = { - .name ="leds" , +static struct syscore_ops leds_syscore_ops = { .shutdown = leds_shutdown, .suspend = leds_suspend, .resume = leds_resume, }; -static struct sys_device leds_device = { - .id =0 , - .cls = &leds_sysclass, -}; -static int __init leds_init (void ) {int ret;
@@ -107,6 +109,8 @@ static int __init leds_init(void) ret =sysdev_register (&leds_device);if (ret ==0 ) ret =sysdev_create_file (&leds_device, &attr_event); +if (ret ==0 ) +register_syscore_ops (&leds_syscore_ops);return ret; }
[Update] Re: [PATCH 10/10] ARM: Use struct syscore_ops instead of sysdevs for PM in timer and leds
In reply to Stephen BoydQuoted 13 lines · Stephen Boyd
Review
Quoted 10 lines · Rafael J. Wysocki
#if defined(CONFIG_PM)&& !defined(CONFIG_GENERIC_CLOCKEVENTS)(quoted diff) +2
-4-static int timer_suspend(struct sys_device *dev, pm_message_t state) +static int timer_suspend(void) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - - if (timer->suspend != NULL) + if (system_timer->suspend) timer->suspend();Shouldn't this be
system_timer->suspend()?
Indeed, thanks a lot!
I must have forgotten to test it with CONFIG_GENERIC_CLOCKEVENTS unset.
Updated patch follows.
---
From: Rafael J. Wysocki <[email protected]>
Subject: ARM: Use struct syscore_ops instead of sysdevs for PM in timer and leds
Convert arch/arm/kernel/time.c and arch/arm/kernel/leds.c to using struct syscore_ops for power management instead of sysdev classes and sysdevs.
This simplifies the code in arch/arm/kernel/time.c quite a bit and is necessary for removing sysdevs from the kernel entirely in future.
--- arch/arm/include/asm/mach/time.h | 1 - arch/arm/kernel/leds.c | 28 ++++++++++++++++------------ arch/arm/kernel/time.c | 35 ++++++++++++----------------------- 3 files changed, 28 insertions(+), 36 deletions(-)
arch/arm/kernel/time.c +12 -23
@@ -21,7 +21,7 @@#include <linux/timex.h> #include <linux/errno.h> #include <linux/profile.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/timer.h> #include <linux/irq.h>
@@ -117,48 +117,37 @@ void timer_tick(void)#endif #if defined(CONFIG_PM ) && !defined(CONFIG_GENERIC_CLOCKEVENTS ) -static int timer_suspend (struct sys_device *dev,pm_message_t state) +static int timer_suspend (void ) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - -if (timer->suspend !=NULL ) - timer->suspend (); +if (system_timer->suspend) + system_timer->suspend ();return 0 ; } -static int timer_resume (struct sys_device *dev) +static void timer_resume (void ) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - -if (timer->resume !=NULL ) - timer->resume (); - -return 0 ; +if (system_timer->resume) + system_timer->resume (); }#else #define timer_suspend NULL#define timer_resume NULL#endif -static struct sysdev_class timer_sysclass = { - .name ="timer" , +static struct syscore_ops timer_syscore_ops = { .suspend = timer_suspend, .resume = timer_resume, }; -static int __init timer_init_sysfs (void ) +static int __init timer_init_syscore_ops (void ) { -int ret =sysdev_class_register (&timer_sysclass); -if (ret ==0 ) { - system_timer->dev.cls = &timer_sysclass; - ret =sysdev_register (&system_timer->dev); - } +register_syscore_ops (&timer_syscore_ops); -return ret; +return 0 ; } -device_initcall (timer_init_sysfs); +device_initcall (timer_init_syscore_ops);void __init time_init (void ) {
arch/arm/include/asm/mach/time.h +0 -1
@@ -34,7 +34,6 @@* timer interrupt which may be pending. */ struct sys_timer { -struct sys_device dev;void (*init)(void );void (*suspend)(void );void (*resume)(void );
arch/arm/kernel/leds.c +16 -12
@@ -10,6 +10,7 @@#include <linux/module.h> #include <linux/init.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <asm/leds.h>
@@ -69,36 +70,37 @@ static ssize_t leds_store(struct sys_dev static SYSDEV_ATTR(event, 0200, NULL, leds_store); -static int leds_suspend (struct sys_device *dev,pm_message_t state) +static struct sysdev_class leds_sysclass = { + .name ="leds" , +}; + +static struct sys_device leds_device = { + .id =0 , + .cls = &leds_sysclass, +}; + +static int leds_suspend (void ) {leds_event (led_stop);return 0 ; } -static int leds_resume (struct sys_device *dev) +static void leds_resume (void ) {leds_event (led_start); -return 0 ; } -static int leds_shutdown (struct sys_device *dev) +static void leds_shutdown (void ) {leds_event (led_halted); -return 0 ; } -static struct sysdev_class leds_sysclass = { - .name ="leds" , +static struct syscore_ops leds_syscore_ops = { .shutdown = leds_shutdown, .suspend = leds_suspend, .resume = leds_resume, }; -static struct sys_device leds_device = { - .id =0 , - .cls = &leds_sysclass, -}; -static int __init leds_init (void ) {int ret;
@@ -107,6 +109,8 @@ static int __init leds_init(void) ret =sysdev_register (&leds_device);if (ret ==0 ) ret =sysdev_create_file (&leds_device, &attr_event); +if (ret ==0 ) +register_syscore_ops (&leds_syscore_ops);return ret; }
Re: [PATCH 10/10] ARM: Use struct syscore_ops instead of sysdevs for PM in timer and leds
In reply to Rafael J. WysockiReview
Quoted 10 lines · Rafael J. Wysocki
#if defined(CONFIG_PM)&& !defined(CONFIG_GENERIC_CLOCKEVENTS)(quoted diff) +2
-4-static int timer_suspend(struct sys_device *dev, pm_message_t state) +static int timer_suspend(void) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - - if (timer->suspend != NULL) + if (system_timer->suspend) timer->suspend();
Shouldn't this be system_timer->suspend() ?
Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
PATCH 10/10 ARM: Use struct syscore_ops instead of sysdevs for PM in timer and leds
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
Convert arch/arm/kernel/time.c and arch/arm/kernel/leds.c to using struct syscore_ops for power management instead of sysdev classes and sysdevs.
This simplifies the code in arch/arm/kernel/time.c quite a bit and is necessary for removing sysdevs from the kernel entirely in future.
--- arch/arm/include/asm/mach/time.h | 1 - arch/arm/kernel/leds.c | 28 ++++++++++++++++------------ arch/arm/kernel/time.c | 33 +++++++++++---------------------- 3 files changed, 27 insertions(+), 35 deletions(-)
arch/arm/kernel/time.c +11 -22
@@ -21,7 +21,7 @@#include <linux/timex.h> #include <linux/errno.h> #include <linux/profile.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/timer.h> #include <linux/irq.h>
@@ -117,48 +117,37 @@ void timer_tick(void)#endif #if defined(CONFIG_PM ) && !defined(CONFIG_GENERIC_CLOCKEVENTS ) -static int timer_suspend (struct sys_device *dev,pm_message_t state) +static int timer_suspend (void ) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - -if (timer->suspend !=NULL ) +if (system_timer->suspend) timer->suspend ();return 0 ; } -static int timer_resume (struct sys_device *dev) +static void timer_resume (void ) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - -if (timer->resume !=NULL ) - timer->resume (); - -return 0 ; +if (system_timer->resume) + system_timer->resume (); }#else #define timer_suspend NULL#define timer_resume NULL#endif -static struct sysdev_class timer_sysclass = { - .name ="timer" , +static struct syscore_ops timer_syscore_ops = { .suspend = timer_suspend, .resume = timer_resume, }; -static int __init timer_init_sysfs (void ) +static int __init timer_init_syscore_ops (void ) { -int ret =sysdev_class_register (&timer_sysclass); -if (ret ==0 ) { - system_timer->dev.cls = &timer_sysclass; - ret =sysdev_register (&system_timer->dev); - } +register_syscore_ops (&timer_syscore_ops); -return ret; +return 0 ; } -device_initcall (timer_init_sysfs); +device_initcall (timer_init_syscore_ops);void __init time_init (void ) {
arch/arm/include/asm/mach/time.h +0 -1
@@ -34,7 +34,6 @@* timer interrupt which may be pending. */ struct sys_timer { -struct sys_device dev;void (*init)(void );void (*suspend)(void );void (*resume)(void );
arch/arm/kernel/leds.c +16 -12
@@ -10,6 +10,7 @@#include <linux/module.h> #include <linux/init.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <asm/leds.h>
@@ -69,36 +70,37 @@ static ssize_t leds_store(struct sys_dev static SYSDEV_ATTR(event, 0200, NULL, leds_store); -static int leds_suspend (struct sys_device *dev,pm_message_t state) +static struct sysdev_class leds_sysclass = { + .name ="leds" , +}; + +static struct sys_device leds_device = { + .id =0 , + .cls = &leds_sysclass, +}; + +static int leds_suspend (void ) {leds_event (led_stop);return 0 ; } -static int leds_resume (struct sys_device *dev) +static void leds_resume (void ) {leds_event (led_start); -return 0 ; } -static int leds_shutdown (struct sys_device *dev) +static void leds_shutdown (void ) {leds_event (led_halted); -return 0 ; } -static struct sysdev_class leds_sysclass = { - .name ="leds" , +static struct syscore_ops leds_syscore_ops = { .shutdown = leds_shutdown, .suspend = leds_suspend, .resume = leds_resume, }; -static struct sys_device leds_device = { - .id =0 , - .cls = &leds_sysclass, -}; -static int __init leds_init (void ) {int ret;
@@ -107,6 +109,8 @@ static int __init leds_init(void) ret =sysdev_register (&leds_device);if (ret ==0 ) ret =sysdev_create_file (&leds_device, &attr_event); +if (ret ==0 ) +register_syscore_ops (&leds_syscore_ops);return ret; }
PATCH 1/1 Allow subsystems to avoid using sysdevs for defining "core" PM callbacks
In reply to Rafael J. WysockiQuoted 64 lines · Rafael J. Wysocki
Hi,
Quoted 35 lines · Rafael J. Wysocki
There are multiple problems with sysdevs, or struct
sys_deviceobjects to be precise, that are so annoying that some people have started to think of removind them entirely from the kernel. To me, personally, the most obvious issue is the way sysdevs are used for defining suspend/resume callbacks to be executed with one CPU on-line and interrupts disabled. Greg and Kay may tell you more about the other problems with sysdevs. :-)Some subsystems need to carry out certain operations during suspend after we've disabled non-boot CPUs and interrupts have been switched off on the only on-line one. Currently, the only way to achieve that is to define sysdev suspend/resume callbacks, but this is cumbersome and inefficient. Namely, to do that, one has to define a sysdev class providing the callbacks and a sysdev actually using them, which is excessively complicated. Moreover, the sysdev suspend/resume callbacks take arguments that are not really used by the majority of subsystems defining sysdev suspend/resume callbacks (or even if they are used, they don't really _need_ to be used, so they are simply unnecessary). Of course, if a sysdev is only defined to provide suspend/resume (and maybe shutdown) callbacks, there's no real reason why it should show up in sysfs.
For this reason, I thought it would be a good idea to provide a simpler interface for subsystems to define "very late" suspend callbacks and "very early" resume callbacks (and "very late" shutdown callbacks as well) without the entire bloat related to sysdevs. The interface is introduced by the first of the following patches, while the second patch converts some sysdev users related to the x86 architecture to using the new interface.
I believe that call sysdev users who need to define suspend/resume/shutdown callbacks may be converted to using the interface provided by the first patch, which in turn should allow us to convert the remaining sysdev functionality into "normal" struct device interfaces. Still, even if that turns out to be too complicated, the bloat reduction resulting from the second patch kind of shows that moving at least some sysdev users to a simpler interface (like in the first patch) is a good idea anyway.
Quoted 4 lines
This is a proof of concept, so the patches have not been tested. Please be extrememly careful, because they touch sensitive code, so to speak. In the majority of cases the changes are rather straightforward, but there are some more interesting cases as well (
io_apic.cmost importantly).Since Greg likes the idea and there haven't been any objections so far, here's the official submission. The patches have been tested on HP nx6325 and Toshiba Portege R500.
Patch [1/8] is regareded as 2.6.38 material, following Greg's advice. The other patches in the set are regarded as 2.6.39 material. The last one obviously depends on all of the previous ones.
[1/8] - Introduce struct
syscore_opsfor registering operations to be run on
one CPU during suspend/resume/shutdown.[2/8] - Convert sysdev users in
arch/x86to using structsyscore_ops.[3/8] - Make ACPI use struct
syscore_opsforirqrouter_resume().[4/8] - Make timekeeping use struct
syscore_opsfor suspend/resume.[5/8] - Make Intel IOMMU use struct
syscore_opsfor suspend/resume.[6/8] - Make KVM use struct
syscore_opsfor suspend/resume.
Quoted 7 lines
[7/8] - Make cpufreq use struct
syscore_opsfor boot CPU suspend/resume.[8/8] - Introduce config switch allowing architectures to skip sysdev
suspend/resume/shutdown code.If there are no objectsions, I'd like to push these patches through the suspend tree.
A little followup with two ARM-related patches.
[9/10] - Make sh drivers use struct syscore_ops for suspend/resume (instead of
sysdevs).
[10/10] - Use struct syscore_ops for suspend/resume (instead of sysdevs) in
core ARM code.
Thanks,
Rafael
cover Do not use sysdevs for implementing "core" PM operations on x86
In reply to Rafael J. WysockiHi,
Quoted 62 lines · Rafael J. Wysocki
Quoted 35 lines · Rafael J. Wysocki
There are multiple problems with sysdevs, or struct
sys_deviceobjects to be precise, that are so annoying that some people have started to think of removind them entirely from the kernel. To me, personally, the most obvious issue is the way sysdevs are used for defining suspend/resume callbacks to be executed with one CPU on-line and interrupts disabled. Greg and Kay may tell you more about the other problems with sysdevs. :-)Some subsystems need to carry out certain operations during suspend after we've disabled non-boot CPUs and interrupts have been switched off on the only on-line one. Currently, the only way to achieve that is to define sysdev suspend/resume callbacks, but this is cumbersome and inefficient. Namely, to do that, one has to define a sysdev class providing the callbacks and a sysdev actually using them, which is excessively complicated. Moreover, the sysdev suspend/resume callbacks take arguments that are not really used by the majority of subsystems defining sysdev suspend/resume callbacks (or even if they are used, they don't really _need_ to be used, so they are simply unnecessary). Of course, if a sysdev is only defined to provide suspend/resume (and maybe shutdown) callbacks, there's no real reason why it should show up in sysfs.
For this reason, I thought it would be a good idea to provide a simpler interface for subsystems to define "very late" suspend callbacks and "very early" resume callbacks (and "very late" shutdown callbacks as well) without the entire bloat related to sysdevs. The interface is introduced by the first of the following patches, while the second patch converts some sysdev users related to the x86 architecture to using the new interface.
I believe that call sysdev users who need to define suspend/resume/shutdown callbacks may be converted to using the interface provided by the first patch, which in turn should allow us to convert the remaining sysdev functionality into "normal" struct device interfaces. Still, even if that turns out to be too complicated, the bloat reduction resulting from the second patch kind of shows that moving at least some sysdev users to a simpler interface (like in the first patch) is a good idea anyway.
Quoted 4 lines
This is a proof of concept, so the patches have not been tested. Please be extrememly careful, because they touch sensitive code, so to speak. In the majority of cases the changes are rather straightforward, but there are some more interesting cases as well (
io_apic.cmost importantly).Since Greg likes the idea and there haven't been any objections so far, here's the official submission. The patches have been tested on HP nx6325 and Toshiba Portege R500.
Patch [1/8] is regareded as 2.6.38 material, following Greg's advice. The other patches in the set are regarded as 2.6.39 material. The last one obviously depends on all of the previous ones.
[1/8] - Introduce struct
syscore_opsfor registering operations to be run on
one CPU during suspend/resume/shutdown.[2/8] - Convert sysdev users in
arch/x86to using structsyscore_ops.[3/8] - Make ACPI use struct
syscore_opsforirqrouter_resume().[4/8] - Make timekeeping use struct
syscore_opsfor suspend/resume.[5/8] - Make Intel IOMMU use struct
syscore_opsfor suspend/resume.[6/8] - Make KVM use struct
syscore_opsfor suspend/resume.
Quoted 7 lines
[7/8] - Make cpufreq use struct
syscore_opsfor boot CPU suspend/resume.[8/8] - Introduce config switch allowing architectures to skip sysdev
suspend/resume/shutdown code.If there are no objectsions, I'd like to push these patches through the suspend tree.
[1/8] has been merged in the meantime and [3/8] has been included into the ACPI tree. if there are no objections, I'm going to push the following patches to Linus this week through the suspend-2.6 tree:
[1/6] - Convert sysdev users in arch/x86 to using struct syscore_ops.
[2/6] - Make timekeeping use struct syscore_ops for suspend/resume.
[3/6] - Make Intel IOMMU use struct syscore_ops for suspend/resume.
[4/6] - Make KVM use struct syscore_ops for suspend/resume.
[5/6] - Make cpufreq use struct syscore_ops for boot CPU suspend/resume.
[6/6] - Introduce config switch allowing architectures to skip sysdev
suspend/resume/shutdown code.
Thanks,
Rafael
PATCH 1/6 x86: Use syscore_ops instead of sysdev classes and sysdevs
From: Rafael J. Wysocki <[email protected]>
Some subsystems in the x86 tree need to carry out suspend/resume and shutdown operations with one CPU on-line and interrupts disabled and they define sysdev classes and sysdevs or sysdev drivers for this purpose. This leads to unnecessarily complicated code and excessive memory usage, so switch them to using struct syscore_ops objects for this purpose instead.
Generally, there are three categories of subsystems that use sysdevs for implementing PM operations: (1) subsystems whose suspend/resume callbacks ignore their arguments entirely (the majority), (2) subsystems whose suspend/resume callbacks use their struct sys_device argument, but don't really need to do that, because they can be implemented differently in an arguably simpler way (io_apic.c), and (3) subsystems whose suspend/resume callbacks use their struct sys_device argument, but the value of that argument is always the same and could be ignored (microcode_core.c). In all of these cases the subsystems in question may be readily converted to using struct syscore_ops objects for power management and shutdown.
--- arch/x86/kernel/amd_iommu_init.c | 26 ++-------- arch/x86/kernel/apic/apic.c | 33 +++---------- arch/x86/kernel/apic/io_apic.c | 97 ++++++++++++++++++--------------------- arch/x86/kernel/cpu/mcheck/mce.c | 21 ++++---- arch/x86/kernel/cpu/mtrr/main.c | 10 ++-- arch/x86/kernel/i8237.c | 30 ++---------- arch/x86/kernel/i8259.c | 33 ++++--------- arch/x86/kernel/microcode_core.c | 34 +++++-------- arch/x86/kernel/pci-gart_64.c | 32 ++---------- arch/x86/oprofile/nmi_int.c | 44 ++++------------- 10 files changed, 128 insertions(+), 232 deletions(-)
arch/x86/kernel/amd_iommu_init.c +6 -20
@@ -21,7 +21,7 @@#include <linux/acpi.h> #include <linux/list.h> #include <linux/slab.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/interrupt.h> #include <linux/msi.h> #include <asm/pci-direct.h>
@@ -1260,7 +1260,7 @@ static void disable_iommus(void)* disable suspend until real resume implemented */ -static int amd_iommu_resume (struct sys_device *dev) +static void amd_iommu_resume (void ) {struct amd_iommu *iommu;
@@ -1276,11 +1276,9 @@ static int amd_iommu_resume(struct sys_d*/ amd_iommu_flush_all_devices ();amd_iommu_flush_all_domains (); - -return 0 ; } -static int amd_iommu_suspend (struct sys_device *dev,pm_message_t state) +static int amd_iommu_suspend (void ) {/* disable IOMMUs to go out of the way for BIOS */ disable_iommus ();
@@ -1288,17 +1286,11 @@ static int amd_iommu_suspend(struct sys_return 0 ; } -static struct sysdev_class amd_iommu_sysdev_class = { - .name ="amd_iommu" , +static struct syscore_ops amd_iommu_syscore_ops = { .suspend = amd_iommu_suspend, .resume = amd_iommu_resume, }; -static struct sys_device device_amd_iommu = { - .id =0 , - .cls = &amd_iommu_sysdev_class, -}; -/* * This is the core init function for AMD IOMMU hardware in the system. * This function is called from the generic x86 DMA layer initialization
@@ -1415,14 +1407,6 @@ static int __init amd_iommu_init(void) goto free; } - ret =sysdev_class_register (&amd_iommu_sysdev_class); -if (ret) - goto free; - - ret =sysdev_register (&device_amd_iommu); -if (ret) - goto free; - ret =amd_iommu_init_devices ();if (ret) goto free;
@@ -1441,6 +1425,8 @@ static int __init amd_iommu_init(void)amd_iommu_init_notifier (); +register_syscore_ops (&amd_iommu_syscore_ops); +if (iommu_pass_through) goto out;
arch/x86/kernel/apic/apic.c +9 -24
@@ -24,7 +24,7 @@#include <linux/ftrace.h> #include <linux/ioport.h> #include <linux/module.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/delay.h> #include <linux/timex.h> #include <linux/dmar.h>
@@ -2046,7 +2046,7 @@ static struct {unsigned int apic_thmr; } apic_pm_state; -static int lapic_suspend (struct sys_device *dev,pm_message_t state) +static int lapic_suspend (void ) {unsigned long flags;int maxlvt;
@@ -2084,23 +2084,21 @@ static int lapic_suspend(struct sys_devireturn 0 ; } -static int lapic_resume (struct sys_device *dev) +static void lapic_resume (void ) {unsigned int l, h;unsigned long flags; -int maxlvt; -int ret =0 ; +int maxlvt, ret;struct IO_APIC_route_entry **ioapic_entries =NULL ;if (!apic_pm_state.active) -return 0 ; +return ;local_irq_save (flags);if (intr_remapping_enabled) { ioapic_entries =alloc_ioapic_entries ();if (!ioapic_entries) {WARN (1 ,"Alloc ioapic_entries in lapic resume failed." ); - ret = -ENOMEM ; goto restore; }
@@ -2162,8 +2160,6 @@ static int lapic_resume(struct sys_devic } restore:local_irq_restore (flags); - -return ret; }/*
@@ -2171,17 +2167,11 @@ restore:* are needed on every CPU up until machine_halt/restart/poweroff. */ -static struct sysdev_class lapic_sysclass = { - .name ="lapic" , +static struct syscore_ops lapic_syscore_ops = { .resume = lapic_resume, .suspend = lapic_suspend, }; -static struct sys_device device_lapic = { - .id =0 , - .cls = &lapic_sysclass, -}; -static void __cpuinit apic_pm_activate (void ) { apic_pm_state.active =1 ;
@@ -2189,16 +2179,11 @@ static void __cpuinit apic_pm_activate(vstatic int __init init_lapic_sysfs (void ) { -int error; - -if (!cpu_has_apic) -return 0 ;/* XXX: remove suspend/resume procs if !apic_pm_state.active? */ +if (cpu_has_apic) +register_syscore_ops (&lapic_syscore_ops); - error =sysdev_class_register (&lapic_sysclass); -if (!error) - error =sysdev_register (&device_lapic); -return error; +return 0 ; }/* local apic needs to resume before other devices access its registers. */
arch/x86/kernel/apic/io_apic.c +46 -51
142 lines not on this page · raw message
arch/x86/kernel/i8237.c +7 -23
@@ -10,7 +10,7 @@*/ #include <linux/init.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <asm/dma.h>
@@ -21,7 +21,7 @@* in asm/dma.h. */ -static int i8237A_resume (struct sys_device *dev) +static void i8237A_resume (void ) {unsigned long flags;int i;
@@ -41,31 +41,15 @@ static int i8237A_resume(struct sys_devienable_dma (4 );release_dma_lock (flags); - -return 0 ; } -static int i8237A_suspend (struct sys_device *dev,pm_message_t state) -{ -return 0 ; -} - -static struct sysdev_class i8237_sysdev_class = { - .name ="i8237" , - .suspend = i8237A_suspend, +static struct syscore_ops i8237_syscore_ops = { .resume = i8237A_resume, }; -static struct sys_device device_i8237A = { - .id =0 , - .cls = &i8237_sysdev_class, -}; - -static int __init i8237A_init_sysfs (void ) +static int __init i8237A_init_ops (void ) { -int error =sysdev_class_register (&i8237_sysdev_class); -if (!error) - error =sysdev_register (&device_i8237A); -return error; +register_syscore_ops (&i8237_syscore_ops); +return 0 ; } -device_initcall (i8237A_init_sysfs); +device_initcall (i8237A_init_ops);
arch/x86/kernel/i8259.c +10 -23
@@ -8,7 +8,7 @@#include <linux/random.h> #include <linux/init.h> #include <linux/kernel_stat.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/bitops.h> #include <linux/acpi.h> #include <linux/io.h>
@@ -245,20 +245,19 @@ static void save_ELCR(char *trigger) trigger[1 ] =inb (0x4d1 ) &0xDE ; } -static int i8259A_resume (struct sys_device *dev) +static void i8259A_resume (void ) {init_8259A (i8259A_auto_eoi);restore_ELCR (irq_trigger); -return 0 ; } -static int i8259A_suspend (struct sys_device *dev,pm_message_t state) +static int i8259A_suspend (void ) {save_ELCR (irq_trigger);return 0 ; } -static int i8259A_shutdown (struct sys_device *dev) +static void i8259A_shutdown (void ) {/* Put the i8259A into a quiescent state that * the kernel initialization code can get it
@@ -266,21 +265,14 @@ static int i8259A_shutdown(struct sys_de*/ outb (0xff ,PIC_MASTER_IMR );/* mask all of 8259A-1 */ outb (0xff ,PIC_SLAVE_IMR );/* mask all of 8259A-1 */ -return 0 ; } -static struct sysdev_class i8259_sysdev_class = { - .name ="i8259" , +static struct syscore_ops i8259_syscore_ops = { .suspend = i8259A_suspend, .resume = i8259A_resume, .shutdown = i8259A_shutdown, }; -static struct sys_device device_i8259A = { - .id =0 , - .cls = &i8259_sysdev_class, -}; -static void mask_8259A (void ) {unsigned long flags;
@@ -399,17 +391,12 @@ struct legacy_pic default_legacy_pic = {struct legacy_pic *legacy_pic = &default_legacy_pic; -static int __init i8259A_init_sysfs (void ) +static int __init i8259A_init_ops (void ) { -int error; - -if (legacy_pic != &default_legacy_pic) -return 0 ; +if (legacy_pic == &default_legacy_pic) +register_syscore_ops (&i8259_syscore_ops); - error =sysdev_class_register (&i8259_sysdev_class); -if (!error) - error =sysdev_register (&device_i8259A); -return error; +return 0 ; } -device_initcall (i8259A_init_sysfs); +device_initcall (i8259A_init_ops);
arch/x86/kernel/pci-gart_64.c +7 -25
@@ -27,7 +27,7 @@#include <linux/kdebug.h> #include <linux/scatterlist.h> #include <linux/iommu-helper.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/io.h> #include <linux/gfp.h> #include <asm/atomic.h>
@@ -589,7 +589,7 @@ void set_up_gart_resume(u32 aper_order, aperture_alloc = aper_alloc; } -static void gart_fixup_northbridges (struct sys_device *dev) +static void gart_fixup_northbridges (void ) {int i;
@@ -613,33 +613,20 @@ static void gart_fixup_northbridges(stru } } -static int gart_resume (struct sys_device *dev) +static void gart_resume (void ) {pr_info ("PCI-DMA: Resuming GART IOMMU\n" ); -gart_fixup_northbridges (dev); +gart_fixup_northbridges ();enable_gart_translations (); - -return 0 ; } -static int gart_suspend (struct sys_device *dev,pm_message_t state) -{ -return 0 ; -} - -static struct sysdev_class gart_sysdev_class = { - .name ="gart" , - .suspend = gart_suspend, +static struct syscore_ops gart_syscore_ops = { .resume = gart_resume, }; -static struct sys_device device_gart = { - .cls = &gart_sysdev_class, -}; -/* * Private Northbridge GATT initialization in case we cannot use the * AGP driver for some reason.
@@ -650,7 +637,7 @@ static __init int init_amd_gatt(struct aunsigned aper_base, new_aper_base;struct pci_dev *dev;void *gatt; -int i, error; +int i;pr_info ("PCI-DMA: Disabling AGP.\n" );
@@ -685,12 +672,7 @@ static __init int init_amd_gatt(struct a agp_gatt_table = gatt; - error =sysdev_class_register (&gart_sysdev_class); -if (!error) - error =sysdev_register (&device_gart); -if (error) -panic ("Could not register gart_sysdev -- " -"would corrupt data on next suspend" ); +register_syscore_ops (&gart_syscore_ops);flush_gart ();
arch/x86/oprofile/nmi_int.c +12 -32
89 lines not on this page · raw message
arch/x86/kernel/cpu/mcheck/mce.c +12 -9
@@ -21,6 +21,7 @@#include <linux/percpu.h> #include <linux/string.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/delay.h> #include <linux/ctype.h> #include <linux/sched.h>
@@ -1749,14 +1750,14 @@ static int mce_disable_error_reporting(vreturn 0 ; } -static int mce_suspend (struct sys_device *dev,pm_message_t state) +static int mce_suspend (void ) {return mce_disable_error_reporting (); } -static int mce_shutdown (struct sys_device *dev) +static void mce_shutdown (void ) { -return mce_disable_error_reporting (); +mce_disable_error_reporting (); }/*
@@ -1764,14 +1765,18 @@ static int mce_shutdown(struct sys_devic* Only one CPU is active at this time, the others get re-added later using * CPU hotplug: */ -static int mce_resume (struct sys_device *dev) +static void mce_resume (void ) {__mcheck_cpu_init_generic ();__mcheck_cpu_init_vendor (__this_cpu_ptr (&cpu_info)); - -return 0 ; } +static struct syscore_ops mce_syscore_ops = { + .suspend = mce_suspend, + .shutdown = mce_shutdown, + .resume = mce_resume, +}; +static void mce_cpu_restart (void *data) {del_timer_sync (&__get_cpu_var (mce_timer));
@@ -1808,9 +1813,6 @@ static void mce_enable_ce(void *all) }static struct sysdev_class mce_sysclass = { - .suspend = mce_suspend, - .shutdown = mce_shutdown, - .resume = mce_resume, .name ="machinecheck" , };
@@ -2139,6 +2141,7 @@ static __init int mcheck_init_device(voireturn err; } +register_syscore_ops (&mce_syscore_ops);register_hotcpu_notifier (&mce_cpu_notifier);misc_register (&mce_log_device);
arch/x86/kernel/cpu/mtrr/main.c +5 -5
@@ -45,6 +45,7 @@#include <linux/cpu.h> #include <linux/pci.h> #include <linux/smp.h> +#include <linux/syscore_ops.h> #include <asm/processor.h> #include <asm/e820.h>
@@ -630,7 +631,7 @@ struct mtrr_value {static struct mtrr_value mtrr_value[MTRR_MAX_VAR_RANGES ]; -static int mtrr_save (struct sys_device *sysdev,pm_message_t state) +static int mtrr_save (void ) {int i;
@@ -642,7 +643,7 @@ static int mtrr_save(struct sys_device *return 0 ; } -static int mtrr_restore (struct sys_device *sysdev) +static void mtrr_restore (void ) {int i;
@@ -653,12 +654,11 @@ static int mtrr_restore(struct sys_devic mtrr_value[i].ltype); } } -return 0 ; } -static struct sysdev_driver mtrr_sysdev_driver = { +static struct syscore_ops mtrr_syscore_ops = { .suspend = mtrr_save, .resume = mtrr_restore, };
@@ -839,7 +839,7 @@ static int __init mtrr_init_finialize(vo* TBD: is there any system with such CPU which supports * suspend/resume? If no, we should remove the code. */ -sysdev_driver_register (&cpu_sysdev_class, &mtrr_sysdev_driver); +register_syscore_ops (&mtrr_syscore_ops);return 0 ; }
arch/x86/kernel/microcode_core.c +14 -20
@@ -82,6 +82,7 @@#include <linux/cpu.h> #include <linux/fs.h> #include <linux/mm.h> +#include <linux/syscore_ops.h> #include <asm/microcode.h> #include <asm/processor.h>
@@ -438,33 +439,25 @@ static int mc_sysdev_remove(struct sys_dreturn 0 ; } -static int mc_sysdev_resume (struct sys_device *dev) +static struct sysdev_driver mc_sysdev_driver = { + .add = mc_sysdev_add, + .remove = mc_sysdev_remove, +}; + +/** +* mc_bp_resume - Update boot CPU microcode during resume. +*/ +static void mc_bp_resume (void ) { -int cpu = dev->id; +int cpu =smp_processor_id ();struct ucode_cpu_info *uci = ucode_cpu_info + cpu; -if (!cpu_online (cpu)) -return 0 ; - -/* -* All non-bootup cpus are still disabled, -* so only CPU 0 will apply ucode here. -* -* Moreover, there can be no concurrent -* updates from any other places at this point. -*/ -WARN_ON (cpu !=0 ); -if (uci->valid && uci->mc) microcode_ops->apply_microcode (cpu); - -return 0 ; } -static struct sysdev_driver mc_sysdev_driver = { - .add = mc_sysdev_add, - .remove = mc_sysdev_remove, - .resume = mc_sysdev_resume, +static struct syscore_ops mc_syscore_ops = { + .resume = mc_bp_resume, }; static __cpuinit int
@@ -542,6 +535,7 @@ static int __init microcode_init(void)if (error)return error; +register_syscore_ops (&mc_syscore_ops);register_hotcpu_notifier (&mc_cpu_notifier); pr_info("Microcode Update Driver: v" MICROCODE_VERSION
PATCH 1/6 x86: Use syscore_ops instead of sysdev classes and sysdevs
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
Some subsystems in the x86 tree need to carry out suspend/resume and shutdown operations with one CPU on-line and interrupts disabled and they define sysdev classes and sysdevs or sysdev drivers for this purpose. This leads to unnecessarily complicated code and excessive memory usage, so switch them to using struct syscore_ops objects for this purpose instead.
Generally, there are three categories of subsystems that use sysdevs for implementing PM operations: (1) subsystems whose suspend/resume callbacks ignore their arguments entirely (the majority), (2) subsystems whose suspend/resume callbacks use their struct sys_device argument, but don't really need to do that, because they can be implemented differently in an arguably simpler way (io_apic.c), and (3) subsystems whose suspend/resume callbacks use their struct sys_device argument, but the value of that argument is always the same and could be ignored (microcode_core.c). In all of these cases the subsystems in question may be readily converted to using struct syscore_ops objects for power management and shutdown.
--- arch/x86/kernel/amd_iommu_init.c | 26 ++-------- arch/x86/kernel/apic/apic.c | 33 +++---------- arch/x86/kernel/apic/io_apic.c | 97 ++++++++++++++++++--------------------- arch/x86/kernel/cpu/mcheck/mce.c | 21 ++++---- arch/x86/kernel/cpu/mtrr/main.c | 10 ++-- arch/x86/kernel/i8237.c | 30 ++---------- arch/x86/kernel/i8259.c | 33 ++++--------- arch/x86/kernel/microcode_core.c | 34 +++++-------- arch/x86/kernel/pci-gart_64.c | 32 ++---------- arch/x86/oprofile/nmi_int.c | 44 ++++------------- 10 files changed, 128 insertions(+), 232 deletions(-)
arch/x86/kernel/amd_iommu_init.c +6 -20
@@ -21,7 +21,7 @@#include <linux/acpi.h> #include <linux/list.h> #include <linux/slab.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/interrupt.h> #include <linux/msi.h> #include <asm/pci-direct.h>
@@ -1260,7 +1260,7 @@ static void disable_iommus(void)* disable suspend until real resume implemented */ -static int amd_iommu_resume (struct sys_device *dev) +static void amd_iommu_resume (void ) {struct amd_iommu *iommu;
@@ -1276,11 +1276,9 @@ static int amd_iommu_resume(struct sys_d*/ amd_iommu_flush_all_devices ();amd_iommu_flush_all_domains (); - -return 0 ; } -static int amd_iommu_suspend (struct sys_device *dev,pm_message_t state) +static int amd_iommu_suspend (void ) {/* disable IOMMUs to go out of the way for BIOS */ disable_iommus ();
@@ -1288,17 +1286,11 @@ static int amd_iommu_suspend(struct sys_return 0 ; } -static struct sysdev_class amd_iommu_sysdev_class = { - .name ="amd_iommu" , +static struct syscore_ops amd_iommu_syscore_ops = { .suspend = amd_iommu_suspend, .resume = amd_iommu_resume, }; -static struct sys_device device_amd_iommu = { - .id =0 , - .cls = &amd_iommu_sysdev_class, -}; -/* * This is the core init function for AMD IOMMU hardware in the system. * This function is called from the generic x86 DMA layer initialization
@@ -1415,14 +1407,6 @@ static int __init amd_iommu_init(void) goto free; } - ret =sysdev_class_register (&amd_iommu_sysdev_class); -if (ret) - goto free; - - ret =sysdev_register (&device_amd_iommu); -if (ret) - goto free; - ret =amd_iommu_init_devices ();if (ret) goto free;
@@ -1441,6 +1425,8 @@ static int __init amd_iommu_init(void)amd_iommu_init_notifier (); +register_syscore_ops (&amd_iommu_syscore_ops); +if (iommu_pass_through) goto out;
arch/x86/kernel/apic/apic.c +9 -24
@@ -24,7 +24,7 @@#include <linux/ftrace.h> #include <linux/ioport.h> #include <linux/module.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/delay.h> #include <linux/timex.h> #include <linux/dmar.h>
@@ -2046,7 +2046,7 @@ static struct {unsigned int apic_thmr; } apic_pm_state; -static int lapic_suspend (struct sys_device *dev,pm_message_t state) +static int lapic_suspend (void ) {unsigned long flags;int maxlvt;
@@ -2084,23 +2084,21 @@ static int lapic_suspend(struct sys_devireturn 0 ; } -static int lapic_resume (struct sys_device *dev) +static void lapic_resume (void ) {unsigned int l, h;unsigned long flags; -int maxlvt; -int ret =0 ; +int maxlvt, ret;struct IO_APIC_route_entry **ioapic_entries =NULL ;if (!apic_pm_state.active) -return 0 ; +return ;local_irq_save (flags);if (intr_remapping_enabled) { ioapic_entries =alloc_ioapic_entries ();if (!ioapic_entries) {WARN (1 ,"Alloc ioapic_entries in lapic resume failed." ); - ret = -ENOMEM ; goto restore; }
@@ -2162,8 +2160,6 @@ static int lapic_resume(struct sys_devic } restore:local_irq_restore (flags); - -return ret; }/*
@@ -2171,17 +2167,11 @@ restore:* are needed on every CPU up until machine_halt/restart/poweroff. */ -static struct sysdev_class lapic_sysclass = { - .name ="lapic" , +static struct syscore_ops lapic_syscore_ops = { .resume = lapic_resume, .suspend = lapic_suspend, }; -static struct sys_device device_lapic = { - .id =0 , - .cls = &lapic_sysclass, -}; -static void __cpuinit apic_pm_activate (void ) { apic_pm_state.active =1 ;
@@ -2189,16 +2179,11 @@ static void __cpuinit apic_pm_activate(vstatic int __init init_lapic_sysfs (void ) { -int error; - -if (!cpu_has_apic) -return 0 ;/* XXX: remove suspend/resume procs if !apic_pm_state.active? */ +if (cpu_has_apic) +register_syscore_ops (&lapic_syscore_ops); - error =sysdev_class_register (&lapic_sysclass); -if (!error) - error =sysdev_register (&device_lapic); -return error; +return 0 ; }/* local apic needs to resume before other devices access its registers. */
arch/x86/kernel/apic/io_apic.c +46 -51
142 lines not on this page · raw message
arch/x86/kernel/i8237.c +7 -23
@@ -10,7 +10,7 @@*/ #include <linux/init.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <asm/dma.h>
@@ -21,7 +21,7 @@* in asm/dma.h. */ -static int i8237A_resume (struct sys_device *dev) +static void i8237A_resume (void ) {unsigned long flags;int i;
@@ -41,31 +41,15 @@ static int i8237A_resume(struct sys_devienable_dma (4 );release_dma_lock (flags); - -return 0 ; } -static int i8237A_suspend (struct sys_device *dev,pm_message_t state) -{ -return 0 ; -} - -static struct sysdev_class i8237_sysdev_class = { - .name ="i8237" , - .suspend = i8237A_suspend, +static struct syscore_ops i8237_syscore_ops = { .resume = i8237A_resume, }; -static struct sys_device device_i8237A = { - .id =0 , - .cls = &i8237_sysdev_class, -}; - -static int __init i8237A_init_sysfs (void ) +static int __init i8237A_init_ops (void ) { -int error =sysdev_class_register (&i8237_sysdev_class); -if (!error) - error =sysdev_register (&device_i8237A); -return error; +register_syscore_ops (&i8237_syscore_ops); +return 0 ; } -device_initcall (i8237A_init_sysfs); +device_initcall (i8237A_init_ops);
arch/x86/kernel/i8259.c +10 -23
@@ -8,7 +8,7 @@#include <linux/random.h> #include <linux/init.h> #include <linux/kernel_stat.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/bitops.h> #include <linux/acpi.h> #include <linux/io.h>
@@ -245,20 +245,19 @@ static void save_ELCR(char *trigger) trigger[1 ] =inb (0x4d1 ) &0xDE ; } -static int i8259A_resume (struct sys_device *dev) +static void i8259A_resume (void ) {init_8259A (i8259A_auto_eoi);restore_ELCR (irq_trigger); -return 0 ; } -static int i8259A_suspend (struct sys_device *dev,pm_message_t state) +static int i8259A_suspend (void ) {save_ELCR (irq_trigger);return 0 ; } -static int i8259A_shutdown (struct sys_device *dev) +static void i8259A_shutdown (void ) {/* Put the i8259A into a quiescent state that * the kernel initialization code can get it
@@ -266,21 +265,14 @@ static int i8259A_shutdown(struct sys_de*/ outb (0xff ,PIC_MASTER_IMR );/* mask all of 8259A-1 */ outb (0xff ,PIC_SLAVE_IMR );/* mask all of 8259A-1 */ -return 0 ; } -static struct sysdev_class i8259_sysdev_class = { - .name ="i8259" , +static struct syscore_ops i8259_syscore_ops = { .suspend = i8259A_suspend, .resume = i8259A_resume, .shutdown = i8259A_shutdown, }; -static struct sys_device device_i8259A = { - .id =0 , - .cls = &i8259_sysdev_class, -}; -static void mask_8259A (void ) {unsigned long flags;
@@ -399,17 +391,12 @@ struct legacy_pic default_legacy_pic = {struct legacy_pic *legacy_pic = &default_legacy_pic; -static int __init i8259A_init_sysfs (void ) +static int __init i8259A_init_ops (void ) { -int error; - -if (legacy_pic != &default_legacy_pic) -return 0 ; +if (legacy_pic == &default_legacy_pic) +register_syscore_ops (&i8259_syscore_ops); - error =sysdev_class_register (&i8259_sysdev_class); -if (!error) - error =sysdev_register (&device_i8259A); -return error; +return 0 ; } -device_initcall (i8259A_init_sysfs); +device_initcall (i8259A_init_ops);
arch/x86/kernel/pci-gart_64.c +7 -25
@@ -27,7 +27,7 @@#include <linux/kdebug.h> #include <linux/scatterlist.h> #include <linux/iommu-helper.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/io.h> #include <linux/gfp.h> #include <asm/atomic.h>
@@ -589,7 +589,7 @@ void set_up_gart_resume(u32 aper_order, aperture_alloc = aper_alloc; } -static void gart_fixup_northbridges (struct sys_device *dev) +static void gart_fixup_northbridges (void ) {int i;
@@ -613,33 +613,20 @@ static void gart_fixup_northbridges(stru } } -static int gart_resume (struct sys_device *dev) +static void gart_resume (void ) {pr_info ("PCI-DMA: Resuming GART IOMMU\n" ); -gart_fixup_northbridges (dev); +gart_fixup_northbridges ();enable_gart_translations (); - -return 0 ; } -static int gart_suspend (struct sys_device *dev,pm_message_t state) -{ -return 0 ; -} - -static struct sysdev_class gart_sysdev_class = { - .name ="gart" , - .suspend = gart_suspend, +static struct syscore_ops gart_syscore_ops = { .resume = gart_resume, }; -static struct sys_device device_gart = { - .cls = &gart_sysdev_class, -}; -/* * Private Northbridge GATT initialization in case we cannot use the * AGP driver for some reason.
@@ -650,7 +637,7 @@ static __init int init_amd_gatt(struct aunsigned aper_base, new_aper_base;struct pci_dev *dev;void *gatt; -int i, error; +int i;pr_info ("PCI-DMA: Disabling AGP.\n" );
@@ -685,12 +672,7 @@ static __init int init_amd_gatt(struct a agp_gatt_table = gatt; - error =sysdev_class_register (&gart_sysdev_class); -if (!error) - error =sysdev_register (&device_gart); -if (error) -panic ("Could not register gart_sysdev -- " -"would corrupt data on next suspend" ); +register_syscore_ops (&gart_syscore_ops);flush_gart ();
arch/x86/oprofile/nmi_int.c +12 -32
89 lines not on this page · raw message
arch/x86/kernel/cpu/mcheck/mce.c +12 -9
@@ -21,6 +21,7 @@#include <linux/percpu.h> #include <linux/string.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/delay.h> #include <linux/ctype.h> #include <linux/sched.h>
@@ -1749,14 +1750,14 @@ static int mce_disable_error_reporting(vreturn 0 ; } -static int mce_suspend (struct sys_device *dev,pm_message_t state) +static int mce_suspend (void ) {return mce_disable_error_reporting (); } -static int mce_shutdown (struct sys_device *dev) +static void mce_shutdown (void ) { -return mce_disable_error_reporting (); +mce_disable_error_reporting (); }/*
@@ -1764,14 +1765,18 @@ static int mce_shutdown(struct sys_devic* Only one CPU is active at this time, the others get re-added later using * CPU hotplug: */ -static int mce_resume (struct sys_device *dev) +static void mce_resume (void ) {__mcheck_cpu_init_generic ();__mcheck_cpu_init_vendor (__this_cpu_ptr (&cpu_info)); - -return 0 ; } +static struct syscore_ops mce_syscore_ops = { + .suspend = mce_suspend, + .shutdown = mce_shutdown, + .resume = mce_resume, +}; +static void mce_cpu_restart (void *data) {del_timer_sync (&__get_cpu_var (mce_timer));
@@ -1808,9 +1813,6 @@ static void mce_enable_ce(void *all) }static struct sysdev_class mce_sysclass = { - .suspend = mce_suspend, - .shutdown = mce_shutdown, - .resume = mce_resume, .name ="machinecheck" , };
@@ -2139,6 +2141,7 @@ static __init int mcheck_init_device(voireturn err; } +register_syscore_ops (&mce_syscore_ops);register_hotcpu_notifier (&mce_cpu_notifier);misc_register (&mce_log_device);
arch/x86/kernel/cpu/mtrr/main.c +5 -5
@@ -45,6 +45,7 @@#include <linux/cpu.h> #include <linux/pci.h> #include <linux/smp.h> +#include <linux/syscore_ops.h> #include <asm/processor.h> #include <asm/e820.h>
@@ -630,7 +631,7 @@ struct mtrr_value {static struct mtrr_value mtrr_value[MTRR_MAX_VAR_RANGES ]; -static int mtrr_save (struct sys_device *sysdev,pm_message_t state) +static int mtrr_save (void ) {int i;
@@ -642,7 +643,7 @@ static int mtrr_save(struct sys_device *return 0 ; } -static int mtrr_restore (struct sys_device *sysdev) +static void mtrr_restore (void ) {int i;
@@ -653,12 +654,11 @@ static int mtrr_restore(struct sys_devic mtrr_value[i].ltype); } } -return 0 ; } -static struct sysdev_driver mtrr_sysdev_driver = { +static struct syscore_ops mtrr_syscore_ops = { .suspend = mtrr_save, .resume = mtrr_restore, };
@@ -839,7 +839,7 @@ static int __init mtrr_init_finialize(vo* TBD: is there any system with such CPU which supports * suspend/resume? If no, we should remove the code. */ -sysdev_driver_register (&cpu_sysdev_class, &mtrr_sysdev_driver); +register_syscore_ops (&mtrr_syscore_ops);return 0 ; }
arch/x86/kernel/microcode_core.c +14 -20
@@ -82,6 +82,7 @@#include <linux/cpu.h> #include <linux/fs.h> #include <linux/mm.h> +#include <linux/syscore_ops.h> #include <asm/microcode.h> #include <asm/processor.h>
@@ -438,33 +439,25 @@ static int mc_sysdev_remove(struct sys_dreturn 0 ; } -static int mc_sysdev_resume (struct sys_device *dev) +static struct sysdev_driver mc_sysdev_driver = { + .add = mc_sysdev_add, + .remove = mc_sysdev_remove, +}; + +/** +* mc_bp_resume - Update boot CPU microcode during resume. +*/ +static void mc_bp_resume (void ) { -int cpu = dev->id; +int cpu =smp_processor_id ();struct ucode_cpu_info *uci = ucode_cpu_info + cpu; -if (!cpu_online (cpu)) -return 0 ; - -/* -* All non-bootup cpus are still disabled, -* so only CPU 0 will apply ucode here. -* -* Moreover, there can be no concurrent -* updates from any other places at this point. -*/ -WARN_ON (cpu !=0 ); -if (uci->valid && uci->mc) microcode_ops->apply_microcode (cpu); - -return 0 ; } -static struct sysdev_driver mc_sysdev_driver = { - .add = mc_sysdev_add, - .remove = mc_sysdev_remove, - .resume = mc_sysdev_resume, +static struct syscore_ops mc_syscore_ops = { + .resume = mc_bp_resume, }; static __cpuinit int
@@ -542,6 +535,7 @@ static int __init microcode_init(void)if (error)return error; +register_syscore_ops (&mc_syscore_ops);register_hotcpu_notifier (&mc_cpu_notifier); pr_info("Microcode Update Driver: v" MICROCODE_VERSION
PATCH 2/6 timekeeping: Use syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
The timekeeping subsystem uses a sysdev class and a sysdev for executing timekeeping_suspend() after interrupts have been turned off on the boot CPU (during system suspend) and for executing timekeeping_resume() before turning on interrupts on the boot CPU (during system resume). However, since both of these functions ignore their arguments, the entire mechanism may be replaced with a struct syscore_ops object which is simpler.
--- kernel/time/timekeeping.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-)
kernel/time/timekeeping.c +8 -19
@@ -14,7 +14,7 @@#include <linux/init.h> #include <linux/mm.h> #include <linux/sched.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/clocksource.h> #include <linux/jiffies.h> #include <linux/time.h>
@@ -597,13 +597,12 @@ static struct timespec timekeeping_suspe/** * timekeeping_resume - Resumes the generic timekeeping subsystem. -* @dev: unused * * This is for the generic clocksource timekeeping. * xtime/wall_to_monotonic/jiffies/etc are * still managed by arch specific suspend/resume code. */ -static int timekeeping_resume (struct sys_device *dev) +static void timekeeping_resume (void ) {unsigned long flags;struct timespec ts;
@@ -632,11 +631,9 @@ static int timekeeping_resume(struct sys/* Resume hrtimers */ hres_timers_resume (); - -return 0 ; } -static int timekeeping_suspend (struct sys_device *dev,pm_message_t state) +static int timekeeping_suspend (void ) {unsigned long flags;
@@ -654,26 +651,18 @@ static int timekeeping_suspend(struct sy }/* sysfs resume/suspend bits for timekeeping */ -static struct sysdev_class timekeeping_sysclass = { - .name ="timekeeping" , +static struct syscore_ops timekeeping_syscore_ops = { .resume = timekeeping_resume, .suspend = timekeeping_suspend, }; -static struct sys_device device_timer = { - .id =0 , - .cls = &timekeeping_sysclass, -}; - -static int __init timekeeping_init_device (void ) +static int __init timekeeping_init_ops (void ) { -int error =sysdev_class_register (&timekeeping_sysclass); -if (!error) - error =sysdev_register (&device_timer); -return error; +register_syscore_ops (&timekeeping_syscore_ops); +return 0 ; } -device_initcall (timekeeping_init_device); +device_initcall (timekeeping_init_ops);/* * If the error is already larger, we look ahead even further
PATCH 2/6 timekeeping: Use syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
The timekeeping subsystem uses a sysdev class and a sysdev for executing timekeeping_suspend() after interrupts have been turned off on the boot CPU (during system suspend) and for executing timekeeping_resume() before turning on interrupts on the boot CPU (during system resume). However, since both of these functions ignore their arguments, the entire mechanism may be replaced with a struct syscore_ops object which is simpler.
--- kernel/time/timekeeping.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-)
kernel/time/timekeeping.c +8 -19
@@ -14,7 +14,7 @@#include <linux/init.h> #include <linux/mm.h> #include <linux/sched.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/clocksource.h> #include <linux/jiffies.h> #include <linux/time.h>
@@ -597,13 +597,12 @@ static struct timespec timekeeping_suspe/** * timekeeping_resume - Resumes the generic timekeeping subsystem. -* @dev: unused * * This is for the generic clocksource timekeeping. * xtime/wall_to_monotonic/jiffies/etc are * still managed by arch specific suspend/resume code. */ -static int timekeeping_resume (struct sys_device *dev) +static void timekeeping_resume (void ) {unsigned long flags;struct timespec ts;
@@ -632,11 +631,9 @@ static int timekeeping_resume(struct sys/* Resume hrtimers */ hres_timers_resume (); - -return 0 ; } -static int timekeeping_suspend (struct sys_device *dev,pm_message_t state) +static int timekeeping_suspend (void ) {unsigned long flags;
@@ -654,26 +651,18 @@ static int timekeeping_suspend(struct sy }/* sysfs resume/suspend bits for timekeeping */ -static struct sysdev_class timekeeping_sysclass = { - .name ="timekeeping" , +static struct syscore_ops timekeeping_syscore_ops = { .resume = timekeeping_resume, .suspend = timekeeping_suspend, }; -static struct sys_device device_timer = { - .id =0 , - .cls = &timekeeping_sysclass, -}; - -static int __init timekeeping_init_device (void ) +static int __init timekeeping_init_ops (void ) { -int error =sysdev_class_register (&timekeeping_sysclass); -if (!error) - error =sysdev_register (&device_timer); -return error; +register_syscore_ops (&timekeeping_syscore_ops); +return 0 ; } -device_initcall (timekeeping_init_device); +device_initcall (timekeeping_init_ops);/* * If the error is already larger, we look ahead even further
PATCH 3/6 PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
The Intel IOMMU subsystem uses a sysdev class and a sysdev for executing iommu_suspend() after interrupts have been turned off on the boot CPU (during system suspend) and for executing iommu_resume() before turning on interrupts on the boot CPU (during system resume). However, since both of these functions ignore their arguments, the entire mechanism may be replaced with a struct syscore_ops object which is simpler.
--- drivers/pci/intel-iommu.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-)
drivers/pci/intel-iommu.c +9 -29
@@ -36,7 +36,7 @@#include <linux/iova.h> #include <linux/iommu.h> #include <linux/intel-iommu.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/tboot.h> #include <linux/dmi.h> #include <asm/cacheflush.h>
@@ -3135,7 +3135,7 @@ static void iommu_flush_all(void) } } -static int iommu_suspend (struct sys_device *dev,pm_message_t state) +static int iommu_suspend (void ) {struct dmar_drhd_unit *drhd;struct intel_iommu *iommu =NULL ;
@@ -3175,7 +3175,7 @@ nomem:return -ENOMEM ; } -static int iommu_resume (struct sys_device *dev) +static void iommu_resume (void ) {struct dmar_drhd_unit *drhd;struct intel_iommu *iommu =NULL ;
@@ -3183,7 +3183,7 @@ static int iommu_resume(struct sys_devicif (init_iommu_hw ()) {WARN (1 ,"IOMMU setup failed, DMAR can not resume!\n" ); -return -EIO ; +return ; }for_each_active_iommu (iommu, drhd) {
@@ -3204,40 +3204,20 @@ static int iommu_resume(struct sys_devicfor_each_active_iommu (iommu, drhd) kfree(iommu->iommu_state); - - return 0; } -static struct sysdev_class iommu_sysclass = { - .name ="iommu" , +static struct syscore_ops iommu_syscore_ops = { .resume = iommu_resume, .suspend = iommu_suspend, }; -static struct sys_device device_iommu = { - .cls = &iommu_sysclass, -}; - -static int __init init_iommu_sysfs (void ) +static void __init init_iommu_pm_ops (void ) { -int error; - - error =sysdev_class_register (&iommu_sysclass); -if (error) -return error; - - error =sysdev_register (&device_iommu); -if (error) -sysdev_class_unregister (&iommu_sysclass); - -return error; +register_syscore_ops (&iommu_syscore_ops); }#else -static int __init init_iommu_sysfs (void ) -{ -return 0 ; -} +static inline int init_iommu_pm_ops (void ) { }#endif /* CONFIG_PM */ /*
@@ -3320,7 +3300,7 @@ int __init intel_iommu_init(void)#endif dma_ops = &intel_dma_ops; -init_iommu_sysfs (); +init_iommu_pm_ops ();register_iommu (&intel_iommu_ops);
Re: [PATCH 3/6] PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
Quoted 2 lines · Rafael J. Wysocki
drivers/pci/intel-iommu.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-)
Looks good. I prepare a patch to convert AMD IOMMU to syscore_ops too.
Joerg
Signature · 5 lines
AMD Operating System Research Center Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach General Managers: Alberto Bozzo, Andrew Bowd Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632
Re: [PATCH 3/6] PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
Quoted 5 lines · Joerg Roedel
Quoted 2 lines · Rafael J. Wysocki
drivers/pci/intel-iommu.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-)Looks good.
May I take that as an ACK?
Quoted 1 line
I prepare a patch to convert AMD IOMMU to
syscore_opstoo.
Already done. :-)
It's a part of patch [1/6].
Thanks,
Rafael
Re: [PATCH 3/6] PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
Quoted 8 lines · Rafael J. Wysocki
Quoted 5 lines · Joerg Roedel
Quoted 2 lines · Rafael J. Wysocki
drivers/pci/intel-iommu.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-)Looks good.
May I take that as an ACK?
Sure :-)
Quoted 5 lines
Quoted 1 line
I prepare a patch to convert AMD IOMMU to
syscore_opstoo.Already done. :-)
It's a part of patch [1/6].
I see, saves me work, thanks :-)
Joerg
Signature · 5 lines
AMD Operating System Research Center Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach General Managers: Alberto Bozzo, Andrew Bowd Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632
Re: [PATCH 3/6] PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiQuoted 8 lines · Rafael J. Wysocki
Quoted 5 lines · Joerg Roedel
Quoted 2 lines · Rafael J. Wysocki
drivers/pci/intel-iommu.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-)Looks good.
May I take that as an ACK?
Sure :-)
Quoted 5 lines
Quoted 1 line
I prepare a patch to convert AMD IOMMU to
syscore_opstoo.Already done. :-)
It's a part of patch [1/6].
I see, saves me work, thanks :-)
Joerg
Signature · 5 lines
AMD Operating System Research Center Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach General Managers: Alberto Bozzo, Andrew Bowd Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632
Re: [PATCH 3/6] PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
In reply to Joerg RoedelQuoted 5 lines · Joerg Roedel
Quoted 2 lines · Rafael J. Wysocki
drivers/pci/intel-iommu.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-)Looks good.
May I take that as an ACK?
Quoted 1 line
I prepare a patch to convert AMD IOMMU to
syscore_opstoo.
Already done. :-)
It's a part of patch [1/6].
Thanks,
Rafael
Re: [PATCH 3/6] PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiQuoted 2 lines · Rafael J. Wysocki
drivers/pci/intel-iommu.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-)
Looks good. I prepare a patch to convert AMD IOMMU to syscore_ops too.
Joerg
Signature · 5 lines
AMD Operating System Research Center Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach General Managers: Alberto Bozzo, Andrew Bowd Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632
PATCH 3/6 PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
The Intel IOMMU subsystem uses a sysdev class and a sysdev for executing iommu_suspend() after interrupts have been turned off on the boot CPU (during system suspend) and for executing iommu_resume() before turning on interrupts on the boot CPU (during system resume). However, since both of these functions ignore their arguments, the entire mechanism may be replaced with a struct syscore_ops object which is simpler.
--- drivers/pci/intel-iommu.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-)
drivers/pci/intel-iommu.c +9 -29
@@ -36,7 +36,7 @@#include <linux/iova.h> #include <linux/iommu.h> #include <linux/intel-iommu.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/tboot.h> #include <linux/dmi.h> #include <asm/cacheflush.h>
@@ -3135,7 +3135,7 @@ static void iommu_flush_all(void) } } -static int iommu_suspend (struct sys_device *dev,pm_message_t state) +static int iommu_suspend (void ) {struct dmar_drhd_unit *drhd;struct intel_iommu *iommu =NULL ;
@@ -3175,7 +3175,7 @@ nomem:return -ENOMEM ; } -static int iommu_resume (struct sys_device *dev) +static void iommu_resume (void ) {struct dmar_drhd_unit *drhd;struct intel_iommu *iommu =NULL ;
@@ -3183,7 +3183,7 @@ static int iommu_resume(struct sys_devicif (init_iommu_hw ()) {WARN (1 ,"IOMMU setup failed, DMAR can not resume!\n" ); -return -EIO ; +return ; }for_each_active_iommu (iommu, drhd) {
@@ -3204,40 +3204,20 @@ static int iommu_resume(struct sys_devicfor_each_active_iommu (iommu, drhd) kfree(iommu->iommu_state); - - return 0; } -static struct sysdev_class iommu_sysclass = { - .name ="iommu" , +static struct syscore_ops iommu_syscore_ops = { .resume = iommu_resume, .suspend = iommu_suspend, }; -static struct sys_device device_iommu = { - .cls = &iommu_sysclass, -}; - -static int __init init_iommu_sysfs (void ) +static void __init init_iommu_pm_ops (void ) { -int error; - - error =sysdev_class_register (&iommu_sysclass); -if (error) -return error; - - error =sysdev_register (&device_iommu); -if (error) -sysdev_class_unregister (&iommu_sysclass); - -return error; +register_syscore_ops (&iommu_syscore_ops); }#else -static int __init init_iommu_sysfs (void ) -{ -return 0 ; -} +static inline int init_iommu_pm_ops (void ) { }#endif /* CONFIG_PM */ /*
@@ -3320,7 +3300,7 @@ int __init intel_iommu_init(void)#endif dma_ops = &intel_dma_ops; -init_iommu_sysfs (); +init_iommu_pm_ops ();register_iommu (&intel_iommu_ops);
PATCH 4/6 KVM: Use syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
KVM uses a sysdev class and a sysdev for executing kvm_suspend() after interrupts have been turned off on the boot CPU (during system suspend) and for executing kvm_resume() before turning on interrupts on the boot CPU (during system resume). However, since both of these functions ignore their arguments, the entire mechanism may be replaced with a struct syscore_ops object which is simpler.
--- virt/kvm/kvm_main.c | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-)
virt/kvm/kvm_main.c +8 -26
@@ -30,7 +30,7 @@#include <linux/debugfs.h> #include <linux/highmem.h> #include <linux/file.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/cpu.h> #include <linux/sched.h> #include <linux/cpumask.h>
@@ -2447,33 +2447,26 @@ static void kvm_exit_debug(void)debugfs_remove (kvm_debugfs_dir); } -static int kvm_suspend (struct sys_device *dev,pm_message_t state) +static int kvm_suspend (void ) {if (kvm_usage_count)hardware_disable_nolock (NULL );return 0 ; } -static int kvm_resume (struct sys_device *dev) +static void kvm_resume (void ) {if (kvm_usage_count) {WARN_ON (raw_spin_is_locked (&kvm_lock));hardware_enable_nolock (NULL ); } -return 0 ; } -static struct sysdev_class kvm_sysdev_class = { - .name ="kvm" , +static struct syscore_ops kvm_syscore_ops = { .suspend = kvm_suspend, .resume = kvm_resume, }; -static struct sys_device kvm_sysdev = { - .id =0 , - .cls = &kvm_sysdev_class, -}; -struct page *bad_page;pfn_t bad_pfn;
@@ -2557,14 +2550,6 @@ int kvm_init(void *opaque, unsigned vcpu goto out_free_2;register_reboot_notifier (&kvm_reboot_notifier); - r =sysdev_class_register (&kvm_sysdev_class); -if (r) - goto out_free_3; - - r =sysdev_register (&kvm_sysdev); -if (r) - goto out_free_4; -/* A kmem cache lets us meet the alignment requirements of fx_save. */ if (!vcpu_align) vcpu_align = __alignof__(struct kvm_vcpu );
@@ -2572,7 +2557,7 @@ int kvm_init(void *opaque, unsigned vcpu 0, NULL);if (!kvm_vcpu_cache) { r = -ENOMEM ; - goto out_free_5; + goto out_free_3; } r =kvm_async_pf_init ();
@@ -2589,6 +2574,8 @@ int kvm_init(void *opaque, unsigned vcpu goto out_unreg; } +register_syscore_ops (&kvm_syscore_ops); + kvm_preempt_ops.sched_in = kvm_sched_in; kvm_preempt_ops.sched_out = kvm_sched_out;
@@ -2600,10 +2587,6 @@ out_unreg:kvm_async_pf_deinit (); out_free:kmem_cache_destroy (kvm_vcpu_cache); -out_free_5: -sysdev_unregister (&kvm_sysdev); -out_free_4: -sysdev_class_unregister (&kvm_sysdev_class); out_free_3:unregister_reboot_notifier (&kvm_reboot_notifier);unregister_cpu_notifier (&kvm_cpu_notifier);
@@ -2631,8 +2614,7 @@ void kvm_exit(void)misc_deregister (&kvm_dev);kmem_cache_destroy (kvm_vcpu_cache);kvm_async_pf_deinit (); -sysdev_unregister (&kvm_sysdev); -sysdev_class_unregister (&kvm_sysdev_class); +unregister_syscore_ops (&kvm_syscore_ops);unregister_reboot_notifier (&kvm_reboot_notifier);unregister_cpu_notifier (&kvm_cpu_notifier);on_each_cpu (hardware_disable_nolock,NULL ,1 );
Re: [PATCH 4/6] KVM: Use syscore_ops instead of sysdev class and sysdev
Quoted 9 lines · Rafael J. Wysocki
From: Rafael J. Wysocki<[email protected]>
KVM uses a sysdev class and a sysdev for executing
kvm_suspend()after interrupts have been turned off on the boot CPU (during system suspend) and for executingkvm_resume()before turning on interrupts on the boot CPU (during system resume). However, since both of these functions ignore their arguments, the entire mechanism may be replaced with a structsyscore_opsobject which is simpler.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH 4/6] KVM: Use syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiQuoted 9 lines · Rafael J. Wysocki
From: Rafael J. Wysocki<[email protected]>
KVM uses a sysdev class and a sysdev for executing
kvm_suspend()after interrupts have been turned off on the boot CPU (during system suspend) and for executingkvm_resume()before turning on interrupts on the boot CPU (during system resume). However, since both of these functions ignore their arguments, the entire mechanism may be replaced with a structsyscore_opsobject which is simpler.
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH 4/6 KVM: Use syscore_ops instead of sysdev class and sysdev
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
KVM uses a sysdev class and a sysdev for executing kvm_suspend() after interrupts have been turned off on the boot CPU (during system suspend) and for executing kvm_resume() before turning on interrupts on the boot CPU (during system resume). However, since both of these functions ignore their arguments, the entire mechanism may be replaced with a struct syscore_ops object which is simpler.
--- virt/kvm/kvm_main.c | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-)
virt/kvm/kvm_main.c +8 -26
@@ -30,7 +30,7 @@#include <linux/debugfs.h> #include <linux/highmem.h> #include <linux/file.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/cpu.h> #include <linux/sched.h> #include <linux/cpumask.h>
@@ -2447,33 +2447,26 @@ static void kvm_exit_debug(void)debugfs_remove (kvm_debugfs_dir); } -static int kvm_suspend (struct sys_device *dev,pm_message_t state) +static int kvm_suspend (void ) {if (kvm_usage_count)hardware_disable_nolock (NULL );return 0 ; } -static int kvm_resume (struct sys_device *dev) +static void kvm_resume (void ) {if (kvm_usage_count) {WARN_ON (raw_spin_is_locked (&kvm_lock));hardware_enable_nolock (NULL ); } -return 0 ; } -static struct sysdev_class kvm_sysdev_class = { - .name ="kvm" , +static struct syscore_ops kvm_syscore_ops = { .suspend = kvm_suspend, .resume = kvm_resume, }; -static struct sys_device kvm_sysdev = { - .id =0 , - .cls = &kvm_sysdev_class, -}; -struct page *bad_page;pfn_t bad_pfn;
@@ -2557,14 +2550,6 @@ int kvm_init(void *opaque, unsigned vcpu goto out_free_2;register_reboot_notifier (&kvm_reboot_notifier); - r =sysdev_class_register (&kvm_sysdev_class); -if (r) - goto out_free_3; - - r =sysdev_register (&kvm_sysdev); -if (r) - goto out_free_4; -/* A kmem cache lets us meet the alignment requirements of fx_save. */ if (!vcpu_align) vcpu_align = __alignof__(struct kvm_vcpu );
@@ -2572,7 +2557,7 @@ int kvm_init(void *opaque, unsigned vcpu 0, NULL);if (!kvm_vcpu_cache) { r = -ENOMEM ; - goto out_free_5; + goto out_free_3; } r =kvm_async_pf_init ();
@@ -2589,6 +2574,8 @@ int kvm_init(void *opaque, unsigned vcpu goto out_unreg; } +register_syscore_ops (&kvm_syscore_ops); + kvm_preempt_ops.sched_in = kvm_sched_in; kvm_preempt_ops.sched_out = kvm_sched_out;
@@ -2600,10 +2587,6 @@ out_unreg:kvm_async_pf_deinit (); out_free:kmem_cache_destroy (kvm_vcpu_cache); -out_free_5: -sysdev_unregister (&kvm_sysdev); -out_free_4: -sysdev_class_unregister (&kvm_sysdev_class); out_free_3:unregister_reboot_notifier (&kvm_reboot_notifier);unregister_cpu_notifier (&kvm_cpu_notifier);
@@ -2631,8 +2614,7 @@ void kvm_exit(void)misc_deregister (&kvm_dev);kmem_cache_destroy (kvm_vcpu_cache);kvm_async_pf_deinit (); -sysdev_unregister (&kvm_sysdev); -sysdev_class_unregister (&kvm_sysdev_class); +unregister_syscore_ops (&kvm_syscore_ops);unregister_reboot_notifier (&kvm_reboot_notifier);unregister_cpu_notifier (&kvm_cpu_notifier);on_each_cpu (hardware_disable_nolock,NULL ,1 );
PATCH 5/6 cpufreq: Use syscore_ops for boot CPU suspend/resume (v2)
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
The cpufreq subsystem uses sysdev suspend and resume for executing cpufreq_suspend() and cpufreq_resume(), respectively, during system suspend, after interrupts have been switched off on the boot CPU, and during system resume, while interrupts are still off on the boot CPU. In both cases the other CPUs are off-line at the relevant point (either they have been switched off via CPU hotplug during suspend, or they haven't been switched on yet during resume). For this reason, although it may seem that cpufreq_suspend() and cpufreq_resume() are executed for all CPUs in the system, they are only called for the boot CPU in fact, which is quite confusing.
To remove the confusion and to prepare for elimiating sysdev suspend and resume operations from the kernel enirely, convernt cpufreq to using a struct syscore_ops object for the boot CPU suspend and resume and rename the callbacks so that their names reflect their purpose. In addition, put some explanatory remarks into their kerneldoc comments.
--- drivers/cpufreq/cpufreq.c | 66 ++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 40 deletions(-)
drivers/cpufreq/cpufreq.c +26 -40
@@ -28,6 +28,7 @@#include <linux/cpu.h> #include <linux/completion.h> #include <linux/mutex.h> +#include <linux/syscore_ops.h> #include <trace/events/power.h>
@@ -1340,35 +1341,31 @@ out: }EXPORT_SYMBOL (cpufreq_get); +static struct sysdev_driver cpufreq_sysdev_driver = { + .add = cpufreq_add_dev, + .remove = cpufreq_remove_dev, +}; +/** -* cpufreq_suspend - let the low level driver prepare for suspend +* cpufreq_bp_suspend - Prepare the boot CPU for system suspend. +* +* This function is only executed for the boot processor. The other CPUs +* have been put offline by means of CPU hotplug. */ - -static int cpufreq_suspend (struct sys_device *sysdev,pm_message_t pmsg) +static int cpufreq_bp_suspend (void ) {int ret =0 ; -int cpu = sysdev->id; +int cpu =smp_processor_id ();struct cpufreq_policy *cpu_policy;dprintk ("suspending cpu %u\n" , cpu); -if (!cpu_online (cpu)) -return 0 ; - -/* we may be lax here as interrupts are off. Nonetheless -* we need to grab the correct cpu policy, as to check -* whether we really run on this CPU. -*/ - +/* If there's no policy for the boot CPU, we have nothing to do. */ cpu_policy =cpufreq_cpu_get (cpu);if (!cpu_policy) -return -EINVAL ; - -/* only handle each CPU group once */ -if (unlikely (cpu_policy->cpu != cpu)) - goto out; +return 0 ;if (cpufreq_driver->suspend) { ret = cpufreq_driver->suspend (cpu_policy);
@@ -1377,13 +1374,12 @@ static int cpufreq_suspend(struct sys_de "step on CPU %u\n", cpu_policy->cpu); } -out:cpufreq_cpu_put (cpu_policy);return ret; }/** -* cpufreq_resume - restore proper CPU frequency handling after resume +* cpufreq_bp_resume - Restore proper frequency handling of the boot CPU. * * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are
@@ -1391,31 +1387,23 @@ out:* what we believe it to be. This is a bit later than when it * should be, but nonethteless it's better than calling * cpufreq_driver->get() here which might re-enable interrupts... +* +* This function is only executed for the boot CPU. The other CPUs have not +* been turned on yet. */ -static int cpufreq_resume (struct sys_device *sysdev) +static void cpufreq_bp_resume (void ) {int ret =0 ; -int cpu = sysdev->id; +int cpu =smp_processor_id ();struct cpufreq_policy *cpu_policy;dprintk ("resuming cpu %u\n" , cpu); -if (!cpu_online (cpu)) -return 0 ; - -/* we may be lax here as interrupts are off. Nonetheless -* we need to grab the correct cpu policy, as to check -* whether we really run on this CPU. -*/ - +/* If there's no policy for the boot CPU, we have nothing to do. */ cpu_policy =cpufreq_cpu_get (cpu);if (!cpu_policy) -return -EINVAL ; - -/* only handle each CPU group once */ -if (unlikely (cpu_policy->cpu != cpu)) - goto fail; +return ;if (cpufreq_driver->resume) { ret = cpufreq_driver->resume (cpu_policy);
@@ -1430,14 +1418,11 @@ static int cpufreq_resume(struct sys_dev fail:cpufreq_cpu_put (cpu_policy); -return ret; } -static struct sysdev_driver cpufreq_sysdev_driver = { - .add = cpufreq_add_dev, - .remove = cpufreq_remove_dev, - .suspend = cpufreq_suspend, - .resume = cpufreq_resume, +static struct syscore_ops cpufreq_syscore_ops = { + .suspend = cpufreq_bp_suspend, + .resume = cpufreq_bp_resume, };
@@ -2002,6 +1987,7 @@ static int __init cpufreq_core_init(void cpufreq_global_kobject =kobject_create_and_add ("cpufreq" , &cpu_sysdev_class.kset.kobj);BUG_ON (!cpufreq_global_kobject); +register_syscore_ops (&cpufreq_syscore_ops);return 0 ; }
PATCH 5/6 cpufreq: Use syscore_ops for boot CPU suspend/resume (v2)
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
The cpufreq subsystem uses sysdev suspend and resume for executing cpufreq_suspend() and cpufreq_resume(), respectively, during system suspend, after interrupts have been switched off on the boot CPU, and during system resume, while interrupts are still off on the boot CPU. In both cases the other CPUs are off-line at the relevant point (either they have been switched off via CPU hotplug during suspend, or they haven't been switched on yet during resume). For this reason, although it may seem that cpufreq_suspend() and cpufreq_resume() are executed for all CPUs in the system, they are only called for the boot CPU in fact, which is quite confusing.
To remove the confusion and to prepare for elimiating sysdev suspend and resume operations from the kernel enirely, convernt cpufreq to using a struct syscore_ops object for the boot CPU suspend and resume and rename the callbacks so that their names reflect their purpose. In addition, put some explanatory remarks into their kerneldoc comments.
--- drivers/cpufreq/cpufreq.c | 66 ++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 40 deletions(-)
drivers/cpufreq/cpufreq.c +26 -40
@@ -28,6 +28,7 @@#include <linux/cpu.h> #include <linux/completion.h> #include <linux/mutex.h> +#include <linux/syscore_ops.h> #include <trace/events/power.h>
@@ -1340,35 +1341,31 @@ out: }EXPORT_SYMBOL (cpufreq_get); +static struct sysdev_driver cpufreq_sysdev_driver = { + .add = cpufreq_add_dev, + .remove = cpufreq_remove_dev, +}; +/** -* cpufreq_suspend - let the low level driver prepare for suspend +* cpufreq_bp_suspend - Prepare the boot CPU for system suspend. +* +* This function is only executed for the boot processor. The other CPUs +* have been put offline by means of CPU hotplug. */ - -static int cpufreq_suspend (struct sys_device *sysdev,pm_message_t pmsg) +static int cpufreq_bp_suspend (void ) {int ret =0 ; -int cpu = sysdev->id; +int cpu =smp_processor_id ();struct cpufreq_policy *cpu_policy;dprintk ("suspending cpu %u\n" , cpu); -if (!cpu_online (cpu)) -return 0 ; - -/* we may be lax here as interrupts are off. Nonetheless -* we need to grab the correct cpu policy, as to check -* whether we really run on this CPU. -*/ - +/* If there's no policy for the boot CPU, we have nothing to do. */ cpu_policy =cpufreq_cpu_get (cpu);if (!cpu_policy) -return -EINVAL ; - -/* only handle each CPU group once */ -if (unlikely (cpu_policy->cpu != cpu)) - goto out; +return 0 ;if (cpufreq_driver->suspend) { ret = cpufreq_driver->suspend (cpu_policy);
@@ -1377,13 +1374,12 @@ static int cpufreq_suspend(struct sys_de "step on CPU %u\n", cpu_policy->cpu); } -out:cpufreq_cpu_put (cpu_policy);return ret; }/** -* cpufreq_resume - restore proper CPU frequency handling after resume +* cpufreq_bp_resume - Restore proper frequency handling of the boot CPU. * * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are
@@ -1391,31 +1387,23 @@ out:* what we believe it to be. This is a bit later than when it * should be, but nonethteless it's better than calling * cpufreq_driver->get() here which might re-enable interrupts... +* +* This function is only executed for the boot CPU. The other CPUs have not +* been turned on yet. */ -static int cpufreq_resume (struct sys_device *sysdev) +static void cpufreq_bp_resume (void ) {int ret =0 ; -int cpu = sysdev->id; +int cpu =smp_processor_id ();struct cpufreq_policy *cpu_policy;dprintk ("resuming cpu %u\n" , cpu); -if (!cpu_online (cpu)) -return 0 ; - -/* we may be lax here as interrupts are off. Nonetheless -* we need to grab the correct cpu policy, as to check -* whether we really run on this CPU. -*/ - +/* If there's no policy for the boot CPU, we have nothing to do. */ cpu_policy =cpufreq_cpu_get (cpu);if (!cpu_policy) -return -EINVAL ; - -/* only handle each CPU group once */ -if (unlikely (cpu_policy->cpu != cpu)) - goto fail; +return ;if (cpufreq_driver->resume) { ret = cpufreq_driver->resume (cpu_policy);
@@ -1430,14 +1418,11 @@ static int cpufreq_resume(struct sys_dev fail:cpufreq_cpu_put (cpu_policy); -return ret; } -static struct sysdev_driver cpufreq_sysdev_driver = { - .add = cpufreq_add_dev, - .remove = cpufreq_remove_dev, - .suspend = cpufreq_suspend, - .resume = cpufreq_resume, +static struct syscore_ops cpufreq_syscore_ops = { + .suspend = cpufreq_bp_suspend, + .resume = cpufreq_bp_resume, };
@@ -2002,6 +1987,7 @@ static int __init cpufreq_core_init(void cpufreq_global_kobject =kobject_create_and_add ("cpufreq" , &cpu_sysdev_class.kset.kobj);BUG_ON (!cpufreq_global_kobject); +register_syscore_ops (&cpufreq_syscore_ops);return 0 ; }
PATCH 6/6 Introduce ARCH_NO_SYSDEV_OPS config option (v2)
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
Introduce Kconfig option allowing architectures where sysdev operations used during system suspend, resume and shutdown have been completely replaced with struct sycore_ops operations to avoid building sysdev code that will never be used.
Make callbacks in struct sys_device and struct sysdev_driver depend on ARCH_NO_SYSDEV_OPS to allows us to verify if all of the references have been actually removed from the code the given architecture depends on.
Make x86 select ARCH_NO_SYSDEV_OPS.
--- arch/x86/Kconfig | 1 + drivers/base/Kconfig | 7 +++++++ drivers/base/sys.c | 3 ++- include/linux/device.h | 4 ++++ include/linux/pm.h | 10 ++++++++-- include/linux/sysdev.h | 7 +++++-- 6 files changed, 27 insertions(+), 5 deletions(-)
include/linux/pm.h +8 -2
@@ -529,13 +529,19 @@ struct dev_power_domain {*/ #ifdef CONFIG_PM_SLEEP -extern void device_pm_lock (void ); +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS +extern int sysdev_suspend (pm_message_t state);extern int sysdev_resume (void ); +#else +static inline int sysdev_suspend (pm_message_t state) {return 0 ; } +static inline int sysdev_resume (void ) {return 0 ; } +#endif + +extern void device_pm_lock (void );extern void dpm_resume_noirq (pm_message_t state);extern void dpm_resume_end (pm_message_t state);extern void device_pm_unlock (void ); -extern int sysdev_suspend (pm_message_t state);extern int dpm_suspend_noirq (pm_message_t state);extern int dpm_suspend_start (pm_message_t state);
include/linux/sysdev.h +5 -2
@@ -33,12 +33,13 @@ struct sysdev_class {const char *name;struct list_head drivers;struct sysdev_class_attribute **attrs; - +struct kset kset; +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS /* Default operations for these types of devices */ int (*shutdown)(struct sys_device *);int (*suspend)(struct sys_device *,pm_message_t state);int (*resume)(struct sys_device *); -struct kset kset; +#endif };struct sysdev_class_attribute {
@@ -76,9 +77,11 @@ struct sysdev_driver {struct list_head entry;int (*add)(struct sys_device *);int (*remove)(struct sys_device *); +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS int (*shutdown)(struct sys_device *);int (*suspend)(struct sys_device *,pm_message_t state);int (*resume)(struct sys_device *); +#endif };
include/linux/device.h +4 -0
@@ -633,8 +633,12 @@ static inline int devtmpfs_mount(const c/* drivers/base/power/shutdown.c */ extern void device_shutdown (void ); +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS /* drivers/base/sys.c */ extern void sysdev_shutdown (void ); +#else +static inline void sysdev_shutdown (void ) { } +#endif /* debugging and troubleshooting/diagnostic helpers. */ extern const char *dev_driver_string (const struct device *dev);
arch/x86/Kconfig +1 -0
@@ -71,6 +71,7 @@ config X86 select GENERIC_IRQ_SHOW select IRQ_FORCED_THREADING select USE_GENERIC_SMP_HELPERS if SMP + select ARCH_NO_SYSDEV_OPS config INSTRUCTION_DECODER def_bool (KPROBES || PERF_EVENTS)
drivers/base/sys.c +2 -1
@@ -329,7 +329,7 @@ void sysdev_unregister(struct sys_device } - +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS /** * sysdev_shutdown - Shut down all system devices. *
@@ -524,6 +524,7 @@ int sysdev_resume(void) return 0; }EXPORT_SYMBOL_GPL (sysdev_resume); +#endif /* CONFIG_ARCH_NO_SYSDEV_OPS */ int __init system_bus_init (void ) {
drivers/base/Kconfig +7 -0
@@ -168,4 +168,11 @@ config SYS_HYPERVISOR bool default n +config ARCH_NO_SYSDEV_OPS + bool + ---help--- + To be selected by architectures that don't use sysdev class or + sysdev driver power management (suspend/resume) and shutdown + operations. + endmenu
PATCH 6/6 Introduce ARCH_NO_SYSDEV_OPS config option (v2)
In reply to Rafael J. WysockiFrom: Rafael J. Wysocki <[email protected]>
Introduce Kconfig option allowing architectures where sysdev operations used during system suspend, resume and shutdown have been completely replaced with struct sycore_ops operations to avoid building sysdev code that will never be used.
Make callbacks in struct sys_device and struct sysdev_driver depend on ARCH_NO_SYSDEV_OPS to allows us to verify if all of the references have been actually removed from the code the given architecture depends on.
Make x86 select ARCH_NO_SYSDEV_OPS.
--- arch/x86/Kconfig | 1 + drivers/base/Kconfig | 7 +++++++ drivers/base/sys.c | 3 ++- include/linux/device.h | 4 ++++ include/linux/pm.h | 10 ++++++++-- include/linux/sysdev.h | 7 +++++-- 6 files changed, 27 insertions(+), 5 deletions(-)
include/linux/pm.h +8 -2
@@ -529,13 +529,19 @@ struct dev_power_domain {*/ #ifdef CONFIG_PM_SLEEP -extern void device_pm_lock (void ); +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS +extern int sysdev_suspend (pm_message_t state);extern int sysdev_resume (void ); +#else +static inline int sysdev_suspend (pm_message_t state) {return 0 ; } +static inline int sysdev_resume (void ) {return 0 ; } +#endif + +extern void device_pm_lock (void );extern void dpm_resume_noirq (pm_message_t state);extern void dpm_resume_end (pm_message_t state);extern void device_pm_unlock (void ); -extern int sysdev_suspend (pm_message_t state);extern int dpm_suspend_noirq (pm_message_t state);extern int dpm_suspend_start (pm_message_t state);
include/linux/sysdev.h +5 -2
@@ -33,12 +33,13 @@ struct sysdev_class {const char *name;struct list_head drivers;struct sysdev_class_attribute **attrs; - +struct kset kset; +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS /* Default operations for these types of devices */ int (*shutdown)(struct sys_device *);int (*suspend)(struct sys_device *,pm_message_t state);int (*resume)(struct sys_device *); -struct kset kset; +#endif };struct sysdev_class_attribute {
@@ -76,9 +77,11 @@ struct sysdev_driver {struct list_head entry;int (*add)(struct sys_device *);int (*remove)(struct sys_device *); +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS int (*shutdown)(struct sys_device *);int (*suspend)(struct sys_device *,pm_message_t state);int (*resume)(struct sys_device *); +#endif };
include/linux/device.h +4 -0
@@ -633,8 +633,12 @@ static inline int devtmpfs_mount(const c/* drivers/base/power/shutdown.c */ extern void device_shutdown (void ); +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS /* drivers/base/sys.c */ extern void sysdev_shutdown (void ); +#else +static inline void sysdev_shutdown (void ) { } +#endif /* debugging and troubleshooting/diagnostic helpers. */ extern const char *dev_driver_string (const struct device *dev);
arch/x86/Kconfig +1 -0
@@ -71,6 +71,7 @@ config X86 select GENERIC_IRQ_SHOW select IRQ_FORCED_THREADING select USE_GENERIC_SMP_HELPERS if SMP + select ARCH_NO_SYSDEV_OPS config INSTRUCTION_DECODER def_bool (KPROBES || PERF_EVENTS)
drivers/base/sys.c +2 -1
@@ -329,7 +329,7 @@ void sysdev_unregister(struct sys_device } - +#ifndef CONFIG_ARCH_NO_SYSDEV_OPS /** * sysdev_shutdown - Shut down all system devices. *
@@ -524,6 +524,7 @@ int sysdev_resume(void) return 0; }EXPORT_SYMBOL_GPL (sysdev_resume); +#endif /* CONFIG_ARCH_NO_SYSDEV_OPS */ int __init system_bus_init (void ) {
drivers/base/Kconfig +7 -0
@@ -168,4 +168,11 @@ config SYS_HYPERVISOR bool default n +config ARCH_NO_SYSDEV_OPS + bool + ---help--- + To be selected by architectures that don't use sysdev class or + sysdev driver power management (suspend/resume) and shutdown + operations. + endmenu
Re: [PATCH 0/6] Do not use sysdevs for implementing "core" PM operations on x86
In reply to Rafael J. WysockiQuoted 11 lines · Rafael J. Wysocki
Quoted 2 lines
If there are no objectsions, I'd like to push these patches through the suspend tree.
[1/8] has been merged in the meantime and [3/8] has been included into the ACPI tree. if there are no objections, I'm going to push the following patches to Linus this week through the suspend-2.6 tree:
[1/6] - Convert sysdev users in
arch/x86to using structsyscore_ops.[2/6] - Make timekeeping use struct
syscore_opsfor suspend/resume.
Quoted 8 lines
[3/6] - Make Intel IOMMU use struct
syscore_opsfor suspend/resume.[4/6] - Make KVM use struct
syscore_opsfor suspend/resume.[5/6] - Make cpufreq use struct
syscore_opsfor boot CPU suspend/resume.[6/6] - Introduce config switch allowing architectures to skip sysdev
suspend/resume/shutdown code.
The x86 bits look fine.
The patches affect a lot of hardware so please make sure they are tested well before pushing them to Linus :-)
Ingo
Re: [PATCH 0/6] Do not use sysdevs for implementing "core" PM operations on x86
Quoted 18 lines · Ingo Molnar
Quoted 15 lines · Rafael J. Wysocki
Quoted 2 lines
If there are no objectsions, I'd like to push these patches through the suspend tree.
[1/8] has been merged in the meantime and [3/8] has been included into the ACPI tree. if there are no objections, I'm going to push the following patches to Linus this week through the suspend-2.6 tree:
[1/6] - Convert sysdev users in
arch/x86to using structsyscore_ops.[2/6] - Make timekeeping use struct
syscore_opsfor suspend/resume.[3/6] - Make Intel IOMMU use struct
syscore_opsfor suspend/resume.[4/6] - Make KVM use struct
syscore_opsfor suspend/resume.
Quoted 8 lines
Quoted 4 lines
[5/6] - Make cpufreq use struct
syscore_opsfor boot CPU suspend/resume.[6/6] - Introduce config switch allowing architectures to skip sysdev
suspend/resume/shutdown code.The x86 bits look fine.
Acked-by Ingo Molnar <[email protected]>
Thanks!
Quoted 2 lines
The patches affect a lot of hardware so please make sure they are tested well before pushing them to Linus :-)
I have tested the majority, but unfortunately I have no hardware to test the Intel IOMMU patch on it.
Thanks,
Rafael
[GIT PULL] More power management updates for 2.6.39
Hi Linus,
Please pull additional power management updates for 2.6.39 from:
git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6.git syscore
They make subsystems that x86 depends on use struct syscore_ops objects instead of sysdevs for "core" power management, which reduces the code size and kernel memory footprint a bit and sipmlifies the "core" suspend/resume and shutdown code paths.
arch/x86/Kconfig | 1 + arch/x86/kernel/amd_iommu_init.c | 26 ++-------- arch/x86/kernel/apic/apic.c | 33 ++++--------- arch/x86/kernel/apic/io_apic.c | 97 ++++++++++++++++++-------------------- arch/x86/kernel/cpu/mcheck/mce.c | 21 +++++---- arch/x86/kernel/cpu/mtrr/main.c | 10 ++-- arch/x86/kernel/i8237.c | 30 +++--------- arch/x86/kernel/i8259.c | 33 ++++--------- arch/x86/kernel/microcode_core.c | 34 ++++++-------- arch/x86/kernel/pci-gart_64.c | 32 +++---------- arch/x86/oprofile/nmi_int.c | 44 +++++------------ drivers/base/Kconfig | 7 +++ drivers/base/sys.c | 3 +- drivers/cpufreq/cpufreq.c | 66 ++++++++++---------------- drivers/pci/intel-iommu.c | 38 ++++----------- include/linux/device.h | 4 ++ include/linux/pm.h | 10 +++- include/linux/sysdev.h | 7 ++- kernel/time/timekeeping.c | 27 +++------- virt/kvm/kvm_main.c | 34 +++---------- 20 files changed, 206 insertions(+), 351 deletions(-)
---------------
Rafael J. Wysocki (6):
x86: Use syscore_ops instead of sysdev classes and sysdevs
timekeeping: Use syscore_ops instead of sysdev class and sysdev PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
KVM: Use syscore_ops instead of sysdev class and sysdev
cpufreq: Use syscore_ops for boot CPU suspend/resume (v2) Introduce ARCH_NO_SYSDEV_OPS config option (v2)
[GIT PULL] More power management updates for 2.6.39
In reply to Rafael J. WysockiHi Linus,
Please pull additional power management updates for 2.6.39 from:
git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6.git syscore
They make subsystems that x86 depends on use struct syscore_ops objects instead of sysdevs for "core" power management, which reduces the code size and kernel memory footprint a bit and sipmlifies the "core" suspend/resume and shutdown code paths.
arch/x86/Kconfig | 1 + arch/x86/kernel/amd_iommu_init.c | 26 ++-------- arch/x86/kernel/apic/apic.c | 33 ++++--------- arch/x86/kernel/apic/io_apic.c | 97 ++++++++++++++++++-------------------- arch/x86/kernel/cpu/mcheck/mce.c | 21 +++++---- arch/x86/kernel/cpu/mtrr/main.c | 10 ++-- arch/x86/kernel/i8237.c | 30 +++--------- arch/x86/kernel/i8259.c | 33 ++++--------- arch/x86/kernel/microcode_core.c | 34 ++++++-------- arch/x86/kernel/pci-gart_64.c | 32 +++---------- arch/x86/oprofile/nmi_int.c | 44 +++++------------ drivers/base/Kconfig | 7 +++ drivers/base/sys.c | 3 +- drivers/cpufreq/cpufreq.c | 66 ++++++++++---------------- drivers/pci/intel-iommu.c | 38 ++++----------- include/linux/device.h | 4 ++ include/linux/pm.h | 10 +++- include/linux/sysdev.h | 7 ++- kernel/time/timekeeping.c | 27 +++------- virt/kvm/kvm_main.c | 34 +++---------- 20 files changed, 206 insertions(+), 351 deletions(-)
---------------
Rafael J. Wysocki (6):
x86: Use syscore_ops instead of sysdev classes and sysdevs
timekeeping: Use syscore_ops instead of sysdev class and sysdev PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev
KVM: Use syscore_ops instead of sysdev class and sysdev
cpufreq: Use syscore_ops for boot CPU suspend/resume (v2) Introduce ARCH_NO_SYSDEV_OPS config option (v2)
Re: [PATCH 0/6] Do not use sysdevs for implementing "core" PM operations on x86
In reply to Ingo MolnarQuoted 18 lines · Ingo Molnar
Quoted 15 lines · Rafael J. Wysocki
Quoted 2 lines
If there are no objectsions, I'd like to push these patches through the suspend tree.
[1/8] has been merged in the meantime and [3/8] has been included into the ACPI tree. if there are no objections, I'm going to push the following patches to Linus this week through the suspend-2.6 tree:
[1/6] - Convert sysdev users in
arch/x86to using structsyscore_ops.[2/6] - Make timekeeping use struct
syscore_opsfor suspend/resume.[3/6] - Make Intel IOMMU use struct
syscore_opsfor suspend/resume.[4/6] - Make KVM use struct
syscore_opsfor suspend/resume.
Quoted 8 lines
Quoted 4 lines
[5/6] - Make cpufreq use struct
syscore_opsfor boot CPU suspend/resume.[6/6] - Introduce config switch allowing architectures to skip sysdev
suspend/resume/shutdown code.The x86 bits look fine.
Acked-by Ingo Molnar <[email protected]>
Thanks!
Quoted 2 lines
The patches affect a lot of hardware so please make sure they are tested well before pushing them to Linus :-)
I have tested the majority, but unfortunately I have no hardware to test the Intel IOMMU patch on it.
Thanks,
Rafael
Re: [PATCH 0/6] Do not use sysdevs for implementing "core" PM operations on x86
In reply to Rafael J. WysockiQuoted 11 lines · Rafael J. Wysocki
Quoted 2 lines
If there are no objectsions, I'd like to push these patches through the suspend tree.
[1/8] has been merged in the meantime and [3/8] has been included into the ACPI tree. if there are no objections, I'm going to push the following patches to Linus this week through the suspend-2.6 tree:
[1/6] - Convert sysdev users in
arch/x86to using structsyscore_ops.[2/6] - Make timekeeping use struct
syscore_opsfor suspend/resume.
Quoted 8 lines
[3/6] - Make Intel IOMMU use struct
syscore_opsfor suspend/resume.[4/6] - Make KVM use struct
syscore_opsfor suspend/resume.[5/6] - Make cpufreq use struct
syscore_opsfor boot CPU suspend/resume.[6/6] - Introduce config switch allowing architectures to skip sysdev
suspend/resume/shutdown code.
The x86 bits look fine.
The patches affect a lot of hardware so please make sure they are tested well before pushing them to Linus :-)
Ingo
cover Do not use sysdevs for implementing "core" PM operations on x86
In reply to Rafael J. WysockiHi,
Quoted 62 lines · Rafael J. Wysocki
Quoted 35 lines · Rafael J. Wysocki
There are multiple problems with sysdevs, or struct
sys_deviceobjects to be precise, that are so annoying that some people have started to think of removind them entirely from the kernel. To me, personally, the most obvious issue is the way sysdevs are used for defining suspend/resume callbacks to be executed with one CPU on-line and interrupts disabled. Greg and Kay may tell you more about the other problems with sysdevs. :-)Some subsystems need to carry out certain operations during suspend after we've disabled non-boot CPUs and interrupts have been switched off on the only on-line one. Currently, the only way to achieve that is to define sysdev suspend/resume callbacks, but this is cumbersome and inefficient. Namely, to do that, one has to define a sysdev class providing the callbacks and a sysdev actually using them, which is excessively complicated. Moreover, the sysdev suspend/resume callbacks take arguments that are not really used by the majority of subsystems defining sysdev suspend/resume callbacks (or even if they are used, they don't really _need_ to be used, so they are simply unnecessary). Of course, if a sysdev is only defined to provide suspend/resume (and maybe shutdown) callbacks, there's no real reason why it should show up in sysfs.
For this reason, I thought it would be a good idea to provide a simpler interface for subsystems to define "very late" suspend callbacks and "very early" resume callbacks (and "very late" shutdown callbacks as well) without the entire bloat related to sysdevs. The interface is introduced by the first of the following patches, while the second patch converts some sysdev users related to the x86 architecture to using the new interface.
I believe that call sysdev users who need to define suspend/resume/shutdown callbacks may be converted to using the interface provided by the first patch, which in turn should allow us to convert the remaining sysdev functionality into "normal" struct device interfaces. Still, even if that turns out to be too complicated, the bloat reduction resulting from the second patch kind of shows that moving at least some sysdev users to a simpler interface (like in the first patch) is a good idea anyway.
Quoted 4 lines
This is a proof of concept, so the patches have not been tested. Please be extrememly careful, because they touch sensitive code, so to speak. In the majority of cases the changes are rather straightforward, but there are some more interesting cases as well (
io_apic.cmost importantly).Since Greg likes the idea and there haven't been any objections so far, here's the official submission. The patches have been tested on HP nx6325 and Toshiba Portege R500.
Patch [1/8] is regareded as 2.6.38 material, following Greg's advice. The other patches in the set are regarded as 2.6.39 material. The last one obviously depends on all of the previous ones.
[1/8] - Introduce struct
syscore_opsfor registering operations to be run on
one CPU during suspend/resume/shutdown.[2/8] - Convert sysdev users in
arch/x86to using structsyscore_ops.[3/8] - Make ACPI use struct
syscore_opsforirqrouter_resume().[4/8] - Make timekeeping use struct
syscore_opsfor suspend/resume.[5/8] - Make Intel IOMMU use struct
syscore_opsfor suspend/resume.[6/8] - Make KVM use struct
syscore_opsfor suspend/resume.
Quoted 7 lines
[7/8] - Make cpufreq use struct
syscore_opsfor boot CPU suspend/resume.[8/8] - Introduce config switch allowing architectures to skip sysdev
suspend/resume/shutdown code.If there are no objectsions, I'd like to push these patches through the suspend tree.
[1/8] has been merged in the meantime and [3/8] has been included into the ACPI tree. if there are no objections, I'm going to push the following patches to Linus this week through the suspend-2.6 tree:
[1/6] - Convert sysdev users in arch/x86 to using struct syscore_ops.
[2/6] - Make timekeeping use struct syscore_ops for suspend/resume.
[3/6] - Make Intel IOMMU use struct syscore_ops for suspend/resume.
[4/6] - Make KVM use struct syscore_ops for suspend/resume.
[5/6] - Make cpufreq use struct syscore_ops for boot CPU suspend/resume.
[6/6] - Introduce config switch allowing architectures to skip sysdev
suspend/resume/shutdown code.
Thanks,
Rafael