Skip to content

Commit

Permalink
ARM: Use struct syscore_ops instead of sysdevs for PM in common code
Browse files Browse the repository at this point in the history
Convert some ARM architecture's common code to using
struct syscore_ops objects for power management instead of sysdev
classes and sysdevs.

This simplifies the code and reduces the kernel's memory footprint.
It also is necessary for removing sysdevs from the kernel entirely in
the future.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Rafael J. Wysocki committed Apr 24, 2011
1 parent 5dd12af commit 328f5cc
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 94 deletions.
69 changes: 25 additions & 44 deletions arch/arm/common/vic.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/io.h>
#include <linux/sysdev.h>
#include <linux/syscore_ops.h>
#include <linux/device.h>
#include <linux/amba/bus.h>

#include <asm/mach/irq.h>
#include <asm/hardware/vic.h>

#if defined(CONFIG_PM)
#ifdef CONFIG_PM
/**
* struct vic_device - VIC PM device
* @sysdev: The system device which is registered.
* @irq: The IRQ number for the base of the VIC.
* @base: The register base for the VIC.
* @resume_sources: A bitmask of interrupts for resume.
Expand All @@ -43,8 +42,6 @@
* @protect: Save for VIC_PROTECT.
*/
struct vic_device {
struct sys_device sysdev;

void __iomem *base;
int irq;
u32 resume_sources;
Expand All @@ -59,11 +56,6 @@ struct vic_device {
static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];

static int vic_id;

static inline struct vic_device *to_vic(struct sys_device *sys)
{
return container_of(sys, struct vic_device, sysdev);
}
#endif /* CONFIG_PM */

/**
Expand All @@ -85,10 +77,9 @@ static void vic_init2(void __iomem *base)
writel(32, base + VIC_PL190_DEF_VECT_ADDR);
}

#if defined(CONFIG_PM)
static int vic_class_resume(struct sys_device *dev)
#ifdef CONFIG_PM
static void resume_one_vic(struct vic_device *vic)
{
struct vic_device *vic = to_vic(dev);
void __iomem *base = vic->base;

printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
Expand All @@ -107,13 +98,18 @@ static int vic_class_resume(struct sys_device *dev)

writel(vic->soft_int, base + VIC_INT_SOFT);
writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
}

return 0;
static void vic_resume(void)
{
int id;

for (id = vic_id - 1; id >= 0; id--)
resume_one_vic(vic_devices + id);
}

static int vic_class_suspend(struct sys_device *dev, pm_message_t state)
static void suspend_one_vic(struct vic_device *vic)
{
struct vic_device *vic = to_vic(dev);
void __iomem *base = vic->base;

printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
Expand All @@ -128,14 +124,21 @@ static int vic_class_suspend(struct sys_device *dev, pm_message_t state)

writel(vic->resume_irqs, base + VIC_INT_ENABLE);
writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR);
}

static int vic_suspend(void)
{
int id;

for (id = 0; id < vic_id; id++)
suspend_one_vic(vic_devices + id);

return 0;
}

struct sysdev_class vic_class = {
.name = "vic",
.suspend = vic_class_suspend,
.resume = vic_class_resume,
struct syscore_ops vic_syscore_ops = {
.suspend = vic_suspend,
.resume = vic_resume,
};

/**
Expand All @@ -147,30 +150,8 @@ struct sysdev_class vic_class = {
*/
static int __init vic_pm_init(void)
{
struct vic_device *dev = vic_devices;
int err;
int id;

if (vic_id == 0)
return 0;

err = sysdev_class_register(&vic_class);
if (err) {
printk(KERN_ERR "%s: cannot register class\n", __func__);
return err;
}

for (id = 0; id < vic_id; id++, dev++) {
dev->sysdev.id = id;
dev->sysdev.cls = &vic_class;

err = sysdev_register(&dev->sysdev);
if (err) {
printk(KERN_ERR "%s: failed to register device\n",
__func__);
return err;
}
}
if (vic_id > 0)
register_syscore_ops(&vic_syscore_ops);

return 0;
}
Expand Down
1 change: 0 additions & 1 deletion arch/arm/include/asm/mach/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 16 additions & 12 deletions arch/arm/kernel/leds.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -69,36 +70,37 @@ static ssize_t leds_store(struct sys_device *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;
Expand All @@ -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;
}

Expand Down
35 changes: 12 additions & 23 deletions arch/arm/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -115,48 +115,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)
{
Expand Down
19 changes: 5 additions & 14 deletions arch/arm/vfp/vfpmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,9 @@ static void vfp_enable(void *unused)
}

#ifdef CONFIG_PM
#include <linux/sysdev.h>
#include <linux/syscore_ops.h>

static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
static int vfp_pm_suspend(void)
{
struct thread_info *ti = current_thread_info();
u32 fpexc = fmrx(FPEXC);
Expand All @@ -420,34 +420,25 @@ static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}

static int vfp_pm_resume(struct sys_device *dev)
static void vfp_pm_resume(void)
{
/* ensure we have access to the vfp */
vfp_enable(NULL);

/* and disable it to ensure the next usage restores the state */
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);

return 0;
}

static struct sysdev_class vfp_pm_sysclass = {
.name = "vfp",
static struct syscore_ops vfp_pm_syscore_ops = {
.suspend = vfp_pm_suspend,
.resume = vfp_pm_resume,
};

static struct sys_device vfp_pm_sysdev = {
.cls = &vfp_pm_sysclass,
};

static void vfp_pm_init(void)
{
sysdev_class_register(&vfp_pm_sysclass);
sysdev_register(&vfp_pm_sysdev);
register_syscore_ops(&vfp_pm_syscore_ops);
}


#else
static inline void vfp_pm_init(void) { }
#endif /* CONFIG_PM */
Expand Down

0 comments on commit 328f5cc

Please sign in to comment.