aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-power14
-rw-r--r--Documentation/feature-removal-schedule.txt8
-rw-r--r--Documentation/kernel-parameters.txt2
-rw-r--r--Documentation/power/devices.txt14
-rw-r--r--Documentation/power/notifiers.txt51
-rw-r--r--arch/arm/common/vic.c69
-rw-r--r--arch/arm/include/asm/mach/time.h1
-rw-r--r--arch/arm/kernel/leds.c28
-rw-r--r--arch/arm/kernel/time.c35
-rw-r--r--arch/arm/mach-exynos4/pm.c45
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c26
-rw-r--r--arch/arm/mach-omap1/pm_bus.c69
-rw-r--r--arch/arm/mach-omap2/Makefile6
-rw-r--r--arch/arm/mach-omap2/pm_bus.c85
-rw-r--r--arch/arm/mach-pxa/balloon3.c1
-rw-r--r--arch/arm/mach-pxa/clock-pxa2xx.c18
-rw-r--r--arch/arm/mach-pxa/clock-pxa3xx.c17
-rw-r--r--arch/arm/mach-pxa/clock.h7
-rw-r--r--arch/arm/mach-pxa/cm-x270.c1
-rw-r--r--arch/arm/mach-pxa/cm-x2xx.c23
-rw-r--r--arch/arm/mach-pxa/colibri-evalboard.c1
-rw-r--r--arch/arm/mach-pxa/colibri-pxa270-income.c1
-rw-r--r--arch/arm/mach-pxa/colibri-pxa270.c1
-rw-r--r--arch/arm/mach-pxa/generic.h8
-rw-r--r--arch/arm/mach-pxa/irq.c17
-rw-r--r--arch/arm/mach-pxa/lpd270.c20
-rw-r--r--arch/arm/mach-pxa/lubbock.c21
-rw-r--r--arch/arm/mach-pxa/mainstone.c22
-rw-r--r--arch/arm/mach-pxa/mfp-pxa2xx.c12
-rw-r--r--arch/arm/mach-pxa/mfp-pxa3xx.c21
-rw-r--r--arch/arm/mach-pxa/mioa701.c43
-rw-r--r--arch/arm/mach-pxa/palmld.c1
-rw-r--r--arch/arm/mach-pxa/palmtreo.c1
-rw-r--r--arch/arm/mach-pxa/palmz72.c24
-rw-r--r--arch/arm/mach-pxa/pxa25x.c25
-rw-r--r--arch/arm/mach-pxa/pxa27x.c25
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c25
-rw-r--r--arch/arm/mach-pxa/pxa95x.c20
-rw-r--r--arch/arm/mach-pxa/raumfeld.c1
-rw-r--r--arch/arm/mach-pxa/smemc.c29
-rw-r--r--arch/arm/mach-pxa/trizeps4.c1
-rw-r--r--arch/arm/mach-pxa/viper.c12
-rw-r--r--arch/arm/mach-pxa/vpac270.c1
-rw-r--r--arch/arm/mach-s3c2410/irq.c30
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c17
-rw-r--r--arch/arm/mach-s3c2410/pm.c13
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.c5
-rw-r--r--arch/arm/mach-s3c2412/irq.c2
-rw-r--r--arch/arm/mach-s3c2412/mach-jive.c19
-rw-r--r--arch/arm/mach-s3c2412/pm.c27
-rw-r--r--arch/arm/mach-s3c2412/s3c2412.c4
-rw-r--r--arch/arm/mach-s3c2416/irq.c2
-rw-r--r--arch/arm/mach-s3c2416/pm.c27
-rw-r--r--arch/arm/mach-s3c2416/s3c2416.c5
-rw-r--r--arch/arm/mach-s3c2440/mach-osiris.c18
-rw-r--r--arch/arm/mach-s3c2440/s3c2440.c8
-rw-r--r--arch/arm/mach-s3c2440/s3c2442.c6
-rw-r--r--arch/arm/mach-s3c2440/s3c244x-irq.c4
-rw-r--r--arch/arm/mach-s3c2440/s3c244x.c62
-rw-r--r--arch/arm/mach-s3c64xx/irq-pm.c18
-rw-r--r--arch/arm/mach-s5pv210/pm.c25
-rw-r--r--arch/arm/mach-sa1100/irq.c19
-rw-r--r--arch/arm/mach-shmobile/pm_runtime.c145
-rw-r--r--arch/arm/plat-omap/gpio.c35
-rw-r--r--arch/arm/plat-omap/omap_device.c23
-rw-r--r--arch/arm/plat-pxa/gpio.c17
-rw-r--r--arch/arm/plat-pxa/mfp.c1
-rw-r--r--arch/arm/plat-s3c24xx/dma.c68
-rw-r--r--arch/arm/plat-s3c24xx/irq-pm.c7
-rw-r--r--arch/arm/plat-s5p/irq-pm.c7
-rw-r--r--arch/arm/plat-samsung/include/plat/cpu.h6
-rw-r--r--arch/arm/plat-samsung/include/plat/pm.h6
-rw-r--r--arch/arm/vfp/vfpmodule.c19
-rw-r--r--arch/avr32/mach-at32ap/intc.c38
-rw-r--r--arch/blackfin/kernel/nmi.c30
-rw-r--r--arch/powerpc/include/asm/mpic.h3
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c28
-rw-r--r--arch/powerpc/platforms/powermac/pic.c42
-rw-r--r--arch/powerpc/sysdev/ipic.c36
-rw-r--r--arch/powerpc/sysdev/mpic.c48
-rw-r--r--arch/sh/Kconfig1
-rw-r--r--arch/sh/configs/apsh4ad0a_defconfig1
-rw-r--r--arch/sh/configs/sdk7786_defconfig1
-rw-r--r--arch/sh/kernel/cpu/shmobile/pm_runtime.c33
-rw-r--r--arch/unicore32/kernel/irq.c23
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/kernel/acpi/sleep.c5
-rw-r--r--arch/x86/kernel/apm_32.c4
-rw-r--r--drivers/base/Kconfig7
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/dd.c6
-rw-r--r--drivers/base/firmware_class.c5
-rw-r--r--drivers/base/platform.c138
-rw-r--r--drivers/base/power/Makefile4
-rw-r--r--drivers/base/power/clock_ops.c431
-rw-r--r--drivers/base/power/generic_ops.c39
-rw-r--r--drivers/base/power/main.c82
-rw-r--r--drivers/base/power/runtime.c29
-rw-r--r--drivers/base/power/sysfs.c4
-rw-r--r--drivers/base/power/wakeup.c1
-rw-r--r--drivers/base/sys.c202
-rw-r--r--drivers/xen/manage.c8
-rw-r--r--include/linux/device.h7
-rw-r--r--include/linux/kmod.h1
-rw-r--r--include/linux/platform_device.h63
-rw-r--r--include/linux/pm.h39
-rw-r--r--include/linux/pm_runtime.h42
-rw-r--r--include/linux/sysdev.h11
-rw-r--r--kernel/freezer.c4
-rw-r--r--kernel/kexec.c9
-rw-r--r--kernel/kmod.c16
-rw-r--r--kernel/power/Kconfig10
-rw-r--r--kernel/power/hibernate.c58
-rw-r--r--kernel/power/main.c1
-rw-r--r--kernel/power/power.h4
-rw-r--r--kernel/power/snapshot.c33
-rw-r--r--kernel/power/suspend.c10
-rw-r--r--kernel/sys.c3
118 files changed, 1393 insertions, 1667 deletions
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index 194ca446ac2..b464d12761b 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -158,3 +158,17 @@ Description:
successful, will make the kernel abort a subsequent transition
to a sleep state if any wakeup events are reported after the
write has returned.
+
+What: /sys/power/reserved_size
+Date: May 2011
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/power/reserved_size file allows user space to control
+ the amount of memory reserved for allocations made by device
+ drivers during the "device freeze" stage of hibernation. It can
+ be written a string representing a non-negative integer that
+ will be used as the amount of memory to reserve for allocations
+ made by device drivers' "freeze" callbacks, in bytes.
+
+ Reading from this file will display the current value, which is
+ set to 1 MB by default.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 492e81df296..f6a24e8aa11 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -460,14 +460,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
----------------------------
-What: The acpi_sleep=s4_nonvs command line option
-When: 2.6.37
-Files: arch/x86/kernel/acpi/sleep.c
-Why: superseded by acpi_sleep=nonvs
-Who: Rafael J. Wysocki <rjw@sisk.pl>
-
-----------------------------
-
What: PCI DMA unmap state API
When: August 2012
Why: PCI DMA unmap state API (include/linux/pci-dma.h) was replaced
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index cc85a927819..259037b873b 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -245,7 +245,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
acpi_sleep= [HW,ACPI] Sleep options
Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
- old_ordering, s4_nonvs, sci_force_enable }
+ old_ordering, nonvs, sci_force_enable }
See Documentation/power/video.txt for information on
s3_bios and s3_mode.
s3_beep is for debugging; it makes the PC's speaker beep
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 1971bcf48a6..88880839ece 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -279,11 +279,15 @@ When the system goes into the standby or memory sleep state, the phases are:
time.) Unlike the other suspend-related phases, during the prepare
phase the device tree is traversed top-down.
- The prepare phase uses only a bus callback. After the callback method
- returns, no new children may be registered below the device. The method
- may also prepare the device or driver in some way for the upcoming
- system power transition, but it should not put the device into a
- low-power state.
+ In addition to that, if device drivers need to allocate additional
+ memory to be able to hadle device suspend correctly, that should be
+ done in the prepare phase.
+
+ After the prepare callback method returns, no new children may be
+ registered below the device. The method may also prepare the device or
+ driver in some way for the upcoming system power transition (for
+ example, by allocating additional memory required for this purpose), but
+ it should not put the device into a low-power state.
2. The suspend methods should quiesce the device to stop it from performing
I/O. They also may save the device registers and put it into the
diff --git a/Documentation/power/notifiers.txt b/Documentation/power/notifiers.txt
index cf980709122..c2a4a346c0d 100644
--- a/Documentation/power/notifiers.txt
+++ b/Documentation/power/notifiers.txt
@@ -1,46 +1,41 @@
Suspend notifiers
- (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
-
-There are some operations that device drivers may want to carry out in their
-.suspend() routines, but shouldn't, because they can cause the hibernation or
-suspend to fail. For example, a driver may want to allocate a substantial amount
-of memory (like 50 MB) in .suspend(), but that shouldn't be done after the
-swsusp's memory shrinker has run.
-
-Also, there may be some operations, that subsystems want to carry out before a
-hibernation/suspend or after a restore/resume, requiring the system to be fully
-functional, so the drivers' .suspend() and .resume() routines are not suitable
-for this purpose. For example, device drivers may want to upload firmware to
-their devices after a restore from a hibernation image, but they cannot do it by
-calling request_firmware() from their .resume() routines (user land processes
-are frozen at this point). The solution may be to load the firmware into
-memory before processes are frozen and upload it from there in the .resume()
-routine. Of course, a hibernation notifier may be used for this purpose.
-
-The subsystems that have such needs can register suspend notifiers that will be
-called upon the following events by the suspend core:
+ (C) 2007-2011 Rafael J. Wysocki <rjw@sisk.pl>, GPL
+
+There are some operations that subsystems or drivers may want to carry out
+before hibernation/suspend or after restore/resume, but they require the system
+to be fully functional, so the drivers' and subsystems' .suspend() and .resume()
+or even .prepare() and .complete() callbacks are not suitable for this purpose.
+For example, device drivers may want to upload firmware to their devices after
+resume/restore, but they cannot do it by calling request_firmware() from their
+.resume() or .complete() routines (user land processes are frozen at these
+points). The solution may be to load the firmware into memory before processes
+are frozen and upload it from there in the .resume() routine.
+A suspend/hibernation notifier may be used for this purpose.
+
+The subsystems or drivers having such needs can register suspend notifiers that
+will be called upon the following events by the PM core:
PM_HIBERNATION_PREPARE The system is going to hibernate or suspend, tasks will
be frozen immediately.
PM_POST_HIBERNATION The system memory state has been restored from a
- hibernation image or an error occurred during the
- hibernation. Device drivers' .resume() callbacks have
+ hibernation image or an error occurred during
+ hibernation. Device drivers' restore callbacks have
been executed and tasks have been thawed.
PM_RESTORE_PREPARE The system is going to restore a hibernation image.
- If all goes well the restored kernel will issue a
+ If all goes well, the restored kernel will issue a
PM_POST_HIBERNATION notification.
-PM_POST_RESTORE An error occurred during the hibernation restore.
- Device drivers' .resume() callbacks have been executed
+PM_POST_RESTORE An error occurred during restore from hibernation.
+ Device drivers' restore callbacks have been executed
and tasks have been thawed.
-PM_SUSPEND_PREPARE The system is preparing for a suspend.
+PM_SUSPEND_PREPARE The system is preparing for suspend.
PM_POST_SUSPEND The system has just resumed or an error occurred during
- the suspend. Device drivers' .resume() callbacks have
- been executed and tasks have been thawed.
+ suspend. Device drivers' resume callbacks have been
+ executed and tasks have been thawed.
It is generally assumed that whatever the notifiers do for
PM_HIBERNATION_PREPARE, should be undone for PM_POST_HIBERNATION. Analogously,
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 113085a7712..7aa4262ada7 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -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.
@@ -43,8 +42,6 @@
* @protect: Save for VIC_PROTECT.
*/
struct vic_device {
- struct sys_device sysdev;
-
void __iomem *base;
int irq;
u32 resume_sources;
@@ -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 */
/**
@@ -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);
@@ -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);
@@ -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,
};
/**
@@ -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;
}
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index 883f6be5117..d5adaae5ee2 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/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);
diff --git a/arch/arm/kernel/leds.c b/arch/arm/kernel/leds.c
index 31a316c1777..0f107dcb034 100644
--- a/arch/arm/kernel/leds.c
+++ b/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_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;
@@ -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;
}
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 1ff46cabc7e..cb634c3e28e 100644
--- a/arch/arm/kernel/time.c
+++ b/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>
@@ -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)
{
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c
index 10d917d9e3a..8755ca8dd48 100644
--- a/arch/arm/mach-exynos4/pm.c
+++ b/arch/arm/mach-exynos4/pm.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
@@ -372,7 +373,27 @@ void exynos4_scu_enable(void __iomem *scu_base)
flush_cache_all();
}
-static int exynos4_pm_resume(struct sys_device *dev)
+static struct sysdev_driver exynos4_pm_driver = {
+ .add = exynos4_pm_add,
+};
+
+static __init int exynos4_pm_drvinit(void)
+{
+ unsigned int tmp;
+
+ s3c_pm_init();
+
+ /* All wakeup disable */
+
+ tmp = __raw_readl(S5P_WAKEUP_MASK);
+ tmp |= ((0xFF << 8) | (0x1F << 1));
+ __raw_writel(tmp, S5P_WAKEUP_MASK);
+
+ return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
+}
+arch_initcall(exynos4_pm_drvinit);
+
+static void exynos4_pm_resume(void)
{
/* For release retention */
@@ -394,27 +415,15 @@ static int exynos4_pm_resume(struct sys_device *dev)
/* enable L2X0*/
writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
#endif
-
- return 0;
}
-static struct sysdev_driver exynos4_pm_driver = {
- .add = exynos4_pm_add,
+static struct syscore_ops exynos4_pm_syscore_ops = {
.resume = exynos4_pm_resume,
};
-static __init int exynos4_pm_drvinit(void)
+static __init int exynos4_pm_syscore_init(void)
{
- unsigned int tmp;
-
- s3c_pm_init();
-
- /* All wakeup disable */
-
- tmp = __raw_readl(S5P_WAKEUP_MASK);
- tmp |= ((0xFF << 8) | (0x1F << 1));
- __raw_writel(tmp, S5P_WAKEUP_MASK);
-
- return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
+ register_syscore_ops(&exynos4_pm_syscore_ops);
+ return 0;
}
-arch_initcall(exynos4_pm_drvinit);
+arch_initcall(exynos4_pm_syscore_init);
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 980803ff348..d3e96451529 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -24,7 +24,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/string.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/amba/bus.h>
#include <linux/amba/kmi.h>
#include <linux/clocksource.h>
@@ -180,13 +180,13 @@ static void __init ap_init_irq(void)
#ifdef CONFIG_PM
static unsigned long ic_irq_enable;
-static int irq_suspend(struct sys_device *dev, pm_message_t state)
+static int irq_suspend(void)
{
ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
return 0;
}
-static int irq_resume(struct sys_device *dev)
+static void irq_resume(void)
{
/* disable all irq sources */
writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
@@ -194,33 +194,25 @@ static int irq_resume(struct sys_device *dev)
writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
- return 0;
}
#else
#define irq_suspend NULL
#define irq_resume NULL
#endif
-static struct sysdev_class irq_class = {
- .name = "irq",
+static struct syscore_ops irq_syscore_ops = {
.suspend = irq_suspend,
.resume = irq_resume,
};
-static struct sys_device irq_device = {
- .id = 0,
- .cls = &irq_class,
-};
-
-static int __init irq_init_sysfs(void)
+static int __init irq_syscore_init(void)
{
- int ret = sysdev_class_register(&irq_class);
- if (ret == 0)
- ret = sysdev_register(&irq_device);
- return ret;
+ register_syscore_ops(&irq_syscore_ops);
+
+ return 0;
}
-device_initcall(irq_init_sysfs);
+device_initcall(irq_syscore_init);
/*
* Flash handling.
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
index 6588c22b8a6..fe31d933f0e 100644
--- a/arch/arm/mach-omap1/pm_bus.c
+++ b/arch/arm/mach-omap1/pm_bus.c
@@ -24,75 +24,50 @@
#ifdef CONFIG_PM_RUNTIME
static int omap1_pm_runtime_suspend(struct device *dev)
{
- struct clk *iclk, *fclk;
- int ret = 0;
+ int ret;
dev_dbg(dev, "%s\n", __func__);
ret = pm_generic_runtime_suspend(dev);
+ if (ret)
+ return ret;
- fclk = clk_get(dev, "fck");
- if (!IS_ERR(fclk)) {
- clk_disable(fclk);
- clk_put(fclk);
- }
-
- iclk = clk_get(dev, "ick");
- if (!IS_ERR(iclk)) {
- clk_disable(iclk);
- clk_put(iclk);
+ ret = pm_runtime_clk_suspend(dev);
+ if (ret) {
+ pm_generic_runtime_resume(dev);
+ return ret;
}
return 0;
-};
+}
static int omap1_pm_runtime_resume(struct device *dev)
{
- struct clk *iclk, *fclk;
-
dev_dbg(dev, "%s\n", __func__);
- iclk = clk_get(dev, "ick");
- if (!IS_ERR(iclk)) {
- clk_enable(iclk);
- clk_put(iclk);
- }
+ pm_runtime_clk_resume(dev);
+ return pm_generic_runtime_resume(dev);
+}
- fclk = clk_get(dev, "fck");
- if (!IS_ERR(fclk)) {
- clk_enable(fclk);
- clk_put(fclk);
- }
+static struct dev_power_domain default_power_domain = {
+ .ops = {
+ .runtime_suspend = omap1_pm_runtime_suspend,
+ .runtime_resume = omap1_pm_runtime_resume,
+ USE_PLATFORM_PM_SLEEP_OPS
+ },
+};
- return pm_generic_runtime_resume(dev);
+static struct pm_clk_notifier_block platform_bus_notifier = {
+ .pwr_domain = &default_power_domain,
+ .con_ids = { "ick", "fck", NULL, },
};
static int __init omap1_pm_runtime_init(void)
{
- const struct dev_pm_ops *pm;
- struct dev_pm_ops *omap_pm;
-
if (!cpu_class_is_omap1())
return -ENODEV;
- pm = platform_bus_get_pm_ops();
- if (!pm) {
- pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
- __func__);
- return -ENODEV;
- }
-
- omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
- if (!omap_pm) {
- pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
- __func__);
- return -ENOMEM;
- }
-
- omap_pm->runtime_suspend = omap1_pm_runtime_suspend;
- omap_pm->runtime_resume = omap1_pm_runtime_resume;
-
- platform_bus_set_pm_ops(omap_pm);
+ pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
return 0;
}
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 512b1520445..66dfbccacd2 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -59,10 +59,10 @@ endif
# Power Management
ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o
obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \
- cpuidle34xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o
+ cpuidle34xx.o
+obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
diff --git a/arch/arm/mach-omap2/pm_bus.c b/arch/arm/mach-omap2/pm_bus.c
deleted file mode 100644
index 5acd2ab298b..00000000000
--- a/arch/arm/mach-omap2/pm_bus.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Runtime PM support code for OMAP
- *
- * Author: Kevin Hilman, Deep Root Systems, LLC
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-
-#include <plat/omap_device.h>
-#include <plat/omap-pm.h>
-
-#ifdef CONFIG_PM_RUNTIME
-static int omap_pm_runtime_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- int r, ret = 0;
-
- dev_dbg(dev, "%s\n", __func__);
-
- ret = pm_generic_runtime_suspend(dev);
-
- if (!ret && dev->parent == &omap_device_parent) {
- r = omap_device_idle(pdev);
- WARN_ON(r);
- }
-
- return ret;
-};
-
-static int omap_pm_runtime_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- int r;
-
- dev_dbg(dev, "%s\n", __func__);
-
- if (dev->parent == &omap_device_parent) {
- r = omap_device_enable(pdev);
- WARN_ON(r);
- }
-
- return pm_generic_runtime_resume(dev);
-};
-#else
-#define omap_pm_runtime_suspend NULL
-#define omap_pm_runtime_resume NULL
-#endif /* CONFIG_PM_RUNTIME */
-
-static int __init omap_pm_runtime_init(void)
-{
- const struct dev_pm_ops *pm;
- struct dev_pm_ops *omap_pm;
-
- pm = platform_bus_get_pm_ops();
- if (!pm) {
- pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
- __func__);
- return -ENODEV;
- }
-
- omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
- if (!omap_pm) {
- pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
- __func__);
- return -ENOMEM;
- }
-
- omap_pm->runtime_suspend = omap_pm_runtime_suspend;
- omap_pm->runtime_resume = omap_pm_runtime_resume;
-
- platform_bus_set_pm_ops(omap_pm);
-
- return 0;
-}
-core_initcall(omap_pm_runtime_init);
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index bfbecec6d05..810a982a66f 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -15,7 +15,6 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/bitops.h>
diff --git a/arch/arm/mach-pxa/clock-pxa2xx.c b/arch/arm/mach-pxa/clock-pxa2xx.c
index 1ce09044849..1d5859d9a0e 100644
--- a/arch/arm/mach-pxa/clock-pxa2xx.c
+++ b/arch/arm/mach-pxa/clock-pxa2xx.c
@@ -9,7 +9,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <mach/pxa2xx-regs.h>
@@ -33,32 +33,22 @@ const struct clkops clk_pxa2xx_cken_ops = {
#ifdef CONFIG_PM
static uint32_t saved_cken;
-static int pxa2xx_clock_suspend(struct sys_device *d, pm_message_t state)
+static int pxa2xx_clock_suspend(void)
{
saved_cken = CKEN;
return 0;
}
-static int pxa2xx_clock_resume(struct sys_device *d)
+static void pxa2xx_clock_resume(void)
{
CKEN = saved_cken;
- return 0;
}
#else
#define pxa2xx_clock_suspend NULL
#define pxa2xx_clock_resume NULL
#endif
-struct sysdev_class pxa2xx_clock_sysclass = {
- .name = "pxa2xx-clock",
+struct syscore_ops pxa2xx_clock_syscore_ops = {
.suspend = pxa2xx_clock_suspend,
.resume = pxa2xx_clock_resume,
};
-
-static int __init pxa2xx_clock_init(void)
-{
- if (cpu_is_pxa2xx())
- return sysdev_class_register(&pxa2xx_clock_sysclass);
- return 0;
-}
-postcore_initcall(pxa2xx_clock_init);
diff --git a/arch/arm/mach-pxa/clock-pxa3xx.c b/arch/arm/mach-pxa/clock-pxa3xx.c
index 3f864cd0bd2..2a37a9a8f62 100644
--- a/arch/arm/mach-pxa/clock-pxa3xx.c
+++ b/arch/arm/mach-pxa/clock-pxa3xx.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/syscore_ops.h>
#include <mach/smemc.h>
#include <mach/pxa3xx-regs.h>
@@ -182,7 +183,7 @@ const struct clkops clk_pxa3xx_pout_ops = {
static uint32_t cken[2];
static uint32_t accr;
-static int pxa3xx_clock_suspend(struct sys_device *d, pm_message_t state)
+static int pxa3xx_clock_suspend(void)
{
cken[0] = CKENA;
cken[1] = CKENB;
@@ -190,28 +191,18 @@ static int pxa3xx_clock_suspend(struct sys_device *d, pm_message_t state)
return 0;
}
-static int pxa3xx_clock_resume(struct sys_device *d)
+static void pxa3xx_clock_resume(void)
{
ACCR = accr;
CKENA = cken[0];
CKENB = cken[1];
- return 0;
}
#else
#define pxa3xx_clock_suspend NULL
#define pxa3xx_clock_resume NULL
#endif
-struct sysdev_class pxa3xx_clock_sysclass = {
- .name = "pxa3xx-clock",
+struct syscore_ops pxa3xx_clock_syscore_ops = {
.suspend = pxa3xx_clock_suspend,
.resume = pxa3xx_clock_resume,
};
-
-static int __init pxa3xx_clock_init(void)
-{
- if (cpu_is_pxa3xx() || cpu_is_pxa95x())
- return sysdev_class_register(&pxa3xx_clock_sysclass);
- return 0;
-}
-postcore_initcall(pxa3xx_clock_init);
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index f9f349a21b5..1f2fb9c43f0 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -1,5 +1,5 @@
#include <linux/clkdev.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
struct clkops {
void (*enable)(struct clk *);
@@ -54,7 +54,7 @@ extern const struct clkops clk_pxa2xx_cken_ops;
void clk_pxa2xx_cken_enable(struct clk *clk);
void clk_pxa2xx_cken_disable(struct clk *clk);
-extern struct sysdev_class pxa2xx_clock_sysclass;
+extern struct syscore_ops pxa2xx_clock_syscore_ops;
#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
#define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay) \
@@ -74,5 +74,6 @@ extern const struct clkops clk_pxa3xx_smemc_ops;
extern void clk_pxa3xx_cken_enable(struct clk *);
extern void clk_pxa3xx_cken_disable(struct clk *);
-extern struct sysdev_class pxa3xx_clock_sysclass;
+extern struct syscore_ops pxa3xx_clock_syscore_ops;
+
#endif
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index b88d601a809..13518a70539 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -10,7 +10,6 @@
*/
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/delay.h>
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index 8225e2e58c6..a1099678247 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -10,7 +10,7 @@
*/
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/irq.h>
#include <linux/gpio.h>
@@ -388,7 +388,7 @@ static inline void cmx2xx_init_display(void) {}
#ifdef CONFIG_PM
static unsigned long sleep_save_msc[10];
-static int cmx2xx_suspend(struct sys_device *dev, pm_message_t state)
+static int cmx2xx_suspend(void)
{
cmx2xx_pci_suspend();
@@ -412,7 +412,7 @@ static int cmx2xx_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
-static int cmx2xx_resume(struct sys_device *dev)
+static void cmx2xx_resume(void)
{
cmx2xx_pci_resume();
@@ -420,27 +420,18 @@ static int cmx2xx_resume(struct sys_device *dev)
__raw_writel(sleep_save_msc[0], MSC0);
__raw_writel(sleep_save_msc[1], MSC1);
__raw_writel(sleep_save_msc[2], MSC2);
-
- return 0;
}
-static struct sysdev_class cmx2xx_pm_sysclass = {
- .name = "pm",
+static struct syscore_ops cmx2xx_pm_syscore_ops = {
.resume = cmx2xx_resume,
.suspend = cmx2xx_suspend,
};
-static struct sys_device cmx2xx_pm_device = {
- .cls = &cmx2xx_pm_sysclass,
-};
-
static int __init cmx2xx_pm_init(void)
{
- int error;
- error = sysdev_class_register(&cmx2xx_pm_sysclass);
- if (error == 0)
- error = sysdev_register(&cmx2xx_pm_device);
- return error;
+ register_syscore_ops(&cmx2xx_pm_syscore_ops);
+
+ return 0;
}
#else
static int __init cmx2xx_pm_init(void) { return 0; }
diff --git a/arch/arm/mach-pxa/colibri-evalboard.c b/arch/arm/mach-pxa/colibri-evalboard.c
index 81c3c433e2d..d28e802e244 100644
--- a/arch/arm/mach-pxa/colibri-evalboard.c
+++ b/arch/arm/mach-pxa/colibri-evalboard.c
@@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <asm/mach-types.h>
diff --git a/arch/arm/mach-pxa/colibri-pxa270-income.c b/arch/arm/mach-pxa/colibri-pxa270-income.c
index 44c1b77ece6..80538b8806e 100644
--- a/arch/arm/mach-pxa/colibri-pxa270-income.c
+++ b/arch/arm/mach-pxa/colibri-pxa270-income.c
@@ -22,7 +22,6 @@
#include <linux/platform_device.h>
#include <linux/pwm_backlight.h>
#include <linux/i2c/pxa-i2c.h>
-#include <linux/sysdev.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c
index 6fc5d328ba7..7545a48ed88 100644
--- a/arch/arm/mach-pxa/colibri-pxa270.c
+++ b/arch/arm/mach-pxa/colibri-pxa270.c
@@ -17,7 +17,6 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
#include <linux/ucb1400.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index a079d8baa45..e6c9344a95a 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -61,10 +61,10 @@ extern unsigned pxa3xx_get_clk_frequency_khz(int);
#define pxa3xx_get_clk_frequency_khz(x) (0)
#endif
-extern struct sysdev_class pxa_irq_sysclass;
-extern struct sysdev_class pxa_gpio_sysclass;
-extern struct sysdev_class pxa2xx_mfp_sysclass;
-extern struct sysdev_class pxa3xx_mfp_sysclass;
+extern struct syscore_ops pxa_irq_syscore_ops;
+extern struct syscore_ops pxa_gpio_syscore_ops;
+extern struct syscore_ops pxa2xx_mfp_syscore_ops;
+extern struct syscore_ops pxa3xx_mfp_syscore_ops;
void __init pxa_set_ffuart_info(void *info);
void __init pxa_set_btuart_info(void *info);
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 6251e3f5c62..32ed551bf9c 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -15,7 +15,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <linux/irq.h>
@@ -183,7 +183,7 @@ void __init pxa_init_irq(int irq_nr, set_wake_t fn)
static unsigned long saved_icmr[MAX_INTERNAL_IRQS/32];
static unsigned long saved_ipr[MAX_INTERNAL_IRQS];
-static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
+static int pxa_irq_suspend(void)
{
int i;
@@ -202,7 +202,7 @@ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
-static int pxa_irq_resume(struct sys_device *dev)
+static void pxa_irq_resume(void)
{
int i;
@@ -218,22 +218,13 @@ static int pxa_irq_resume(struct sys_device *dev)
__raw_writel(saved_ipr[i], IRQ_BASE + IPR(i));
__raw_writel(1, IRQ_BASE + ICCR);
- return 0;
}
#else
#define pxa_irq_suspend NULL
#define pxa_irq_resume NULL
#endif
-struct sysdev_class pxa_irq_sysclass = {
- .name = "irq",
+struct syscore_ops pxa_irq_syscore_ops = {
.suspend = pxa_irq_suspend,
.resume = pxa_irq_resume,
};
-
-static int __init pxa_irq_init(void)
-{
- return sysdev_class_register(&pxa_irq_sysclass);
-}
-
-core_initcall(pxa_irq_init);
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index f5de541725b..6cf8180bf5b 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -15,7 +15,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/bitops.h>
@@ -159,30 +159,22 @@ static void __init lpd270_init_irq(void)
#ifdef CONFIG_PM
-static int lpd270_irq_resume(struct sys_device *dev)
+static void lpd270_irq_resume(void)
{
__raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
- return 0;
}
-static struct sysdev_class lpd270_irq_sysclass = {
- .name = "cpld_irq",
+static struct syscore_ops lpd270_irq_syscore_ops = {
.resume = lpd270_irq_resume,
};
-static struct sys_device lpd270_irq_device = {
- .cls = &lpd270_irq_sysclass,
-};
-
static int __init lpd270_irq_device_init(void)
{
- int ret = -ENODEV;
if (machine_is_logicpd_pxa270()) {
- ret = sysdev_class_register(&lpd270_irq_sysclass);
- if (ret == 0)
- ret = sysdev_register(&lpd270_irq_device);
+ register_syscore_ops(&lpd270_irq_syscore_ops);
+ return 0;
}
- return ret;
+ return -ENODEV;
}
device_initcall(lpd270_irq_device_init);
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 3ede978c83d..e10ddb82714 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -15,7 +15,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/major.h>
#include <linux/fb.h>
#include <linux/interrupt.h>
@@ -176,31 +176,22 @@ static void __init lubbock_init_irq(void)
#ifdef CONFIG_PM
-static int lubbock_irq_resume(struct sys_device *dev)
+static void lubbock_irq_resume(void)
{
LUB_IRQ_MASK_EN = lubbock_irq_enabled;
- return 0;
}
-static struct sysdev_class lubbock_irq_sysclass = {
- .name = "cpld_irq",
+static struct syscore_ops lubbock_irq_syscore_ops = {
.resume = lubbock_irq_resume,
};
-static struct sys_device lubbock_irq_device = {
- .cls = &lubbock_irq_sysclass,
-};
-
static int __init lubbock_irq_device_init(void)
{
- int ret = -ENODEV;
-
if (machine_is_lubbock()) {
- ret = sysdev_class_register(&lubbock_irq_sysclass);
- if (ret == 0)
- ret = sysdev_register(&lubbock_irq_device);
+ register_syscore_ops(&lubbock_irq_syscore_ops);
+ return 0;
}
- return ret;
+ return -ENODEV;
}
device_initcall(lubbock_irq_device_init);
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 95163baca29..3479e2b3b51 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -15,7 +15,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/bitops.h>
@@ -185,31 +185,21 @@ static void __init mainstone_init_irq(void)
#ifdef CONFIG_PM
-static int mainstone_irq_resume(struct sys_device *dev)
+static void mainstone_irq_resume(void)
{
MST_INTMSKENA = mainstone_irq_enabled;
- return 0;
}
-static struct sysdev_class mainstone_irq_sysclass = {
- .name = "cpld_irq",
+static struct syscore_ops mainstone_irq_syscore_ops = {
.resume = mainstone_irq_resume,
};
-static struct sys_device mainstone_irq_device = {
- .cls = &mainstone_irq_sysclass,
-};
-
static int __init mainstone_irq_device_init(void)
{
- int ret = -ENODEV;
+ if (machine_is_mainstone())
+ register_syscore_ops(&mainstone_irq_syscore_ops);
- if (machine_is_mainstone()) {
- ret = sysdev_class_register(&mainstone_irq_sysclass);
- if (ret == 0)
- ret = sysdev_register(&mainstone_irq_device);
- }
- return ret;
+ return 0;
}
device_initcall(mainstone_irq_device_init);
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
index 1d1419b7345..87ae3129f4f 100644
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
@@ -16,7 +16,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <mach/gpio.h>
#include <mach/pxa2xx-regs.h>
@@ -338,7 +338,7 @@ static unsigned long saved_gafr[2][4];
static unsigned long saved_gpdr[4];
static unsigned long saved_pgsr[4];
-static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state)
+static int pxa2xx_mfp_suspend(void)
{
int i;
@@ -365,7 +365,7 @@ static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state)
return 0;
}
-static int pxa2xx_mfp_resume(struct sys_device *d)
+static void pxa2xx_mfp_resume(void)
{
int i;
@@ -376,15 +376,13 @@ static int pxa2xx_mfp_resume(struct sys_device *d)
PGSR(i) = saved_pgsr[i];
}
PSSR = PSSR_RDH | PSSR_PH;
- return 0;
}
#else
#define pxa2xx_mfp_suspend NULL
#define pxa2xx_mfp_resume NULL
#endif
-struct sysdev_class pxa2xx_mfp_sysclass = {
- .name = "mfp",
+struct syscore_ops pxa2xx_mfp_syscore_ops = {
.suspend = pxa2xx_mfp_suspend,
.resume = pxa2xx_mfp_resume,
};
@@ -409,6 +407,6 @@ static int __init pxa2xx_mfp_init(void)
for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++)
gpdr_lpm[i] = GPDR(i * 32);
- return sysdev_class_register(&pxa2xx_mfp_sysclass);
+ return 0;
}
postcore_initcall(pxa2xx_mfp_init);
diff --git a/arch/arm/mach-pxa/mfp-pxa3xx.c b/arch/arm/mach-pxa/mfp-pxa3xx.c
index 7a270eecd48..89863a01ecd 100644
--- a/arch/arm/mach-pxa/mfp-pxa3xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa3xx.c
@@ -17,7 +17,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <mach/hardware.h>
#include <mach/mfp-pxa3xx.h>
@@ -31,13 +31,13 @@
* a pull-down mode if they're an active low chip select, and we're
* just entering standby.
*/
-static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state)
+static int pxa3xx_mfp_suspend(void)
{
mfp_config_lpm();
return 0;
}
-static int pxa3xx_mfp_resume(struct sys_device *d)
+static void pxa3xx_mfp_resume(void)
{
mfp_config_run();
@@ -47,24 +47,13 @@ static int pxa3xx_mfp_resume(struct sys_device *d)
* preserve them here in case they will be referenced later
*/
ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
- return 0;
}
#else
#define pxa3xx_mfp_suspend NULL
#define pxa3xx_mfp_resume NULL
#endif
-struct sysdev_class pxa3xx_mfp_sysclass = {
- .name = "mfp",
+struct syscore_ops pxa3xx_mfp_syscore_ops = {
.suspend = pxa3xx_mfp_suspend,
- .resume = pxa3xx_mfp_resume,
+ .resume = pxa3xx_mfp_resume,
};
-
-static int __init mfp_init_devicefs(void)
-{
- if (cpu_is_pxa3xx())
- return sysdev_class_register(&pxa3xx_mfp_sysclass);
-
- return 0;
-}
-postcore_initcall(mfp_init_devicefs);
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 23925db8ff7..e3470137c93 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -22,7 +22,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/gpio_keys.h>
@@ -488,7 +488,7 @@ static void install_bootstrap(void)
}
-static int mioa701_sys_suspend(struct sys_device *sysdev, pm_message_t state)
+static int mioa701_sys_suspend(void)
{
int i = 0, is_bt_on;
u32 *mem_resume_vector = phys_to_virt(RESUME_VECTOR_ADDR);
@@ -514,7 +514,7 @@ static int mioa701_sys_suspend(struct sys_device *sysdev, pm_message_t state)
return 0;
}
-static int mioa701_sys_resume(struct sys_device *sysdev)
+static void mioa701_sys_resume(void)
{
int i = 0;
u32 *mem_resume_vector = phys_to_virt(RESUME_VECTOR_ADDR);
@@ -527,43 +527,18 @@ static int mioa701_sys_resume(struct sys_device *sysdev)
*mem_resume_enabler = save_buffer[i++];
*mem_resume_bt = save_buffer[i++];
*mem_resume_unknown = save_buffer[i++];
-
- return 0;
}
-static struct sysdev_class mioa701_sysclass = {
- .name = "mioa701",
-};
-
-static struct sys_device sysdev_bootstrap = {
- .cls = &mioa701_sysclass,
-};
-
-static struct sysdev_driver driver_bootstrap = {
- .suspend = &mioa701_sys_suspend,
- .resume = &mioa701_sys_resume,
+static struct syscore_ops mioa701_syscore_ops = {
+ .suspend = mioa701_sys_suspend,
+ .resume = mioa701_sys_resume,
};
static int __init bootstrap_init(void)
{
- int rc;
int save_size = mioa701_bootstrap_lg + (sizeof(u32) * 3);
- rc = sysdev_class_register(&mioa701_sysclass);
- if (rc) {
- printk(KERN_ERR "Failed registering mioa701 sys class\n");
- return -ENODEV;
- }
- rc = sysdev_register(&sysdev_bootstrap);
- if (rc) {
- printk(KERN_ERR "Failed registering mioa701 sys device\n");
- return -ENODEV;
- }
- rc = sysdev_driver_register(&mioa701_sysclass, &driver_bootstrap);
- if (rc) {
- printk(KERN_ERR "Failed registering PMU sys driver\n");
- return -ENODEV;
- }
+ register_syscore_ops(&mioa701_syscore_ops);
save_buffer = kmalloc(save_size, GFP_KERNEL);
if (!save_buffer)
@@ -576,9 +551,7 @@ static int __init bootstrap_init(void)
static void bootstrap_exit(void)
{
kfree(save_buffer);
- sysdev_driver_unregister(&mioa701_sysclass, &driver_bootstrap);
- sysdev_unregister(&sysdev_bootstrap);
- sysdev_class_unregister(&mioa701_sysclass);
+ unregister_syscore_ops(&mioa701_syscore_ops);
printk(KERN_CRIT "Unregistering mioa701 suspend will hang next"
"resume !!!\n");
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index a6f898cbfac..4061ecddee7 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -24,7 +24,6 @@
#include <linux/gpio.h>
#include <linux/wm97xx.h>
#include <linux/power_supply.h>
-#include <linux/sysdev.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index 8aadad55fbe..20d1b18b173 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -25,7 +25,6 @@
#include <linux/pwm_backlight.h>
#include <linux/gpio.h>
#include <linux/power_supply.h>
-#include <linux/sysdev.h>
#include <linux/w1-gpio.h>
#include <asm/mach-types.h>
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 3b8a4f37dbb..65f24f0b77e 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -19,7 +19,7 @@
*/
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
@@ -233,9 +233,9 @@ static struct palmz72_resume_info palmz72_resume_info = {
static unsigned long store_ptr;
-/* sys_device for Palm Zire 72 PM */
+/* syscore_ops for Palm Zire 72 PM */
-static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg)
+static int palmz72_pm_suspend(void)
{
/* setup the resume_info struct for the original bootloader */
palmz72_resume_info.resume_addr = (u32) cpu_resume;
@@ -249,31 +249,23 @@ static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg)
return 0;
}
-static int palmz72_pm_resume(struct sys_device *dev)
+static void palmz72_pm_resume(void)
{
*PALMZ72_SAVE_DWORD = store_ptr;
- return 0;
}
-static struct sysdev_class palmz72_pm_sysclass = {
- .name = "palmz72_pm",
+static struct syscore_ops palmz72_pm_syscore_ops = {
.suspend = palmz72_pm_suspend,
.resume = palmz72_pm_resume,
};
-static struct sys_device palmz72_pm_device = {
- .cls = &palmz72_pm_sysclass,
-};
-
static int __init palmz72_pm_init(void)
{
- int ret = -ENODEV;
if (machine_is_palmz72()) {
- ret = sysdev_class_register(&palmz72_pm_sysclass);
- if (ret == 0)
- ret = sysdev_register(&palmz72_pm_device);
+ register_syscore_ops(&palmz72_pm_syscore_ops);
+ return 0;
}
- return ret;
+ return -ENODEV;
}
device_initcall(palmz72_pm_init);
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index a4af8c52d7e..fed363cec9c 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -21,7 +21,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/irq.h>
#include <asm/mach/map.h>
@@ -350,21 +350,9 @@ static struct platform_device *pxa25x_devices[] __initdata = {
&pxa_device_asoc_platform,
};
-static struct sys_device pxa25x_sysdev[] = {
- {
- .cls = &pxa_irq_sysclass,
- }, {
- .cls = &pxa2xx_mfp_sysclass,
- }, {
- .cls = &pxa_gpio_sysclass,
- }, {
- .cls = &pxa2xx_clock_sysclass,
- }
-};
-
static int __init pxa25x_init(void)
{
- int i, ret = 0;
+ int ret = 0;
if (cpu_is_pxa25x()) {
@@ -377,11 +365,10 @@ static int __init pxa25x_init(void)
pxa25x_init_pm();
- for (i = 0; i < ARRAY_SIZE(pxa25x_sysdev); i++) {
- ret = sysdev_register(&pxa25x_sysdev[i]);
- if (ret)
- pr_err("failed to register sysdev[%d]\n", i);
- }
+ register_syscore_ops(&pxa_irq_syscore_ops);
+ register_syscore_ops(&pxa2xx_mfp_syscore_ops);
+ register_syscore_ops(&pxa_gpio_syscore_ops);
+ register_syscore_ops(&pxa2xx_clock_syscore_ops);
ret = platform_add_devices(pxa25x_devices,
ARRAY_SIZE(pxa25x_devices));
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 909756eaf4b..2fecbec58d8 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -16,7 +16,7 @@
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/i2c/pxa-i2c.h>
@@ -428,21 +428,9 @@ static struct platform_device *devices[] __initdata = {
&pxa27x_device_pwm1,
};
-static struct sys_device pxa27x_sysdev[] = {
- {
- .cls = &pxa_irq_sysclass,
- }, {
- .cls = &pxa2xx_mfp_sysclass,
- }, {
- .cls = &pxa_gpio_sysclass,
- }, {
- .cls = &pxa2xx_clock_sysclass,
- }
-};
-
static int __init pxa27x_init(void)
{
- int i, ret = 0;
+ int ret = 0;
if (cpu_is_pxa27x()) {
@@ -455,11 +443,10 @@ static int __init pxa27x_init(void)
pxa27x_init_pm();
- for (i = 0; i < ARRAY_SIZE(pxa27x_sysdev); i++) {
- ret = sysdev_register(&pxa27x_sysdev[i]);
- if (ret)
- pr_err("failed to register sysdev[%d]\n", i);
- }
+ register_syscore_ops(&pxa_irq_syscore_ops);
+ register_syscore_ops(&pxa2xx_mfp_syscore_ops);
+ register_syscore_ops(&pxa_gpio_syscore_ops);
+ register_syscore_ops(&pxa2xx_clock_syscore_ops);
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 8dd10739115..8521d7d6f1d 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/i2c/pxa-i2c.h>
#include <asm/mach/map.h>
@@ -427,21 +427,9 @@ static struct platform_device *devices[] __initdata = {
&pxa27x_device_pwm1,
};
-static struct sys_device pxa3xx_sysdev[] = {
- {
- .cls = &pxa_irq_sysclass,
- }, {
- .cls = &pxa3xx_mfp_sysclass,
- }, {
- .cls = &pxa_gpio_sysclass,
- }, {
- .cls = &pxa3xx_clock_sysclass,
- }
-};
-
static int __init pxa3xx_init(void)
{
- int i, ret = 0;
+ int ret = 0;
if (cpu_is_pxa3xx()) {
@@ -462,11 +450,10 @@ static int __init pxa3xx_init(void)
pxa3xx_init_pm();
- for (i = 0; i < ARRAY_SIZE(pxa3xx_sysdev); i++) {
- ret = sysdev_register(&pxa3xx_sysdev[i]);
- if (ret)
- pr_err("failed to register sysdev[%d]\n", i);
- }
+ register_syscore_ops(&pxa_irq_syscore_ops);
+ register_syscore_ops(&pxa3xx_mfp_syscore_ops);
+ register_syscore_ops(&pxa_gpio_syscore_ops);
+ register_syscore_ops(&pxa3xx_clock_syscore_ops);
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index 23b229bd06e..ecc82a330fa 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -18,7 +18,7 @@
#include <linux/i2c/pxa-i2c.h>
#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
@@ -260,16 +260,6 @@ static struct platform_device *devices[] __initdata = {
&pxa27x_device_pwm1,
};
-static struct sys_device pxa95x_sysdev[] = {
- {
- .cls = &pxa_irq_sysclass,
- }, {
- .cls = &pxa_gpio_sysclass,
- }, {
- .cls = &pxa3xx_clock_sysclass,
- }
-};
-
static int __init pxa95x_init(void)
{
int ret = 0, i;
@@ -293,11 +283,9 @@ static int __init pxa95x_init(void)
if ((ret = pxa_init_dma(IRQ_DMA, 32)))
return ret;
- for (i = 0; i < ARRAY_SIZE(pxa95x_sysdev); i++) {
- ret = sysdev_register(&pxa95x_sysdev[i]);
- if (ret)
- pr_err("failed to register sysdev[%d]\n", i);
- }
+ register_syscore_ops(&pxa_irq_syscore_ops);
+ register_syscore_ops(&pxa_gpio_syscore_ops);
+ register_syscore_ops(&pxa3xx_clock_syscore_ops);
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index cd1861351f7..d130f77b6d1 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -18,7 +18,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/sysdev.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c
index 232b7316ec0..79923058d10 100644
--- a/arch/arm/mach-pxa/smemc.c
+++ b/arch/arm/mach-pxa/smemc.c
@@ -6,7 +6,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <mach/hardware.h>
#include <mach/smemc.h>
@@ -16,7 +16,7 @@ static unsigned long msc[2];
static unsigned long sxcnfg, memclkcfg;
static unsigned long csadrcfg[4];
-static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state)
+static int pxa3xx_smemc_suspend(void)
{
msc[0] = __raw_readl(MSC0);
msc[1] = __raw_readl(MSC1);
@@ -30,7 +30,7 @@ static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
-static int pxa3xx_smemc_resume(struct sys_device *dev)
+static void pxa3xx_smemc_resume(void)
{
__raw_writel(msc[0], MSC0);
__raw_writel(msc[1], MSC1);
@@ -40,34 +40,19 @@ static int pxa3xx_smemc_resume(struct sys_device *dev)
__raw_writel(csadrcfg[1], CSADRCFG1);
__raw_writel(csadrcfg[2], CSADRCFG2);
__raw_writel(csadrcfg[3], CSADRCFG3);
-
- return 0;
}
-static struct sysdev_class smemc_sysclass = {
- .name = "smemc",
+static struct syscore_ops smemc_syscore_ops = {
.suspend = pxa3xx_smemc_suspend,
.resume = pxa3xx_smemc_resume,
};
-static struct sys_device smemc_sysdev = {
- .id = 0,
- .cls = &smemc_sysclass,
-};
-
static int __init smemc_init(void)
{
- int ret = 0;
+ if (cpu_is_pxa3xx())
+ register_syscore_ops(&smemc_syscore_ops);
- if (cpu_is_pxa3xx()) {
- ret = sysdev_class_register(&smemc_sysclass);
- if (ret)
- return ret;
-
- ret = sysdev_register(&smemc_sysdev);
- }
-
- return ret;
+ return 0;
}
subsys_initcall(smemc_init);
#endif
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index b9cfbebdfe9..687417a9369 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -15,7 +15,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/bitops.h>
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index b523f119e0f..903218eab56 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -44,6 +44,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
+#include <linux/syscore_ops.h>
#include <mach/pxa25x.h>
#include <mach/audio.h>
@@ -130,20 +131,19 @@ static u8 viper_hw_version(void)
return v1;
}
-/* CPU sysdev */
-static int viper_cpu_suspend(struct sys_device *sysdev, pm_message_t state)
+/* CPU system core operations. */
+static int viper_cpu_suspend(void)
{
viper_icr_set_bit(VIPER_ICR_R_DIS);
return 0;
}
-static int viper_cpu_resume(struct sys_device *sysdev)
+static void viper_cpu_resume(void)
{
viper_icr_clear_bit(VIPER_ICR_R_DIS);
- return 0;
}
-static struct sysdev_driver viper_cpu_sysdev_driver = {
+static struct syscore_ops viper_cpu_syscore_ops = {
.suspend = viper_cpu_suspend,
.resume = viper_cpu_resume,
};
@@ -945,7 +945,7 @@ static void __init viper_init(void)
viper_init_vcore_gpios();
viper_init_cpufreq();
- sysdev_driver_register(&cpu_sysdev_class, &viper_cpu_sysdev_driver);
+ register_syscore_ops(&viper_cpu_syscore_ops);
if (version) {
pr_info("viper: hardware v%di%d detected. "
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index f71d377c864..67bd41488bf 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -16,7 +16,6 @@
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/gpio.h>
-#include <linux/sysdev.h>
#include <linux/usb/gpio_vbus.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 5e2f3533205..2854129f8cc 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -23,38 +23,12 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <plat/cpu.h>
#include <plat/pm.h>
-static int s3c2410_irq_add(struct sys_device *sysdev)
-{
- return 0;
-}
-
-static struct sysdev_driver s3c2410_irq_driver = {
- .add = s3c2410_irq_add,
+struct syscore_ops s3c24xx_irq_syscore_ops = {
.suspend = s3c24xx_irq_suspend,
.resume = s3c24xx_irq_resume,
};
-
-static int __init s3c2410_irq_init(void)
-{
- return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
-}
-
-arch_initcall(s3c2410_irq_init);
-
-static struct sysdev_driver s3c2410a_irq_driver = {
- .add = s3c2410_irq_add,
- .suspend = s3c24xx_irq_suspend,
- .resume = s3c24xx_irq_resume,
-};
-
-static int __init s3c2410a_irq_init(void)
-{
- return sysdev_driver_register(&s3c2410a_sysclass, &s3c2410a_irq_driver);
-}
-
-arch_initcall(s3c2410a_irq_init);
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 2970ea9f7c2..1e2d536adda 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -17,7 +17,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/gpio.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/dm9000.h>
@@ -214,17 +214,16 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
/* NAND Flash on BAST board */
#ifdef CONFIG_PM
-static int bast_pm_suspend(struct sys_device *sd, pm_message_t state)
+static int bast_pm_suspend(void)
{
/* ensure that an nRESET is not generated on resume. */
gpio_direction_output(S3C2410_GPA(21), 1);
return 0;
}
-static int bast_pm_resume(struct sys_device *sd)
+static void bast_pm_resume(void)
{
s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
- return 0;
}
#else
@@ -232,16 +231,11 @@ static int bast_pm_resume(struct sys_device *sd)
#define bast_pm_resume NULL
#endif
-static struct sysdev_class bast_pm_sysclass = {
- .name = "mach-bast",
+static struct syscore_ops bast_pm_syscore_ops = {
.suspend = bast_pm_suspend,
.resume = bast_pm_resume,
};
-static struct sys_device bast_pm_sysdev = {
- .cls = &bast_pm_sysclass,
-};
-
static int smartmedia_map[] = { 0 };
static int chip0_map[] = { 1 };
static int chip1_map[] = { 2 };
@@ -642,8 +636,7 @@ static void __init bast_map_io(void)
static void __init bast_init(void)
{
- sysdev_class_register(&bast_pm_sysclass);
- sysdev_register(&bast_pm_sysdev);
+ register_syscore_ops(&bast_pm_syscore_ops);
s3c_i2c0_set_platdata(&bast_i2c_info);
s3c_nand_set_platdata(&bast_nand_info);
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index 725636fc4dc..4728f9aa7df 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -25,6 +25,7 @@
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/gpio.h>
#include <linux/io.h>
@@ -92,7 +93,7 @@ static void s3c2410_pm_prepare(void)
}
}
-static int s3c2410_pm_resume(struct sys_device *dev)
+static void s3c2410_pm_resume(void)
{
unsigned long tmp;
@@ -104,10 +105,12 @@ static int s3c2410_pm_resume(struct sys_device *dev)
if ( machine_is_aml_m5900() )
s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
-
- return 0;
}
+struct syscore_ops s3c2410_pm_syscore_ops = {
+ .resume = s3c2410_pm_resume,
+};
+
static int s3c2410_pm_add(struct sys_device *dev)
{
pm_cpu_prep = s3c2410_pm_prepare;
@@ -119,7 +122,6 @@ static int s3c2410_pm_add(struct sys_device *dev)
#if defined(CONFIG_CPU_S3C2410)
static struct sysdev_driver s3c2410_pm_driver = {
.add = s3c2410_pm_add,
- .resume = s3c2410_pm_resume,
};
/* register ourselves */
@@ -133,7 +135,6 @@ arch_initcall(s3c2410_pm_drvinit);
static struct sysdev_driver s3c2410a_pm_driver = {
.add = s3c2410_pm_add,
- .resume = s3c2410_pm_resume,
};
static int __init s3c2410a_pm_drvinit(void)
@@ -147,7 +148,6 @@ arch_initcall(s3c2410a_pm_drvinit);
#if defined(CONFIG_CPU_S3C2440)
static struct sysdev_driver s3c2440_pm_driver = {
.add = s3c2410_pm_add,
- .resume = s3c2410_pm_resume,
};
static int __init s3c2440_pm_drvinit(void)
@@ -161,7 +161,6 @@ arch_initcall(s3c2440_pm_drvinit);
#if defined(CONFIG_CPU_S3C2442)
static struct sysdev_driver s3c2442_pm_driver = {
.add = s3c2410_pm_add,
- .resume = s3c2410_pm_resume,
};
static int __init s3c2442_pm_drvinit(void)
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index adc90a3c589..f1d3bd8f6f1 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -19,6 +19,7 @@
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/io.h>
@@ -40,6 +41,7 @@
#include <plat/devs.h>
#include <plat/clock.h>
#include <plat/pll.h>
+#include <plat/pm.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
@@ -168,6 +170,9 @@ int __init s3c2410_init(void)
{
printk("S3C2410: Initialising architecture\n");
+ register_syscore_ops(&s3c2410_pm_syscore_ops);
+ register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
return sysdev_register(&s3c2410_sysdev);
}
diff --git a/arch/arm/mach-s3c2412/irq.c b/arch/arm/mach-s3c2412/irq.c
index f3355d2ec63..1a1aa220972 100644
--- a/arch/arm/mach-s3c2412/irq.c
+++ b/arch/arm/mach-s3c2412/irq.c
@@ -202,8 +202,6 @@ static int s3c2412_irq_add(struct sys_device *sysdev)
static struct sysdev_driver s3c2412_irq_driver = {
.add = s3c2412_irq_add,
- .suspend = s3c24xx_irq_suspend,
- .resume = s3c24xx_irq_resume,
};
static int s3c2412_irq_init(void)
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index 923e01bdf01..85dcaeb9e62 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -17,7 +17,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/gpio.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
@@ -486,7 +486,7 @@ static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = {
/* Jive power management device */
#ifdef CONFIG_PM
-static int jive_pm_suspend(struct sys_device *sd, pm_message_t state)
+static int jive_pm_suspend(void)
{
/* Write the magic value u-boot uses to check for resume into
* the INFORM0 register, and ensure INFORM1 is set to the
@@ -498,10 +498,9 @@ static int jive_pm_suspend(struct sys_device *sd, pm_message_t state)
return 0;
}
-static int jive_pm_resume(struct sys_device *sd)
+static void jive_pm_resume(void)
{
__raw_writel(0x0, S3C2412_INFORM0);
- return 0;
}
#else
@@ -509,16 +508,11 @@ static int jive_pm_resume(struct sys_device *sd)
#define jive_pm_resume NULL
#endif
-static struct sysdev_class jive_pm_sysclass = {
- .name = "jive-pm",
+static struct syscore_ops jive_pm_syscore_ops = {
.suspend = jive_pm_suspend,
.resume = jive_pm_resume,
};
-static struct sys_device jive_pm_sysdev = {
- .cls = &jive_pm_sysclass,
-};
-
static void __init jive_map_io(void)
{
s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc));
@@ -536,10 +530,9 @@ static void jive_power_off(void)
static void __init jive_machine_init(void)
{
- /* register system devices for managing low level suspend */
+ /* register system core operations for managing low level suspend */
- sysdev_class_register(&jive_pm_sysclass);
- sysdev_register(&jive_pm_sysdev);
+ register_syscore_ops(&jive_pm_syscore_ops);
/* write our sleep configurations for the IO. Pull down all unused
* IO, ensure that we have turned off all peripherals we do not
diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c
index a7417c479ff..752b13a7b3d 100644
--- a/arch/arm/mach-s3c2412/pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -17,6 +17,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/platform_device.h>
#include <linux/io.h>
@@ -86,13 +87,24 @@ static struct sleep_save s3c2412_sleep[] = {
SAVE_ITEM(S3C2413_GPJSLPCON),
};
-static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state)
+static struct sysdev_driver s3c2412_pm_driver = {
+ .add = s3c2412_pm_add,
+};
+
+static __init int s3c2412_pm_init(void)
+{
+ return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver);
+}
+
+arch_initcall(s3c2412_pm_init);
+
+static int s3c2412_pm_suspend(void)
{
s3c_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
return 0;
}
-static int s3c2412_pm_resume(struct sys_device *dev)
+static void s3c2412_pm_resume(void)
{
unsigned long tmp;
@@ -102,18 +114,9 @@ static int s3c2412_pm_resume(struct sys_device *dev)
__raw_writel(tmp, S3C2412_PWRCFG);
s3c_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
- return 0;
}
-static struct sysdev_driver s3c2412_pm_driver = {
- .add = s3c2412_pm_add,
+struct syscore_ops s3c2412_pm_syscore_ops = {
.suspend = s3c2412_pm_suspend,
.resume = s3c2412_pm_resume,
};
-
-static __init int s3c2412_pm_init(void)
-{
- return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver);
-}
-
-arch_initcall(s3c2412_pm_init);
diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
index 4c6df51ddf3..ef0958d3e5c 100644
--- a/arch/arm/mach-s3c2412/s3c2412.c
+++ b/arch/arm/mach-s3c2412/s3c2412.c
@@ -19,6 +19,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/io.h>
@@ -244,5 +245,8 @@ int __init s3c2412_init(void)
{
printk("S3C2412: Initialising architecture\n");
+ register_syscore_ops(&s3c2412_pm_syscore_ops);
+ register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
return sysdev_register(&s3c2412_sysdev);
}
diff --git a/arch/arm/mach-s3c2416/irq.c b/arch/arm/mach-s3c2416/irq.c
index 77b38f2381c..28ad20d4244 100644
--- a/arch/arm/mach-s3c2416/irq.c
+++ b/arch/arm/mach-s3c2416/irq.c
@@ -236,8 +236,6 @@ static int __init s3c2416_irq_add(struct sys_device *sysdev)
static struct sysdev_driver s3c2416_irq_driver = {
.add = s3c2416_irq_add,
- .suspend = s3c24xx_irq_suspend,
- .resume = s3c24xx_irq_resume,
};
static int __init s3c2416_irq_init(void)
diff --git a/arch/arm/mach-s3c2416/pm.c b/arch/arm/mach-s3c2416/pm.c
index 4a04205b04d..41db2b21e21 100644
--- a/arch/arm/mach-s3c2416/pm.c
+++ b/arch/arm/mach-s3c2416/pm.c
@@ -11,6 +11,7 @@
*/
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
@@ -55,30 +56,26 @@ static int s3c2416_pm_add(struct sys_device *sysdev)
return 0;
}
-static int s3c2416_pm_suspend(struct sys_device *dev, pm_message_t state)
+static struct sysdev_driver s3c2416_pm_driver = {
+ .add = s3c2416_pm_add,
+};
+
+static __init int s3c2416_pm_init(void)
{
- return 0;
+ return sysdev_driver_register(&s3c2416_sysclass, &s3c2416_pm_driver);
}
-static int s3c2416_pm_resume(struct sys_device *dev)
+arch_initcall(s3c2416_pm_init);
+
+
+static void s3c2416_pm_resume(void)
{
/* unset the return-from-sleep amd inform flags */
__raw_writel(0x0, S3C2443_PWRMODE);
__raw_writel(0x0, S3C2412_INFORM0);
__raw_writel(0x0, S3C2412_INFORM1);
-
- return 0;
}
-static struct sysdev_driver s3c2416_pm_driver = {
- .add = s3c2416_pm_add,
- .suspend = s3c2416_pm_suspend,
+struct syscore_ops s3c2416_pm_syscore_ops = {
.resume = s3c2416_pm_resume,
};
-
-static __init int s3c2416_pm_init(void)
-{
- return sysdev_driver_register(&s3c2416_sysclass, &s3c2416_pm_driver);
-}
-
-arch_initcall(s3c2416_pm_init);
diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c
index ba7fd873743..494ce913dc9 100644
--- a/arch/arm/mach-s3c2416/s3c2416.c
+++ b/arch/arm/mach-s3c2416/s3c2416.c
@@ -32,6 +32,7 @@
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/clk.h>
#include <linux/io.h>
@@ -54,6 +55,7 @@
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/sdhci.h>
+#include <plat/pm.h>
#include <plat/iic-core.h>
#include <plat/fb-core.h>
@@ -95,6 +97,9 @@ int __init s3c2416_init(void)
s3c_fb_setname("s3c2443-fb");
+ register_syscore_ops(&s3c2416_pm_syscore_ops);
+ register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
return sysdev_register(&s3c2416_sysdev);
}
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 14dc6789775..d8853639331 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -17,7 +17,7 @@
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/serial_core.h>
#include <linux/clk.h>
#include <linux/i2c.h>
@@ -284,7 +284,7 @@ static struct platform_device osiris_pcmcia = {
#ifdef CONFIG_PM
static unsigned char pm_osiris_ctrl0;
-static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state)
+static int osiris_pm_suspend(void)
{
unsigned int tmp;
@@ -304,7 +304,7 @@ static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state)
return 0;
}
-static int osiris_pm_resume(struct sys_device *sd)
+static void osiris_pm_resume(void)
{
if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8)
__raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1);
@@ -312,8 +312,6 @@ static int osiris_pm_resume(struct sys_device *sd)
__raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0);
s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
-
- return 0;
}
#else
@@ -321,16 +319,11 @@ static int osiris_pm_resume(struct sys_device *sd)
#define osiris_pm_resume NULL
#endif
-static struct sysdev_class osiris_pm_sysclass = {
- .name = "mach-osiris",
+static struct syscore_ops osiris_pm_syscore_ops = {
.suspend = osiris_pm_suspend,
.resume = osiris_pm_resume,
};
-static struct sys_device osiris_pm_sysdev = {
- .cls = &osiris_pm_sysclass,
-};
-
/* Link for DVS driver to TPS65011 */
static void osiris_tps_release(struct device *dev)
@@ -439,8 +432,7 @@ static void __init osiris_map_io(void)
static void __init osiris_init(void)
{
- sysdev_class_register(&osiris_pm_sysclass);
- sysdev_register(&osiris_pm_sysdev);
+ register_syscore_ops(&osiris_pm_syscore_ops);
s3c_i2c0_set_platdata(NULL);
s3c_nand_set_platdata(&osiris_nand_info);
diff --git a/arch/arm/mach-s3c2440/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c
index f7663f731ea..ce99ff72838 100644
--- a/arch/arm/mach-s3c2440/s3c2440.c
+++ b/arch/arm/mach-s3c2440/s3c2440.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/io.h>
@@ -33,6 +34,7 @@
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/s3c244x.h>
+#include <plat/pm.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
@@ -51,6 +53,12 @@ int __init s3c2440_init(void)
s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
s3c_device_wdt.resource[1].end = IRQ_S3C2440_WDT;
+ /* register suspend/resume handlers */
+
+ register_syscore_ops(&s3c2410_pm_syscore_ops);
+ register_syscore_ops(&s3c244x_pm_syscore_ops);
+ register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
/* register our system device for everything else */
return sysdev_register(&s3c2440_sysdev);
diff --git a/arch/arm/mach-s3c2440/s3c2442.c b/arch/arm/mach-s3c2440/s3c2442.c
index ecf81354655..6224bad4d60 100644
--- a/arch/arm/mach-s3c2440/s3c2442.c
+++ b/arch/arm/mach-s3c2440/s3c2442.c
@@ -29,6 +29,7 @@
#include <linux/err.h>
#include <linux/device.h>
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/mutex.h>
@@ -45,6 +46,7 @@
#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/s3c244x.h>
+#include <plat/pm.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
@@ -167,6 +169,10 @@ int __init s3c2442_init(void)
{
printk("S3C2442: Initialising architecture\n");
+ register_syscore_ops(&s3c2410_pm_syscore_ops);
+ register_syscore_ops(&s3c244x_pm_syscore_ops);
+ register_syscore_ops(&s3c24xx_irq_syscore_ops);
+
return sysdev_register(&s3c2442_sysdev);
}
diff --git a/arch/arm/mach-s3c2440/s3c244x-irq.c b/arch/arm/mach-s3c2440/s3c244x-irq.c
index de07c2feaa3..c63e8f26d90 100644
--- a/arch/arm/mach-s3c2440/s3c244x-irq.c
+++ b/arch/arm/mach-s3c2440/s3c244x-irq.c
@@ -116,8 +116,6 @@ static int s3c244x_irq_add(struct sys_device *sysdev)
static struct sysdev_driver s3c2440_irq_driver = {
.add = s3c244x_irq_add,
- .suspend = s3c24xx_irq_suspend,
- .resume = s3c24xx_irq_resume,
};
static int s3c2440_irq_init(void)
@@ -129,8 +127,6 @@ arch_initcall(s3c2440_irq_init);
static struct sysdev_driver s3c2442_irq_driver = {
.add = s3c244x_irq_add,
- .suspend = s3c24xx_irq_suspend,
- .resume = s3c24xx_irq_resume,
};
diff --git a/arch/arm/mach-s3c2440/s3c244x.c b/arch/arm/mach-s3c2440/s3c244x.c
index 90c1707b9c9..7e8a23d2098 100644
--- a/arch/arm/mach-s3c2440/s3c244x.c
+++ b/arch/arm/mach-s3c2440/s3c244x.c
@@ -19,6 +19,7 @@
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/clk.h>
#include <linux/io.h>
@@ -134,45 +135,14 @@ void __init s3c244x_init_clocks(int xtal)
s3c2410_baseclk_add();
}
-#ifdef CONFIG_PM
-
-static struct sleep_save s3c244x_sleep[] = {
- SAVE_ITEM(S3C2440_DSC0),
- SAVE_ITEM(S3C2440_DSC1),
- SAVE_ITEM(S3C2440_GPJDAT),
- SAVE_ITEM(S3C2440_GPJCON),
- SAVE_ITEM(S3C2440_GPJUP)
-};
-
-static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
-{
- s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
- return 0;
-}
-
-static int s3c244x_resume(struct sys_device *dev)
-{
- s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
- return 0;
-}
-
-#else
-#define s3c244x_suspend NULL
-#define s3c244x_resume NULL
-#endif
-
/* Since the S3C2442 and S3C2440 share items, put both sysclasses here */
struct sysdev_class s3c2440_sysclass = {
.name = "s3c2440-core",
- .suspend = s3c244x_suspend,
- .resume = s3c244x_resume
};
struct sysdev_class s3c2442_sysclass = {
.name = "s3c2442-core",
- .suspend = s3c244x_suspend,
- .resume = s3c244x_resume
};
/* need to register class before we actually register the device, and
@@ -194,3 +164,33 @@ static int __init s3c2442_core_init(void)
}
core_initcall(s3c2442_core_init);
+
+
+#ifdef CONFIG_PM
+static struct sleep_save s3c244x_sleep[] = {
+ SAVE_ITEM(S3C2440_DSC0),
+ SAVE_ITEM(S3C2440_DSC1),
+ SAVE_ITEM(S3C2440_GPJDAT),
+ SAVE_ITEM(S3C2440_GPJCON),
+ SAVE_ITEM(S3C2440_GPJUP)
+};
+
+static int s3c244x_suspend(void)
+{
+ s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+ return 0;
+}
+
+static void s3c244x_resume(void)
+{
+ s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+}
+#else
+#define s3c244x_suspend NULL
+#define s3c244x_resume NULL
+#endif
+
+struct syscore_ops s3c244x_pm_syscore_ops = {
+ .suspend = s3c244x_suspend,
+ .resume = s3c244x_resume,
+};
diff --git a/arch/arm/mach-s3c64xx/irq-pm.c b/arch/arm/mach-s3c64xx/irq-pm.c
index da1bec64b9d..8bec61e242c 100644
--- a/arch/arm/mach-s3c64xx/irq-pm.c
+++ b/arch/arm/mach-s3c64xx/irq-pm.c
@@ -13,7 +13,7 @@
*/
#include <linux/kernel.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/interrupt.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
@@ -54,7 +54,7 @@ static struct irq_grp_save {
static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
-static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
+static int s3c64xx_irq_pm_suspend(void)
{
struct irq_grp_save *grp = eint_grp_save;
int i;
@@ -75,7 +75,7 @@ static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
-static int s3c64xx_irq_pm_resume(struct sys_device *dev)
+static void s3c64xx_irq_pm_resume(void)
{
struct irq_grp_save *grp = eint_grp_save;
int i;
@@ -94,18 +94,18 @@ static int s3c64xx_irq_pm_resume(struct sys_device *dev)
}
S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
- return 0;
}
-static struct sysdev_driver s3c64xx_irq_driver = {
+struct syscore_ops s3c64xx_irq_syscore_ops = {
.suspend = s3c64xx_irq_pm_suspend,
.resume = s3c64xx_irq_pm_resume,
};
-static int __init s3c64xx_irq_pm_init(void)
+static __init int s3c64xx_syscore_init(void)
{
- return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
-}
+ register_syscore_ops(&s3c64xx_irq_syscore_ops);
-arch_initcall(s3c64xx_irq_pm_init);
+ return 0;
+}
+core_initcall(s3c64xx_syscore_init);
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
index 549d7924fd4..24febae3d4c 100644
--- a/arch/arm/mach-s5pv210/pm.c
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <plat/cpu.h>
@@ -140,7 +141,17 @@ static int s5pv210_pm_add(struct sys_device *sysdev)
return 0;
}
-static int s5pv210_pm_resume(struct sys_device *dev)
+static struct sysdev_driver s5pv210_pm_driver = {
+ .add = s5pv210_pm_add,
+};
+
+static __init int s5pv210_pm_drvinit(void)
+{
+ return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver);
+}
+arch_initcall(s5pv210_pm_drvinit);
+
+static void s5pv210_pm_resume(void)
{
u32 tmp;
@@ -150,17 +161,15 @@ static int s5pv210_pm_resume(struct sys_device *dev)
__raw_writel(tmp , S5P_OTHERS);
s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
-
- return 0;
}
-static struct sysdev_driver s5pv210_pm_driver = {
- .add = s5pv210_pm_add,
+static struct syscore_ops s5pv210_pm_syscore_ops = {
.resume = s5pv210_pm_resume,
};
-static __init int s5pv210_pm_drvinit(void)
+static __init int s5pv210_pm_syscore_init(void)
{
- return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver);
+ register_syscore_ops(&s5pv210_pm_syscore_ops);
+ return 0;
}
-arch_initcall(s5pv210_pm_drvinit);
+arch_initcall(s5pv210_pm_syscore_init);
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 423ddb3d65e..dfbf824a69f 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -14,7 +14,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/ioport.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <mach/hardware.h>
#include <asm/mach/irq.h>
@@ -234,7 +234,7 @@ static struct sa1100irq_state {
unsigned int iccr;
} sa1100irq_state;
-static int sa1100irq_suspend(struct sys_device *dev, pm_message_t state)
+static int sa1100irq_suspend(void)
{
struct sa1100irq_state *st = &sa1100irq_state;
@@ -264,7 +264,7 @@ static int sa1100irq_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
-static int sa1100irq_resume(struct sys_device *dev)
+static void sa1100irq_resume(void)
{
struct sa1100irq_state *st = &sa1100irq_state;
@@ -277,24 +277,17 @@ static int sa1100irq_resume(struct sys_device *dev)
ICMR = st->icmr;
}
- return 0;
}
-static struct sysdev_class sa1100irq_sysclass = {
- .name = "sa11x0-irq",
+static struct syscore_ops sa1100irq_syscore_ops = {
.suspend = sa1100irq_suspend,
.resume = sa1100irq_resume,
};
-static struct sys_device sa1100irq_device = {
- .id = 0,
- .cls = &sa1100irq_sysclass,
-};
-
static int __init sa1100irq_init_devicefs(void)
{
- sysdev_class_register(&sa1100irq_sysclass);
- return sysdev_register(&sa1100irq_device);
+ register_syscore_ops(&sa1100irq_syscore_ops);
+ return 0;
}
device_initcall(sa1100irq_init_devicefs);
diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c
index 94912d3944d..2d1b67a59e4 100644
--- a/arch/arm/mach-shmobile/pm_runtime.c
+++ b/arch/arm/mach-shmobile/pm_runtime.c
@@ -18,152 +18,41 @@
#include <linux/clk.h>
#include <linux/sh_clk.h>
#include <linux/bitmap.h>
+#include <linux/slab.h>
#ifdef CONFIG_PM_RUNTIME
-#define BIT_ONCE 0
-#define BIT_ACTIVE 1
-#define BIT_CLK_ENABLED 2
-struct pm_runtime_data {
- unsigned long flags;
- struct clk *clk;
-};
-
-static void __devres_release(struct device *dev, void *res)
-{
- struct pm_runtime_data *prd = res;
-
- dev_dbg(dev, "__devres_release()\n");
-
- if (test_bit(BIT_CLK_ENABLED, &prd->flags))
- clk_disable(prd->clk);
-
- if (test_bit(BIT_ACTIVE, &prd->flags))
- clk_put(prd->clk);
-}
-
-static struct pm_runtime_data *__to_prd(struct device *dev)
-{
- return devres_find(dev, __devres_release, NULL, NULL);
-}
-
-static void platform_pm_runtime_init(struct device *dev,
- struct pm_runtime_data *prd)
-{
- if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags)) {
- prd->clk = clk_get(dev, NULL);
- if (!IS_ERR(prd->clk)) {
- set_bit(BIT_ACTIVE, &prd->flags);
- dev_info(dev, "clocks managed by runtime pm\n");
- }
- }
-}
-
-static void platform_pm_runtime_bug(struct device *dev,
- struct pm_runtime_data *prd)
-{
- if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags))
- dev_err(dev, "runtime pm suspend before resume\n");
-}
-
-int platform_pm_runtime_suspend(struct device *dev)
-{
- struct pm_runtime_data *prd = __to_prd(dev);
-
- dev_dbg(dev, "platform_pm_runtime_suspend()\n");
-
- platform_pm_runtime_bug(dev, prd);
-
- if (prd && test_bit(BIT_ACTIVE, &prd->flags)) {
- clk_disable(prd->clk);
- clear_bit(BIT_CLK_ENABLED, &prd->flags);
- }
-
- return 0;
-}
-
-int platform_pm_runtime_resume(struct device *dev)
-{
- struct pm_runtime_data *prd = __to_prd(dev);
-
- dev_dbg(dev, "platform_pm_runtime_resume()\n");
-
- platform_pm_runtime_init(dev, prd);
-
- if (prd && test_bit(BIT_ACTIVE, &prd->flags)) {
- clk_enable(prd->clk);
- set_bit(BIT_CLK_ENABLED, &prd->flags);
- }
-
- return 0;
-}
-
-int platform_pm_runtime_idle(struct device *dev)
+static int default_platform_runtime_idle(struct device *dev)
{
/* suspend synchronously to disable clocks immediately */
return pm_runtime_suspend(dev);
}
-static int platform_bus_notify(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct device *dev = data;
- struct pm_runtime_data *prd;
-
- dev_dbg(dev, "platform_bus_notify() %ld !\n", action);
-
- if (action == BUS_NOTIFY_BIND_DRIVER) {
- prd = devres_alloc(__devres_release, sizeof(*prd), GFP_KERNEL);
- if (prd)
- devres_add(dev, prd);
- else
- dev_err(dev, "unable to alloc memory for runtime pm\n");
- }
-
- return 0;
-}
-
-#else /* CONFIG_PM_RUNTIME */
-
-static int platform_bus_notify(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct device *dev = data;
- struct clk *clk;
+static struct dev_power_domain default_power_domain = {
+ .ops = {
+ .runtime_suspend = pm_runtime_clk_suspend,
+ .runtime_resume = pm_runtime_clk_resume,
+ .runtime_idle = default_platform_runtime_idle,
+ USE_PLATFORM_PM_SLEEP_OPS
+ },
+};
- dev_dbg(dev, "platform_bus_notify() %ld !\n", action);
+#define DEFAULT_PWR_DOMAIN_PTR (&default_power_domain)
- switch (action) {
- case BUS_NOTIFY_BIND_DRIVER:
- clk = clk_get(dev, NULL);
- if (!IS_ERR(clk)) {
- clk_enable(clk);
- clk_put(clk);
- dev_info(dev, "runtime pm disabled, clock forced on\n");
- }
- break;
- case BUS_NOTIFY_UNBOUND_DRIVER:
- clk = clk_get(dev, NULL);
- if (!IS_ERR(clk)) {
- clk_disable(clk);
- clk_put(clk);
- dev_info(dev, "runtime pm disabled, clock forced off\n");
- }
- break;
- }
+#else
- return 0;
-}
+#define DEFAULT_PWR_DOMAIN_PTR NULL
#endif /* CONFIG_PM_RUNTIME */
-static struct notifier_block platform_bus_notifier = {
- .notifier_call = platform_bus_notify
+static struct pm_clk_notifier_block platform_bus_notifier = {
+ .pwr_domain = DEFAULT_PWR_DOMAIN_PTR,
+ .con_ids = { NULL, },
};
static int __init sh_pm_runtime_init(void)
{
- bus_register_notifier(&platform_bus_type, &platform_bus_notifier);
+ pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
return 0;
}
core_initcall(sh_pm_runtime_init);
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index d2adcdda23c..bd9e32187ea 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -17,7 +17,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
@@ -1372,9 +1372,7 @@ static const struct dev_pm_ops omap_mpuio_dev_pm_ops = {
.resume_noirq = omap_mpuio_resume_noirq,
};
-/* use platform_driver for this, now that there's no longer any
- * point to sys_device (other than not disturbing old code).
- */
+/* use platform_driver for this. */
static struct platform_driver omap_mpuio_driver = {
.driver = {
.name = "mpuio",
@@ -1745,7 +1743,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
}
#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
+static int omap_gpio_suspend(void)
{
int i;
@@ -1795,12 +1793,12 @@ static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
return 0;
}
-static int omap_gpio_resume(struct sys_device *dev)
+static void omap_gpio_resume(void)
{
int i;
if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
- return 0;
+ return;
for (i = 0; i < gpio_bank_count; i++) {
struct gpio_bank *bank = &gpio_bank[i];
@@ -1836,21 +1834,13 @@ static int omap_gpio_resume(struct sys_device *dev)
__raw_writel(bank->saved_wakeup, wake_set);
spin_unlock_irqrestore(&bank->lock, flags);
}
-
- return 0;
}
-static struct sysdev_class omap_gpio_sysclass = {
- .name = "gpio",
+static struct syscore_ops omap_gpio_syscore_ops = {
.suspend = omap_gpio_suspend,
.resume = omap_gpio_resume,
};
-static struct sys_device omap_gpio_device = {
- .id = 0,
- .cls = &omap_gpio_sysclass,
-};
-
#endif
#ifdef CONFIG_ARCH_OMAP2PLUS
@@ -2108,21 +2098,14 @@ postcore_initcall(omap_gpio_drv_reg);
static int __init omap_gpio_sysinit(void)
{
- int ret = 0;
-
mpuio_init();
#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
- if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
- if (ret == 0) {
- ret = sysdev_class_register(&omap_gpio_sysclass);
- if (ret == 0)
- ret = sysdev_register(&omap_gpio_device);
- }
- }
+ if (cpu_is_omap16xx() || cpu_class_is_omap2())
+ register_syscore_ops(&omap_gpio_syscore_ops);
#endif
- return ret;
+ return 0;
}
arch_initcall(omap_gpio_sysinit);
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 9bbda9acb73..a37b8eb65b7 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -536,6 +536,28 @@ int omap_early_device_register(struct omap_device *od)
return 0;
}
+static int _od_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ return omap_device_idle(pdev);
+}
+
+static int _od_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ return omap_device_enable(pdev);
+}
+
+static struct dev_power_domain omap_device_power_domain = {
+ .ops = {
+ .runtime_suspend = _od_runtime_suspend,
+ .runtime_resume = _od_runtime_resume,
+ USE_PLATFORM_PM_SLEEP_OPS
+ }
+};
+
/**
* omap_device_register - register an omap_device with one omap_hwmod
* @od: struct omap_device * to register
@@ -549,6 +571,7 @@ int omap_device_register(struct omap_device *od)
pr_debug("omap_device: %s: registering\n", od->pdev.name);
od->pdev.dev.parent = &omap_device_parent;
+ od->pdev.dev.pwr_domain = &omap_device_power_domain;
return platform_device_register(&od->pdev);
}
diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c
index dce088f4567..48ebb9479b6 100644
--- a/arch/arm/plat-pxa/gpio.c
+++ b/arch/arm/plat-pxa/gpio.c
@@ -15,7 +15,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/slab.h>
#include <mach/gpio.h>
@@ -295,7 +295,7 @@ void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
}
#ifdef CONFIG_PM
-static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
+static int pxa_gpio_suspend(void)
{
struct pxa_gpio_chip *c;
int gpio;
@@ -312,7 +312,7 @@ static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
-static int pxa_gpio_resume(struct sys_device *dev)
+static void pxa_gpio_resume(void)
{
struct pxa_gpio_chip *c;
int gpio;
@@ -326,22 +326,13 @@ static int pxa_gpio_resume(struct sys_device *dev)
__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
}
- return 0;
}
#else
#define pxa_gpio_suspend NULL
#define pxa_gpio_resume NULL
#endif
-struct sysdev_class pxa_gpio_sysclass = {
- .name = "gpio",
+struct syscore_ops pxa_gpio_syscore_ops = {
.suspend = pxa_gpio_suspend,
.resume = pxa_gpio_resume,
};
-
-static int __init pxa_gpio_init(void)
-{
- return sysdev_class_register(&pxa_gpio_sysclass);
-}
-
-core_initcall(pxa_gpio_init);
diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c
index a9aa5ad3f4e..be12eadcce2 100644
--- a/arch/arm/plat-pxa/mfp.c
+++ b/arch/arm/plat-pxa/mfp.c
@@ -17,7 +17,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
-#include <linux/sysdev.h>
#include <plat/mfp.h>
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 27ea852e337..c10d10c56e2 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -22,7 +22,7 @@
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/io.h>
@@ -1195,19 +1195,12 @@ int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *d
EXPORT_SYMBOL(s3c2410_dma_getposition);
-static inline struct s3c2410_dma_chan *to_dma_chan(struct sys_device *dev)
-{
- return container_of(dev, struct s3c2410_dma_chan, dev);
-}
-
-/* system device class */
+/* system core operations */
#ifdef CONFIG_PM
-static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
+static void s3c2410_dma_suspend_chan(s3c2410_dma_chan *cp)
{
- struct s3c2410_dma_chan *cp = to_dma_chan(dev);
-
printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
@@ -1222,13 +1215,21 @@ static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
s3c2410_dma_dostop(cp);
}
+}
+
+static int s3c2410_dma_suspend(void)
+{
+ struct s3c2410_dma_chan *cp = s3c2410_chans;
+ int channel;
+
+ for (channel = 0; channel < dma_channels; cp++, channel++)
+ s3c2410_dma_suspend_chan(cp);
return 0;
}
-static int s3c2410_dma_resume(struct sys_device *dev)
+static void s3c2410_dma_resume_chan(struct s3c2410_dma_chan *cp)
{
- struct s3c2410_dma_chan *cp = to_dma_chan(dev);
unsigned int no = cp->number | DMACH_LOW_LEVEL;
/* restore channel's hardware configuration */
@@ -1249,13 +1250,21 @@ static int s3c2410_dma_resume(struct sys_device *dev)
return 0;
}
+static void s3c2410_dma_resume(void)
+{
+ struct s3c2410_dma_chan *cp = s3c2410_chans + dma_channels - 1;
+ int channel;
+
+ for (channel = dma_channels - 1; channel >= 0; cp++, channel--)
+ s3c2410_dma_resume_chan(cp);
+}
+
#else
#define s3c2410_dma_suspend NULL
#define s3c2410_dma_resume NULL
#endif /* CONFIG_PM */
-struct sysdev_class dma_sysclass = {
- .name = "s3c24xx-dma",
+struct syscore_ops dma_syscore_ops = {
.suspend = s3c2410_dma_suspend,
.resume = s3c2410_dma_resume,
};
@@ -1269,39 +1278,14 @@ static void s3c2410_dma_cache_ctor(void *p)
/* initialisation code */
-static int __init s3c24xx_dma_sysclass_init(void)
+static int __init s3c24xx_dma_syscore_init(void)
{
- int ret = sysdev_class_register(&dma_sysclass);
-
- if (ret != 0)
- printk(KERN_ERR "dma sysclass registration failed\n");
-
- return ret;
-}
-
-core_initcall(s3c24xx_dma_sysclass_init);
-
-static int __init s3c24xx_dma_sysdev_register(void)
-{
- struct s3c2410_dma_chan *cp = s3c2410_chans;
- int channel, ret;
-
- for (channel = 0; channel < dma_channels; cp++, channel++) {
- cp->dev.cls = &dma_sysclass;
- cp->dev.id = channel;
- ret = sysdev_register(&cp->dev);
-
- if (ret) {
- printk(KERN_ERR "error registering dev for dma %d\n",
- channel);
- return ret;
- }
- }
+ register_syscore_ops(&dma_syscore_ops);
return 0;
}
-late_initcall(s3c24xx_dma_sysdev_register);
+late_initcall(s3c24xx_dma_syscore_init);
int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
unsigned int stride)
diff --git a/arch/arm/plat-s3c24xx/irq-pm.c b/arch/arm/plat-s3c24xx/irq-pm.c
index c3624d89863..0efb2e2848c 100644
--- a/arch/arm/plat-s3c24xx/irq-pm.c
+++ b/arch/arm/plat-s3c24xx/irq-pm.c
@@ -14,7 +14,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
-#include <linux/sysdev.h>
#include <linux/irq.h>
#include <plat/cpu.h>
@@ -65,7 +64,7 @@ static unsigned long save_extint[3];
static unsigned long save_eintflt[4];
static unsigned long save_eintmask;
-int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+int s3c24xx_irq_suspend(void)
{
unsigned int i;
@@ -81,7 +80,7 @@ int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
-int s3c24xx_irq_resume(struct sys_device *dev)
+void s3c24xx_irq_resume(void)
{
unsigned int i;
@@ -93,6 +92,4 @@ int s3c24xx_irq_resume(struct sys_device *dev)
s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
__raw_writel(save_eintmask, S3C24XX_EINTMASK);
-
- return 0;
}
diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c
index 5259ad458bc..327acb3a446 100644
--- a/arch/arm/plat-s5p/irq-pm.c
+++ b/arch/arm/plat-s5p/irq-pm.c
@@ -16,7 +16,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
-#include <linux/sysdev.h>
#include <plat/cpu.h>
#include <plat/irqs.h>
@@ -77,17 +76,15 @@ static struct sleep_save eint_save[] = {
SAVE_ITEM(S5P_EINT_MASK(3)),
};
-int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+int s3c24xx_irq_suspend(void)
{
s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save));
return 0;
}
-int s3c24xx_irq_resume(struct sys_device *dev)
+void s3c24xx_irq_resume(void)
{
s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save));
-
- return 0;
}
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index cedfff51c82..3aedac0034b 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -68,6 +68,12 @@ extern void s3c24xx_init_uartdevs(char *name,
struct sys_timer;
extern struct sys_timer s3c24xx_timer;
+extern struct syscore_ops s3c2410_pm_syscore_ops;
+extern struct syscore_ops s3c2412_pm_syscore_ops;
+extern struct syscore_ops s3c2416_pm_syscore_ops;
+extern struct syscore_ops s3c244x_pm_syscore_ops;
+extern struct syscore_ops s3c64xx_irq_syscore_ops;
+
/* system device classes */
extern struct sysdev_class s3c2410_sysclass;
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 937cc2ace51..7fb6f6be8c8 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -103,14 +103,16 @@ extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
#ifdef CONFIG_PM
extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
-extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
-extern int s3c24xx_irq_resume(struct sys_device *dev);
+extern int s3c24xx_irq_suspend(void);
+extern void s3c24xx_irq_resume(void);
#else
#define s3c_irqext_wake NULL
#define s3c24xx_irq_suspend NULL
#define s3c24xx_irq_resume NULL
#endif
+extern struct syscore_ops s3c24xx_irq_syscore_ops;
+
/* PM debug functions */
#ifdef CONFIG_SAMSUNG_PM_DEBUG
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index f74695075e6..f25e7ec8941 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -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);
@@ -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 */
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
index 21ce35f33aa..3e3646186c9 100644
--- a/arch/avr32/mach-at32ap/intc.c
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -12,7 +12,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <asm/io.h>
@@ -21,7 +21,6 @@
struct intc {
void __iomem *regs;
struct irq_chip chip;
- struct sys_device sysdev;
#ifdef CONFIG_PM
unsigned long suspend_ipr;
unsigned long saved_ipr[64];
@@ -146,9 +145,8 @@ void intc_set_suspend_handler(unsigned long offset)
intc0.suspend_ipr = offset;
}
-static int intc_suspend(struct sys_device *sdev, pm_message_t state)
+static int intc_suspend(void)
{
- struct intc *intc = container_of(sdev, struct intc, sysdev);
int i;
if (unlikely(!irqs_disabled())) {
@@ -156,28 +154,25 @@ static int intc_suspend(struct sys_device *sdev, pm_message_t state)
return -EINVAL;
}
- if (unlikely(!intc->suspend_ipr)) {
+ if (unlikely(!intc0.suspend_ipr)) {
pr_err("intc_suspend: suspend_ipr not initialized\n");
return -EINVAL;
}
for (i = 0; i < 64; i++) {
- intc->saved_ipr[i] = intc_readl(intc, INTPR0 + 4 * i);
- intc_writel(intc, INTPR0 + 4 * i, intc->suspend_ipr);
+ intc0.saved_ipr[i] = intc_readl(&intc0, INTPR0 + 4 * i);
+ intc_writel(&intc0, INTPR0 + 4 * i, intc0.suspend_ipr);
}
return 0;
}
-static int intc_resume(struct sys_device *sdev)
+static int intc_resume(void)
{
- struct intc *intc = container_of(sdev, struct intc, sysdev);
int i;
- WARN_ON(!irqs_disabled());
-
for (i = 0; i < 64; i++)
- intc_writel(intc, INTPR0 + 4 * i, intc->saved_ipr[i]);
+ intc_writel(&intc0, INTPR0 + 4 * i, intc0.saved_ipr[i]);
return 0;
}
@@ -186,27 +181,18 @@ static int intc_resume(struct sys_device *sdev)
#define intc_resume NULL
#endif
-static struct sysdev_class intc_class = {
- .name = "intc",
+static struct syscore_ops intc_syscore_ops = {
.suspend = intc_suspend,
.resume = intc_resume,
};
-static int __init intc_init_sysdev(void)
+static int __init intc_init_syscore(void)
{
- int ret;
-
- ret = sysdev_class_register(&intc_class);
- if (ret)
- return ret;
+ register_syscore_ops(&intc_syscore_ops);
- intc0.sysdev.id = 0;
- intc0.sysdev.cls = &intc_class;
- ret = sysdev_register(&intc0.sysdev);
-
- return ret;
+ return 0;
}
-device_initcall(intc_init_sysdev);
+device_initcall(intc_init_syscore);
unsigned long intc_get_pending(unsigned int group)
{
diff --git a/arch/blackfin/kernel/nmi.c b/arch/blackfin/kernel/nmi.c
index 0b5f72f17fd..401eb1d8e3b 100644
--- a/arch/blackfin/kernel/nmi.c
+++ b/arch/blackfin/kernel/nmi.c
@@ -12,7 +12,7 @@
#include <linux/bitops.h>
#include <linux/hardirq.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/pm.h>
#include <linux/nmi.h>
#include <linux/smp.h>
@@ -196,43 +196,31 @@ void touch_nmi_watchdog(void)
/* Suspend/resume support */
#ifdef CONFIG_PM
-static int nmi_wdt_suspend(struct sys_device *dev, pm_message_t state)
+static int nmi_wdt_suspend(void)
{
nmi_wdt_stop();
return 0;
}
-static int nmi_wdt_resume(struct sys_device *dev)
+static void nmi_wdt_resume(void)
{
if (nmi_active)
nmi_wdt_start();
- return 0;
}
-static struct sysdev_class nmi_sysclass = {
- .name = DRV_NAME,
+static struct syscore_ops nmi_syscore_ops = {
.resume = nmi_wdt_resume,
.suspend = nmi_wdt_suspend,
};
-static struct sys_device device_nmi_wdt = {
- .id = 0,
- .cls = &nmi_sysclass,
-};
-
-static int __init init_nmi_wdt_sysfs(void)
+static int __init init_nmi_wdt_syscore(void)
{
- int error;
-
- if (!nmi_active)
- return 0;
+ if (nmi_active)
+ register_syscore_ops(&nmi_syscore_ops);
- error = sysdev_class_register(&nmi_sysclass);
- if (!error)
- error = sysdev_register(&device_nmi_wdt);
- return error;
+ return 0;
}
-late_initcall(init_nmi_wdt_sysfs);
+late_initcall(init_nmi_wdt_syscore);
#endif /* CONFIG_PM */
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
index 7005ee0b074..49baddcdd14 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -3,7 +3,6 @@
#ifdef __KERNEL__
#include <linux/irq.h>
-#include <linux/sysdev.h>
#include <asm/dcr.h>
#include <asm/msi_bitmap.h>
@@ -320,8 +319,6 @@ struct mpic
/* link */
struct mpic *next;
- struct sys_device sysdev;
-
#ifdef CONFIG_PM
struct mpic_irq_save *save_data;
#endif
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index acfaccea5f4..3675da73623 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -32,6 +32,7 @@
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/linux_logo.h>
+#include <linux/syscore_ops.h>
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/spu_csa.h>
@@ -521,18 +522,8 @@ void spu_init_channels(struct spu *spu)
}
EXPORT_SYMBOL_GPL(spu_init_channels);
-static int spu_shutdown(struct sys_device *sysdev)
-{
- struct spu *spu = container_of(sysdev, struct spu, sysdev);
-
- spu_free_irqs(spu);
- spu_destroy_spu(spu);
- return 0;
-}
-
static struct sysdev_class spu_sysdev_class = {
.name = "spu",
- .shutdown = spu_shutdown,
};
int spu_add_sysdev_attr(struct sysdev_attribute *attr)
@@ -797,6 +788,22 @@ static inline void crash_register_spus(struct list_head *list)
}
#endif
+static void spu_shutdown(void)
+{
+ struct spu *spu;
+
+ mutex_lock(&spu_full_list_mutex);
+ list_for_each_entry(spu, &spu_full_list, full_list) {
+ spu_free_irqs(spu);
+ spu_destroy_spu(spu);
+ }
+ mutex_unlock(&spu_full_list_mutex);
+}
+
+static struct syscore_ops spu_syscore_ops = {
+ .shutdown = spu_shutdown,
+};
+
static int __init init_spu_base(void)
{
int i, ret = 0;
@@ -830,6 +837,7 @@ static int __init init_spu_base(void)
crash_register_spus(&spu_full_list);
mutex_unlock(&spu_full_list_mutex);
spu_add_sysdev_attr(&attr_stat);
+ register_syscore_ops(&spu_syscore_ops);
spu_init_affinity();
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 023f24086a0..7c18a1607d1 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -21,7 +21,7 @@
#include <linux/signal.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/adb.h>
#include <linux/pmu.h>
#include <linux/module.h>
@@ -677,7 +677,7 @@ not_found:
return viaint;
}
-static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
+static int pmacpic_suspend(void)
{
int viaint = pmacpic_find_viaint();
@@ -698,7 +698,7 @@ static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
return 0;
}
-static int pmacpic_resume(struct sys_device *sysdev)
+static void pmacpic_resume(void)
{
int i;
@@ -709,39 +709,19 @@ static int pmacpic_resume(struct sys_device *sysdev)
for (i = 0; i < max_real_irqs; ++i)
if (test_bit(i, sleep_save_mask))
pmac_unmask_irq(irq_get_irq_data(i));
-
- return 0;
}
-#endif /* CONFIG_PM && CONFIG_PPC32 */
-
-static struct sysdev_class pmacpic_sysclass = {
- .name = "pmac_pic",
+static struct syscore_ops pmacpic_syscore_ops = {
+ .suspend = pmacpic_suspend,
+ .resume = pmacpic_resume,
};
-static struct sys_device device_pmacpic = {
- .id = 0,
- .cls = &pmacpic_sysclass,
-};
-
-static struct sysdev_driver driver_pmacpic = {
-#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
- .suspend = &pmacpic_suspend,
- .resume = &pmacpic_resume,
-#endif /* CONFIG_PM && CONFIG_PPC32 */
-};
-
-static int __init init_pmacpic_sysfs(void)
+static int __init init_pmacpic_syscore(void)
{
-#ifdef CONFIG_PPC32
- if (max_irqs == 0)
- return -ENODEV;
-#endif
- printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");
- sysdev_class_register(&pmacpic_sysclass);
- sysdev_register(&device_pmacpic);
- sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);
+ register_syscore_ops(&pmacpic_syscore_ops);
return 0;
}
-machine_subsys_initcall(powermac, init_pmacpic_sysfs);
+machine_subsys_initcall(powermac, init_pmacpic_syscore);
+
+#endif /* CONFIG_PM && CONFIG_PPC32 */
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index fa438be962b..596554a8725 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -18,7 +18,7 @@
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/signal.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/spinlock.h>
@@ -902,7 +902,7 @@ static struct {
u32 sercr;
} ipic_saved_state;
-static int ipic_suspend(struct sys_device *sdev, pm_message_t state)
+static int ipic_suspend(void)
{
struct ipic *ipic = primary_ipic;
@@ -933,7 +933,7 @@ static int ipic_suspend(struct sys_device *sdev, pm_message_t state)
return 0;
}
-static int ipic_resume(struct sys_device *sdev)
+static void ipic_resume(void)
{
struct ipic *ipic = primary_ipic;
@@ -949,44 +949,26 @@ static int ipic_resume(struct sys_device *sdev)
ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr);
ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr);
ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr);
-
- return 0;
}
#else
#define ipic_suspend NULL
#define ipic_resume NULL
#endif
-static struct sysdev_class ipic_sysclass = {
- .name = "ipic",
+static struct syscore_ops ipic_syscore_ops = {
.suspend = ipic_suspend,
.resume = ipic_resume,
};
-static struct sys_device device_ipic = {
- .id = 0,
- .cls = &ipic_sysclass,
-};
-
-static int __init init_ipic_sysfs(void)
+static int __init init_ipic_syscore(void)
{
- int rc;
-
if (!primary_ipic || !primary_ipic->regs)
return -ENODEV;
- printk(KERN_DEBUG "Registering ipic with sysfs...\n");
- rc = sysdev_class_register(&ipic_sysclass);
- if (rc) {
- printk(KERN_ERR "Failed registering ipic sys class\n");
- return -ENODEV;
- }
- rc = sysdev_register(&device_ipic);
- if (rc) {
- printk(KERN_ERR "Failed registering ipic sys device\n");
- return -ENODEV;
- }
+ printk(KERN_DEBUG "Registering ipic system core operations\n");
+ register_syscore_ops(&ipic_syscore_ops);
+
return 0;
}
-subsys_initcall(init_ipic_sysfs);
+subsys_initcall(init_ipic_syscore);
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index f91c065bed5..7e5dc8f4984 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -27,6 +27,7 @@
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/syscore_ops.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
@@ -1702,9 +1703,8 @@ void mpic_reset_core(int cpu)
#endif /* CONFIG_SMP */
#ifdef CONFIG_PM
-static int mpic_suspend(struct sys_device *dev, pm_message_t state)
+static void mpic_suspend_one(struct mpic *mpic)
{
- struct mpic *mpic = container_of(dev, struct mpic, sysdev);
int i;
for (i = 0; i < mpic->num_sources; i++) {
@@ -1713,13 +1713,22 @@ static int mpic_suspend(struct sys_device *dev, pm_message_t state)
mpic->save_data[i].dest =
mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
}
+}
+
+static int mpic_suspend(void)
+{
+ struct mpic *mpic = mpics;
+
+ while (mpic) {
+ mpic_suspend_one(mpic);
+ mpic = mpic->next;
+ }
return 0;
}
-static int mpic_resume(struct sys_device *dev)
+static void mpic_resume_one(struct mpic *mpic)
{
- struct mpic *mpic = container_of(dev, struct mpic, sysdev);
int i;
for (i = 0; i < mpic->num_sources; i++) {
@@ -1746,33 +1755,28 @@ static int mpic_resume(struct sys_device *dev)
}
#endif
} /* end for loop */
+}
- return 0;
+static void mpic_resume(void)
+{
+ struct mpic *mpic = mpics;
+
+ while (mpic) {
+ mpic_resume_one(mpic);
+ mpic = mpic->next;
+ }
}
-#endif
-static struct sysdev_class mpic_sysclass = {
-#ifdef CONFIG_PM
+static struct syscore_ops mpic_syscore_ops = {
.resume = mpic_resume,
.suspend = mpic_suspend,
-#endif
- .name = "mpic",
};
static int mpic_init_sys(void)
{
- struct mpic *mpic = mpics;
- int error, id = 0;
-
- error = sysdev_class_register(&mpic_sysclass);
-
- while (mpic && !error) {
- mpic->sysdev.cls = &mpic_sysclass;
- mpic->sysdev.id = id++;
- error = sysdev_register(&mpic->sysdev);
- mpic = mpic->next;
- }
- return error;
+ register_syscore_ops(&mpic_syscore_ops);
+ return 0;
}
device_initcall(mpic_init_sys);
+#endif
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 4b89da248d1..bc439de48cd 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -24,7 +24,6 @@ config SUPERH
select RTC_LIB
select GENERIC_ATOMIC64
select GENERIC_IRQ_SHOW
- select ARCH_NO_SYSDEV_OPS
help
The SuperH is a RISC processor targeted for use in embedded systems
and consumer electronics; it was also used in the Sega Dreamcast
diff --git a/arch/sh/configs/apsh4ad0a_defconfig b/arch/sh/configs/apsh4ad0a_defconfig
index e71a531f1e3..77ec0e7b8dd 100644
--- a/arch/sh/configs/apsh4ad0a_defconfig
+++ b/arch/sh/configs/apsh4ad0a_defconfig
@@ -48,7 +48,6 @@ CONFIG_PREEMPT=y
CONFIG_BINFMT_MISC=y
CONFIG_PM=y
CONFIG_PM_DEBUG=y
-CONFIG_PM_VERBOSE=y
CONFIG_PM_RUNTIME=y
CONFIG_CPU_IDLE=y
CONFIG_NET=y
diff --git a/arch/sh/configs/sdk7786_defconfig b/arch/sh/configs/sdk7786_defconfig
index dc4a2eb6a61..c41650572d7 100644
--- a/arch/sh/configs/sdk7786_defconfig
+++ b/arch/sh/configs/sdk7786_defconfig
@@ -83,7 +83,6 @@ CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_BINFMT_MISC=y
CONFIG_PM=y
CONFIG_PM_DEBUG=y
-CONFIG_PM_VERBOSE=y
CONFIG_PM_RUNTIME=y
CONFIG_CPU_IDLE=y
CONFIG_NET=y
diff --git a/arch/sh/kernel/cpu/shmobile/pm_runtime.c b/arch/sh/kernel/cpu/shmobile/pm_runtime.c
index 6dcb8166a64..22db127afa7 100644
--- a/arch/sh/kernel/cpu/shmobile/pm_runtime.c
+++ b/arch/sh/kernel/cpu/shmobile/pm_runtime.c
@@ -139,7 +139,7 @@ void platform_pm_runtime_suspend_idle(void)
queue_work(pm_wq, &hwblk_work);
}
-int platform_pm_runtime_suspend(struct device *dev)
+static int default_platform_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pdev_archdata *ad = &pdev->archdata;
@@ -147,7 +147,7 @@ int platform_pm_runtime_suspend(struct device *dev)
int hwblk = ad->hwblk_id;
int ret = 0;
- dev_dbg(dev, "platform_pm_runtime_suspend() [%d]\n", hwblk);
+ dev_dbg(dev, "%s() [%d]\n", __func__, hwblk);
/* ignore off-chip platform devices */
if (!hwblk)
@@ -183,20 +183,20 @@ int platform_pm_runtime_suspend(struct device *dev)
mutex_unlock(&ad->mutex);
out:
- dev_dbg(dev, "platform_pm_runtime_suspend() [%d] returns %d\n",
- hwblk, ret);
+ dev_dbg(dev, "%s() [%d] returns %d\n",
+ __func__, hwblk, ret);
return ret;
}
-int platform_pm_runtime_resume(struct device *dev)
+static int default_platform_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pdev_archdata *ad = &pdev->archdata;
int hwblk = ad->hwblk_id;
int ret = 0;
- dev_dbg(dev, "platform_pm_runtime_resume() [%d]\n", hwblk);
+ dev_dbg(dev, "%s() [%d]\n", __func__, hwblk);
/* ignore off-chip platform devices */
if (!hwblk)
@@ -228,19 +228,19 @@ int platform_pm_runtime_resume(struct device *dev)
*/
mutex_unlock(&ad->mutex);
out:
- dev_dbg(dev, "platform_pm_runtime_resume() [%d] returns %d\n",
- hwblk, ret);
+ dev_dbg(dev, "%s() [%d] returns %d\n",
+ __func__, hwblk, ret);
return ret;
}
-int platform_pm_runtime_idle(struct device *dev)
+static int default_platform_runtime_idle(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
int hwblk = pdev->archdata.hwblk_id;
int ret = 0;
- dev_dbg(dev, "platform_pm_runtime_idle() [%d]\n", hwblk);
+ dev_dbg(dev, "%s() [%d]\n", __func__, hwblk);
/* ignore off-chip platform devices */
if (!hwblk)
@@ -252,10 +252,19 @@ int platform_pm_runtime_idle(struct device *dev)
/* suspend synchronously to disable clocks immediately */
ret = pm_runtime_suspend(dev);
out:
- dev_dbg(dev, "platform_pm_runtime_idle() [%d] done!\n", hwblk);
+ dev_dbg(dev, "%s() [%d] done!\n", __func__, hwblk);
return ret;
}
+static struct dev_power_domain default_power_domain = {
+ .ops = {
+ .runtime_suspend = default_platform_runtime_suspend,
+ .runtime_resume = default_platform_runtime_resume,
+ .runtime_idle = default_platform_runtime_idle,
+ USE_PLATFORM_PM_SLEEP_OPS
+ },
+};
+
static int platform_bus_notify(struct notifier_block *nb,
unsigned long action, void *data)
{
@@ -276,6 +285,7 @@ static int platform_bus_notify(struct notifier_block *nb,
hwblk_disable(hwblk_info, hwblk);
/* make sure driver re-inits itself once */
__set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
+ dev->pwr_domain = &default_power_domain;
break;
/* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */
case BUS_NOTIFY_BOUND_DRIVER:
@@ -289,6 +299,7 @@ static int platform_bus_notify(struct notifier_block *nb,
__set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
break;
case BUS_NOTIFY_DEL_DEVICE:
+ dev->pwr_domain = NULL;
break;
}
return 0;
diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c
index 2aa30a364bb..d4efa7d679f 100644
--- a/arch/unicore32/kernel/irq.c
+++ b/arch/unicore32/kernel/irq.c
@@ -23,7 +23,7 @@
#include <linux/list.h>
#include <linux/kallsyms.h>
#include <linux/proc_fs.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/gpio.h>
#include <asm/system.h>
@@ -237,7 +237,7 @@ static struct puv3_irq_state {
unsigned int iccr;
} puv3_irq_state;
-static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state)
+static int puv3_irq_suspend(void)
{
struct puv3_irq_state *st = &puv3_irq_state;
@@ -265,7 +265,7 @@ static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
-static int puv3_irq_resume(struct sys_device *dev)
+static void puv3_irq_resume(void)
{
struct puv3_irq_state *st = &puv3_irq_state;
@@ -278,27 +278,20 @@ static int puv3_irq_resume(struct sys_device *dev)
writel(st->icmr, INTC_ICMR);
}
- return 0;
}
-static struct sysdev_class puv3_irq_sysclass = {
- .name = "pkunity-irq",
+static struct syscore_ops puv3_irq_syscore_ops = {
.suspend = puv3_irq_suspend,
.resume = puv3_irq_resume,
};
-static struct sys_device puv3_irq_device = {
- .id = 0,
- .cls = &puv3_irq_sysclass,
-};
-
-static int __init puv3_irq_init_devicefs(void)
+static int __init puv3_irq_init_syscore(void)
{
- sysdev_class_register(&puv3_irq_sysclass);
- return sysdev_register(&puv3_irq_device);
+ register_syscore_ops(&puv3_irq_syscore_ops);
+ return 0;
}
-device_initcall(puv3_irq_init_devicefs);
+device_initcall(puv3_irq_init_syscore);
void __init init_IRQ(void)
{
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e7f94a52a5d..b9ea9a80faa 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -71,7 +71,6 @@ 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)
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index ff93bc1b09c..18a857ba7a2 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -112,11 +112,6 @@ static int __init acpi_sleep_setup(char *str)
#ifdef CONFIG_HIBERNATION
if (strncmp(str, "s4_nohwsig", 10) == 0)
acpi_no_s4_hw_signature();
- if (strncmp(str, "s4_nonvs", 8) == 0) {
- pr_warning("ACPI: acpi_sleep=s4_nonvs is deprecated, "
- "please use acpi_sleep=nonvs instead");
- acpi_nvs_nosave();
- }
#endif
if (strncmp(str, "nonvs", 5) == 0)
acpi_nvs_nosave();
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index adee12e0da1..3bfa0223596 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1238,7 +1238,6 @@ static int suspend(int vetoable)
dpm_suspend_noirq(PMSG_SUSPEND);
local_irq_disable();
- sysdev_suspend(PMSG_SUSPEND);
syscore_suspend();
local_irq_enable();
@@ -1258,7 +1257,6 @@ static int suspend(int vetoable)
err = (err == APM_SUCCESS) ? 0 : -EIO;
syscore_resume();
- sysdev_resume();
local_irq_enable();
dpm_resume_noirq(PMSG_RESUME);
@@ -1282,7 +1280,6 @@ static void standby(void)
dpm_suspend_noirq(PMSG_SUSPEND);
local_irq_disable();
- sysdev_suspend(PMSG_SUSPEND);
syscore_suspend();
local_irq_enable();
@@ -1292,7 +1289,6 @@ static void standby(void)
local_irq_disable();
syscore_resume();
- sysdev_resume();
local_irq_enable();
dpm_resume_noirq(PMSG_RESUME);
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index e9e5238f310..d57e8d0fb82 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -168,11 +168,4 @@ 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
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 19f49e41ce5..a34dca0ad04 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -111,8 +111,6 @@ static inline int driver_match_device(struct device_driver *drv,
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
-extern void sysdev_shutdown(void);
-
extern char *make_class_name(const char *name, struct kobject *kobj);
extern int devres_release_all(struct device *dev);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index da57ee9d63f..29917c7506c 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -316,8 +316,7 @@ static void __device_release_driver(struct device *dev)
drv = dev->driver;
if (drv) {
- pm_runtime_get_noresume(dev);
- pm_runtime_barrier(dev);
+ pm_runtime_get_sync(dev);
driver_sysfs_remove(dev);
@@ -326,6 +325,8 @@ static void __device_release_driver(struct device *dev)
BUS_NOTIFY_UNBIND_DRIVER,
dev);
+ pm_runtime_put_sync(dev);
+
if (dev->bus && dev->bus->remove)
dev->bus->remove(dev);
else if (drv->remove)
@@ -338,7 +339,6 @@ static void __device_release_driver(struct device *dev)
BUS_NOTIFY_UNBOUND_DRIVER,
dev);
- pm_runtime_put_sync(dev);
}
}
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8c798ef7f13..bbb03e6f725 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -521,6 +521,11 @@ static int _request_firmware(const struct firmware **firmware_p,
if (!firmware_p)
return -EINVAL;
+ if (WARN_ON(usermodehelper_is_disabled())) {
+ dev_err(device, "firmware: %s will not be loaded\n", name);
+ return -EBUSY;
+ }
+
*firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
if (!firmware) {
dev_err(device, "%s: kmalloc(struct firmware) failed\n",
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 9e0e4fc24c4..48425f18302 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -667,7 +667,7 @@ static int platform_legacy_resume(struct device *dev)
return ret;
}
-static int platform_pm_prepare(struct device *dev)
+int platform_pm_prepare(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -678,7 +678,7 @@ static int platform_pm_prepare(struct device *dev)
return ret;
}
-static void platform_pm_complete(struct device *dev)
+void platform_pm_complete(struct device *dev)
{
struct device_driver *drv = dev->driver;
@@ -686,16 +686,11 @@ static void platform_pm_complete(struct device *dev)
drv->pm->complete(dev);
}
-#else /* !CONFIG_PM_SLEEP */
-
-#define platform_pm_prepare NULL
-#define platform_pm_complete NULL
-
-#endif /* !CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_SUSPEND
-int __weak platform_pm_suspend(struct device *dev)
+int platform_pm_suspend(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -713,7 +708,7 @@ int __weak platform_pm_suspend(struct device *dev)
return ret;
}
-int __weak platform_pm_suspend_noirq(struct device *dev)
+int platform_pm_suspend_noirq(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -729,7 +724,7 @@ int __weak platform_pm_suspend_noirq(struct device *dev)
return ret;
}
-int __weak platform_pm_resume(struct device *dev)
+int platform_pm_resume(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -747,7 +742,7 @@ int __weak platform_pm_resume(struct device *dev)
return ret;
}
-int __weak platform_pm_resume_noirq(struct device *dev)
+int platform_pm_resume_noirq(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -763,18 +758,11 @@ int __weak platform_pm_resume_noirq(struct device *dev)
return ret;
}
-#else /* !CONFIG_SUSPEND */
-
-#define platform_pm_suspend NULL
-#define platform_pm_resume NULL
-#define platform_pm_suspend_noirq NULL
-#define platform_pm_resume_noirq NULL
-
-#endif /* !CONFIG_SUSPEND */
+#endif /* CONFIG_SUSPEND */
#ifdef CONFIG_HIBERNATE_CALLBACKS
-static int platform_pm_freeze(struct device *dev)
+int platform_pm_freeze(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -792,7 +780,7 @@ static int platform_pm_freeze(struct device *dev)
return ret;
}
-static int platform_pm_freeze_noirq(struct device *dev)
+int platform_pm_freeze_noirq(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -808,7 +796,7 @@ static int platform_pm_freeze_noirq(struct device *dev)
return ret;
}
-static int platform_pm_thaw(struct device *dev)
+int platform_pm_thaw(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -826,7 +814,7 @@ static int platform_pm_thaw(struct device *dev)
return ret;
}
-static int platform_pm_thaw_noirq(struct device *dev)
+int platform_pm_thaw_noirq(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -842,7 +830,7 @@ static int platform_pm_thaw_noirq(struct device *dev)
return ret;
}
-static int platform_pm_poweroff(struct device *dev)
+int platform_pm_poweroff(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -860,7 +848,7 @@ static int platform_pm_poweroff(struct device *dev)
return ret;
}
-static int platform_pm_poweroff_noirq(struct device *dev)
+int platform_pm_poweroff_noirq(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -876,7 +864,7 @@ static int platform_pm_poweroff_noirq(struct device *dev)
return ret;
}
-static int platform_pm_restore(struct device *dev)
+int platform_pm_restore(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -894,7 +882,7 @@ static int platform_pm_restore(struct device *dev)
return ret;
}
-static int platform_pm_restore_noirq(struct device *dev)
+int platform_pm_restore_noirq(struct device *dev)
{
struct device_driver *drv = dev->driver;
int ret = 0;
@@ -910,62 +898,13 @@ static int platform_pm_restore_noirq(struct device *dev)
return ret;
}
-#else /* !CONFIG_HIBERNATE_CALLBACKS */
-
-#define platform_pm_freeze NULL
-#define platform_pm_thaw NULL
-#define platform_pm_poweroff NULL
-#define platform_pm_restore NULL
-#define platform_pm_freeze_noirq NULL
-#define platform_pm_thaw_noirq NULL
-#define platform_pm_poweroff_noirq NULL
-#define platform_pm_restore_noirq NULL
-
-#endif /* !CONFIG_HIBERNATE_CALLBACKS */
-
-#ifdef CONFIG_PM_RUNTIME
-
-int __weak platform_pm_runtime_suspend(struct device *dev)
-{
- return pm_generic_runtime_suspend(dev);
-};
-
-int __weak platform_pm_runtime_resume(struct device *dev)
-{
- return pm_generic_runtime_resume(dev);
-};
-
-int __weak platform_pm_runtime_idle(struct device *dev)
-{
- return pm_generic_runtime_idle(dev);
-};
-
-#else /* !CONFIG_PM_RUNTIME */
-
-#define platform_pm_runtime_suspend NULL
-#define platform_pm_runtime_resume NULL
-#define platform_pm_runtime_idle NULL
-
-#endif /* !CONFIG_PM_RUNTIME */
+#endif /* CONFIG_HIBERNATE_CALLBACKS */
static const struct dev_pm_ops platform_dev_pm_ops = {
- .prepare = platform_pm_prepare,
- .complete = platform_pm_complete,
- .suspend = platform_pm_suspend,
- .resume = platform_pm_resume,
- .freeze = platform_pm_freeze,
- .thaw = platform_pm_thaw,
- .poweroff = platform_pm_poweroff,
- .restore = platform_pm_restore,
- .suspend_noirq = platform_pm_suspend_noirq,
- .resume_noirq = platform_pm_resume_noirq,
- .freeze_noirq = platform_pm_freeze_noirq,
- .thaw_noirq = platform_pm_thaw_noirq,
- .poweroff_noirq = platform_pm_poweroff_noirq,
- .restore_noirq = platform_pm_restore_noirq,
- .runtime_suspend = platform_pm_runtime_suspend,
- .runtime_resume = platform_pm_runtime_resume,
- .runtime_idle = platform_pm_runtime_idle,
+ .runtime_suspend = pm_generic_runtime_suspend,
+ .runtime_resume = pm_generic_runtime_resume,
+ .runtime_idle = pm_generic_runtime_idle,
+ USE_PLATFORM_PM_SLEEP_OPS
};
struct bus_type platform_bus_type = {
@@ -977,41 +916,6 @@ struct bus_type platform_bus_type = {
};
EXPORT_SYMBOL_GPL(platform_bus_type);
-/**
- * platform_bus_get_pm_ops() - return pointer to busses dev_pm_ops
- *
- * This function can be used by platform code to get the current
- * set of dev_pm_ops functions used by the platform_bus_type.
- */
-const struct dev_pm_ops * __init platform_bus_get_pm_ops(void)
-{
- return platform_bus_type.pm;
-}
-
-/**
- * platform_bus_set_pm_ops() - update dev_pm_ops for the platform_bus_type
- *
- * @pm: pointer to new dev_pm_ops struct to be used for platform_bus_type
- *
- * Platform code can override the dev_pm_ops methods of
- * platform_bus_type by using this function. It is expected that
- * platform code will first do a platform_bus_get_pm_ops(), then
- * kmemdup it, then customize selected methods and pass a pointer to
- * the new struct dev_pm_ops to this function.
- *
- * Since platform-specific code is customizing methods for *all*
- * devices (not just platform-specific devices) it is expected that
- * any custom overrides of these functions will keep existing behavior
- * and simply extend it. For example, any customization of the
- * runtime PM methods should continue to call the pm_generic_*
- * functions as the default ones do in addition to the
- * platform-specific behavior.
- */
-void __init platform_bus_set_pm_ops(const struct dev_pm_ops *pm)
-{
- platform_bus_type.pm = pm;
-}
-
int __init platform_bus_init(void)
{
int error;
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index 118c1b92a51..3647e114d0e 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -3,6 +3,6 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
obj-$(CONFIG_PM_OPP) += opp.o
+obj-$(CONFIG_HAVE_CLK) += clock_ops.o
-ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
-ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG \ No newline at end of file
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
new file mode 100644
index 00000000000..c0dd09df7be
--- /dev/null
+++ b/drivers/base/power/clock_ops.c
@@ -0,0 +1,431 @@
+/*
+ * drivers/base/power/clock_ops.c - Generic clock manipulation PM callbacks
+ *
+ * Copyright (c) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#ifdef CONFIG_PM_RUNTIME
+
+struct pm_runtime_clk_data {
+ struct list_head clock_list;
+ struct mutex lock;
+};
+
+enum pce_status {
+ PCE_STATUS_NONE = 0,
+ PCE_STATUS_ACQUIRED,
+ PCE_STATUS_ENABLED,
+ PCE_STATUS_ERROR,
+};
+
+struct pm_clock_entry {
+ struct list_head node;
+ char *con_id;
+ struct clk *clk;
+ enum pce_status status;
+};
+
+static struct pm_runtime_clk_data *__to_prd(struct device *dev)
+{
+ return dev ? dev->power.subsys_data : NULL;
+}
+
+/**
+ * pm_runtime_clk_add - Start using a device clock for runtime PM.
+ * @dev: Device whose clock is going to be used for runtime PM.
+ * @con_id: Connection ID of the clock.
+ *
+ * Add the clock represented by @con_id to the list of clocks used for
+ * the runtime PM of @dev.
+ */
+int pm_runtime_clk_add(struct device *dev, const char *con_id)
+{
+ struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clock_entry *ce;
+
+ if (!prd)
+ return -EINVAL;
+
+ ce = kzalloc(sizeof(*ce), GFP_KERNEL);
+ if (!ce) {
+ dev_err(dev, "Not enough memory for clock entry.\n");
+ return -ENOMEM;
+ }
+
+ if (con_id) {
+ ce->con_id = kstrdup(con_id, GFP_KERNEL);
+ if (!ce->con_id) {
+ dev_err(dev,
+ "Not enough memory for clock connection ID.\n");
+ kfree(ce);
+ return -ENOMEM;
+ }
+ }
+
+ mutex_lock(&prd->lock);
+ list_add_tail(&ce->node, &prd->clock_list);
+ mutex_unlock(&prd->lock);
+ return 0;
+}
+
+/**
+ * __pm_runtime_clk_remove - Destroy runtime PM clock entry.
+ * @ce: Runtime PM clock entry to destroy.
+ *
+ * This routine must be called under the mutex protecting the runtime PM list
+ * of clocks corresponding the the @ce's device.
+ */
+static void __pm_runtime_clk_remove(struct pm_clock_entry *ce)
+{
+ if (!ce)
+ return;
+
+ list_del(&ce->node);
+
+ if (ce->status < PCE_STATUS_ERROR) {
+ if (ce->status == PCE_STATUS_ENABLED)
+ clk_disable(ce->clk);
+
+ if (ce->status >= PCE_STATUS_ACQUIRED)
+ clk_put(ce->clk);
+ }
+
+ if (ce->con_id)
+ kfree(ce->con_id);
+
+ kfree(ce);
+}
+
+/**
+ * pm_runtime_clk_remove - Stop using a device clock for runtime PM.
+ * @dev: Device whose clock should not be used for runtime PM any more.
+ * @con_id: Connection ID of the clock.
+ *
+ * Remove the clock represented by @con_id from the list of clocks used for
+ * the runtime PM of @dev.
+ */
+void pm_runtime_clk_remove(struct device *dev, const char *con_id)
+{
+ struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clock_entry *ce;
+
+ if (!prd)
+ return;
+
+ mutex_lock(&prd->lock);
+
+ list_for_each_entry(ce, &prd->clock_list, node) {
+ if (!con_id && !ce->con_id) {
+ __pm_runtime_clk_remove(ce);
+ break;
+ } else if (!con_id || !ce->con_id) {
+ continue;
+ } else if (!strcmp(con_id, ce->con_id)) {
+ __pm_runtime_clk_remove(ce);
+ break;
+ }
+ }
+
+ mutex_unlock(&prd->lock);
+}
+
+/**
+ * pm_runtime_clk_init - Initialize a device's list of runtime PM clocks.
+ * @dev: Device to initialize the list of runtime PM clocks for.
+ *
+ * Allocate a struct pm_runtime_clk_data object, initialize its lock member and
+ * make the @dev's power.subsys_data field point to it.
+ */
+int pm_runtime_clk_init(struct device *dev)
+{
+ struct pm_runtime_clk_data *prd;
+
+ prd = kzalloc(sizeof(*prd), GFP_KERNEL);
+ if (!prd) {
+ dev_err(dev, "Not enough memory fo runtime PM data.\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&prd->clock_list);
+ mutex_init(&prd->lock);
+ dev->power.subsys_data = prd;
+ return 0;
+}
+
+/**
+ * pm_runtime_clk_destroy - Destroy a device's list of runtime PM clocks.
+ * @dev: Device to destroy the list of runtime PM clocks for.
+ *
+ * Clear the @dev's power.subsys_data field, remove the list of clock entries
+ * from the struct pm_runtime_clk_data object pointed to by it before and free
+ * that object.
+ */
+void pm_runtime_clk_destroy(struct device *dev)
+{
+ struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clock_entry *ce, *c;
+
+ if (!prd)
+ return;
+
+ dev->power.subsys_data = NULL;
+
+ mutex_lock(&prd->lock);
+
+ list_for_each_entry_safe_reverse(ce, c, &prd->clock_list, node)
+ __pm_runtime_clk_remove(ce);
+
+ mutex_unlock(&prd->lock);
+
+ kfree(prd);
+}
+
+/**
+ * pm_runtime_clk_acquire - Acquire a device clock.
+ * @dev: Device whose clock is to be acquired.
+ * @con_id: Connection ID of the clock.
+ */
+static void pm_runtime_clk_acquire(struct device *dev,
+ struct pm_clock_entry *ce)
+{
+ ce->clk = clk_get(dev, ce->con_id);
+ if (IS_ERR(ce->clk)) {
+ ce->status = PCE_STATUS_ERROR;
+ } else {
+ ce->status = PCE_STATUS_ACQUIRED;
+ dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id);
+ }
+}
+
+/**
+ * pm_runtime_clk_suspend - Disable clocks in a device's runtime PM clock list.
+ * @dev: Device to disable the clocks for.
+ */
+int pm_runtime_clk_suspend(struct device *dev)
+{
+ struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clock_entry *ce;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ if (!prd)
+ return 0;
+
+ mutex_lock(&prd->lock);
+
+ list_for_each_entry_reverse(ce, &prd->clock_list, node) {
+ if (ce->status == PCE_STATUS_NONE)
+ pm_runtime_clk_acquire(dev, ce);
+
+ if (ce->status < PCE_STATUS_ERROR) {
+ clk_disable(ce->clk);
+ ce->status = PCE_STATUS_ACQUIRED;
+ }
+ }
+
+ mutex_unlock(&prd->lock);
+
+ return 0;
+}
+
+/**
+ * pm_runtime_clk_resume - Enable clocks in a device's runtime PM clock list.
+ * @dev: Device to enable the clocks for.
+ */
+int pm_runtime_clk_resume(struct device *dev)
+{
+ struct pm_runtime_clk_data *prd = __to_prd(dev);
+ struct pm_clock_entry *ce;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ if (!prd)
+ return 0;
+
+ mutex_lock(&prd->lock);
+
+ list_for_each_entry(ce, &prd->clock_list, node) {
+ if (ce->status == PCE_STATUS_NONE)
+ pm_runtime_clk_acquire(dev, ce);
+
+ if (ce->status < PCE_STATUS_ERROR) {
+ clk_enable(ce->clk);
+ ce->status = PCE_STATUS_ENABLED;
+ }
+ }
+
+ mutex_unlock(&prd->lock);
+
+ return 0;
+}
+
+/**
+ * pm_runtime_clk_notify - Notify routine for device addition and removal.
+ * @nb: Notifier block object this function is a member of.
+ * @action: Operation being carried out by the caller.
+ * @data: Device the routine is being run for.
+ *
+ * For this function to work, @nb must be a member of an object of type
+ * struct pm_clk_notifier_block containing all of the requisite data.
+ * Specifically, the pwr_domain member of that object is copied to the device's
+ * pwr_domain field and its con_ids member is used to populate the device's list
+ * of runtime PM clocks, depending on @action.
+ *
+ * If the device's pwr_domain field is already populated with a value different
+ * from the one stored in the struct pm_clk_notifier_block object, the function
+ * does nothing.
+ */
+static int pm_runtime_clk_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct pm_clk_notifier_block *clknb;
+ struct device *dev = data;
+ char *con_id;
+ int error;
+
+ dev_dbg(dev, "%s() %ld\n", __func__, action);
+
+ clknb = container_of(nb, struct pm_clk_notifier_block, nb);
+
+ switch (action) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ if (dev->pwr_domain)
+ break;
+
+ error = pm_runtime_clk_init(dev);
+ if (error)
+ break;
+
+ dev->pwr_domain = clknb->pwr_domain;
+ if (clknb->con_ids[0]) {
+ for (con_id = clknb->con_ids[0]; *con_id; con_id++)
+ pm_runtime_clk_add(dev, con_id);
+ } else {
+ pm_runtime_clk_add(dev, NULL);
+ }
+
+ break;
+ case BUS_NOTIFY_DEL_DEVICE:
+ if (dev->pwr_domain != clknb->pwr_domain)
+ break;
+
+ dev->pwr_domain = NULL;
+ pm_runtime_clk_destroy(dev);
+ break;
+ }
+
+ return 0;
+}
+
+#else /* !CONFIG_PM_RUNTIME */
+
+/**
+ * enable_clock - Enable a device clock.
+ * @dev: Device whose clock is to be enabled.
+ * @con_id: Connection ID of the clock.
+ */
+static void enable_clock(struct device *dev, const char *con_id)
+{
+ struct clk *clk;
+
+ clk = clk_get(dev, con_id);
+ if (!IS_ERR(clk)) {
+ clk_enable(clk);
+ clk_put(clk);
+ dev_info(dev, "Runtime PM disabled, clock forced on.\n");
+ }
+}
+
+/**
+ * disable_clock - Disable a device clock.
+ * @dev: Device whose clock is to be disabled.
+ * @con_id: Connection ID of the clock.
+ */
+static void disable_clock(struct device *dev, const char *con_id)
+{
+ struct clk *clk;
+
+ clk = clk_get(dev, con_id);
+ if (!IS_ERR(clk)) {
+ clk_disable(clk);
+ clk_put(clk);
+ dev_info(dev, "Runtime PM disabled, clock forced off.\n");
+ }
+}
+
+/**
+ * pm_runtime_clk_notify - Notify routine for device addition and removal.
+ * @nb: Notifier block object this function is a member of.
+ * @action: Operation being carried out by the caller.
+ * @data: Device the routine is being run for.
+ *
+ * For this function to work, @nb must be a member of an object of type
+ * struct pm_clk_notifier_block containing all of the requisite data.
+ * Specifically, the con_ids member of that object is used to enable or disable
+ * the device's clocks, depending on @action.
+ */
+static int pm_runtime_clk_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct pm_clk_notifier_block *clknb;
+ struct device *dev = data;
+ char *con_id;
+
+ dev_dbg(dev, "%s() %ld\n", __func__, action);
+
+ clknb = container_of(nb, struct pm_clk_notifier_block, nb);
+
+ switch (action) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ if (clknb->con_ids[0]) {
+ for (con_id = clknb->con_ids[0]; *con_id; con_id++)
+ enable_clock(dev, con_id);
+ } else {
+ enable_clock(dev, NULL);
+ }
+ break;
+ case BUS_NOTIFY_DEL_DEVICE:
+ if (clknb->con_ids[0]) {
+ for (con_id = clknb->con_ids[0]; *con_id; con_id++)
+ disable_clock(dev, con_id);
+ } else {
+ disable_clock(dev, NULL);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+#endif /* !CONFIG_PM_RUNTIME */
+
+/**
+ * pm_runtime_clk_add_notifier - Add bus type notifier for runtime PM clocks.
+ * @bus: Bus type to add the notifier to.
+ * @clknb: Notifier to be added to the given bus type.
+ *
+ * The nb member of @clknb is not expected to be initialized and its
+ * notifier_call member will be replaced with pm_runtime_clk_notify(). However,
+ * the remaining members of @clknb should be populated prior to calling this
+ * routine.
+ */
+void pm_runtime_clk_add_notifier(struct bus_type *bus,
+ struct pm_clk_notifier_block *clknb)
+{
+ if (!bus || !clknb)
+ return;
+
+ clknb->nb.notifier_call = pm_runtime_clk_notify;
+ bus_register_notifier(bus, &clknb->nb);
+}
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
index 42f97f92562..cb3bb368681 100644
--- a/drivers/base/power/generic_ops.c
+++ b/drivers/base/power/generic_ops.c
@@ -74,6 +74,23 @@ EXPORT_SYMBOL_GPL(pm_generic_runtime_resume);
#ifdef CONFIG_PM_SLEEP
/**
+ * pm_generic_prepare - Generic routine preparing a device for power transition.
+ * @dev: Device to prepare.
+ *
+ * Prepare a device for a system-wide power transition.
+ */
+int pm_generic_prepare(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+ int ret = 0;
+
+ if (drv && drv->pm && drv->pm->prepare)
+ ret = drv->pm->prepare(dev);
+
+ return ret;
+}
+
+/**
* __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback.
* @dev: Device to handle.
* @event: PM transition of the system under way.
@@ -213,16 +230,38 @@ int pm_generic_restore(struct device *dev)
return __pm_generic_resume(dev, PM_EVENT_RESTORE);
}
EXPORT_SYMBOL_GPL(pm_generic_restore);
+
+/**
+ * pm_generic_complete - Generic routine competing a device power transition.
+ * @dev: Device to handle.
+ *
+ * Complete a device power transition during a system-wide power transition.
+ */
+void pm_generic_complete(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+
+ if (drv && drv->pm && drv->pm->complete)
+ drv->pm->complete(dev);
+
+ /*
+ * Let runtime PM try to suspend devices that haven't been in use before
+ * going into the system-wide sleep state we're resuming from.
+ */
+ pm_runtime_idle(dev);
+}
#endif /* CONFIG_PM_SLEEP */
struct dev_pm_ops generic_subsys_pm_ops = {
#ifdef CONFIG_PM_SLEEP
+ .prepare = pm_generic_prepare,
.suspend = pm_generic_suspend,
.resume = pm_generic_resume,
.freeze = pm_generic_freeze,
.thaw = pm_generic_thaw,
.poweroff = pm_generic_poweroff,
.restore = pm_generic_restore,
+ .complete = pm_generic_complete,
#endif
#ifdef CONFIG_PM_RUNTIME
.runtime_suspend = pm_generic_runtime_suspend,
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index abe3ab709e8..aa632020774 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -426,10 +426,8 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
if (dev->pwr_domain) {
pm_dev_dbg(dev, state, "EARLY power domain ");
- pm_noirq_op(dev, &dev->pwr_domain->ops, state);
- }
-
- if (dev->type && dev->type->pm) {
+ error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+ } else if (dev->type && dev->type->pm) {
pm_dev_dbg(dev, state, "EARLY type ");
error = pm_noirq_op(dev, dev->type->pm, state);
} else if (dev->class && dev->class->pm) {
@@ -517,7 +515,8 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
if (dev->pwr_domain) {
pm_dev_dbg(dev, state, "power domain ");
- pm_op(dev, &dev->pwr_domain->ops, state);
+ error = pm_op(dev, &dev->pwr_domain->ops, state);
+ goto End;
}
if (dev->type && dev->type->pm) {
@@ -580,11 +579,13 @@ static bool is_async(struct device *dev)
* Execute the appropriate "resume" callback for all devices whose status
* indicates that they are suspended.
*/
-static void dpm_resume(pm_message_t state)
+void dpm_resume(pm_message_t state)
{
struct device *dev;
ktime_t starttime = ktime_get();
+ might_sleep();
+
mutex_lock(&dpm_list_mtx);
pm_transition = state;
async_error = 0;
@@ -629,12 +630,11 @@ static void device_complete(struct device *dev, pm_message_t state)
{
device_lock(dev);
- if (dev->pwr_domain && dev->pwr_domain->ops.complete) {
+ if (dev->pwr_domain) {
pm_dev_dbg(dev, state, "completing power domain ");
- dev->pwr_domain->ops.complete(dev);
- }
-
- if (dev->type && dev->type->pm) {
+ if (dev->pwr_domain->ops.complete)
+ dev->pwr_domain->ops.complete(dev);
+ } else if (dev->type && dev->type->pm) {
pm_dev_dbg(dev, state, "completing type ");
if (dev->type->pm->complete)
dev->type->pm->complete(dev);
@@ -658,10 +658,12 @@ static void device_complete(struct device *dev, pm_message_t state)
* Execute the ->complete() callbacks for all devices whose PM status is not
* DPM_ON (this allows new devices to be registered).
*/
-static void dpm_complete(pm_message_t state)
+void dpm_complete(pm_message_t state)
{
struct list_head list;
+ might_sleep();
+
INIT_LIST_HEAD(&list);
mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_prepared_list)) {
@@ -690,7 +692,6 @@ static void dpm_complete(pm_message_t state)
*/
void dpm_resume_end(pm_message_t state)
{
- might_sleep();
dpm_resume(state);
dpm_complete(state);
}
@@ -732,7 +733,12 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
{
int error;
- if (dev->type && dev->type->pm) {
+ if (dev->pwr_domain) {
+ pm_dev_dbg(dev, state, "LATE power domain ");
+ error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+ if (error)
+ return error;
+ } else if (dev->type && dev->type->pm) {
pm_dev_dbg(dev, state, "LATE type ");
error = pm_noirq_op(dev, dev->type->pm, state);
if (error)
@@ -749,11 +755,6 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
return error;
}
- if (dev->pwr_domain) {
- pm_dev_dbg(dev, state, "LATE power domain ");
- pm_noirq_op(dev, &dev->pwr_domain->ops, state);
- }
-
return 0;
}
@@ -841,21 +842,27 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
goto End;
}
+ if (dev->pwr_domain) {
+ pm_dev_dbg(dev, state, "power domain ");
+ error = pm_op(dev, &dev->pwr_domain->ops, state);
+ goto End;
+ }
+
if (dev->type && dev->type->pm) {
pm_dev_dbg(dev, state, "type ");
error = pm_op(dev, dev->type->pm, state);
- goto Domain;
+ goto End;
}
if (dev->class) {
if (dev->class->pm) {
pm_dev_dbg(dev, state, "class ");
error = pm_op(dev, dev->class->pm, state);
- goto Domain;
+ goto End;
} else if (dev->class->suspend) {
pm_dev_dbg(dev, state, "legacy class ");
error = legacy_suspend(dev, state, dev->class->suspend);
- goto Domain;
+ goto End;
}
}
@@ -869,12 +876,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
}
}
- Domain:
- if (!error && dev->pwr_domain) {
- pm_dev_dbg(dev, state, "power domain ");
- pm_op(dev, &dev->pwr_domain->ops, state);
- }
-
End:
device_unlock(dev);
complete_all(&dev->power.completion);
@@ -914,11 +915,13 @@ static int device_suspend(struct device *dev)
* dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
* @state: PM transition of the system being carried out.
*/
-static int dpm_suspend(pm_message_t state)
+int dpm_suspend(pm_message_t state)
{
ktime_t starttime = ktime_get();
int error = 0;
+ might_sleep();
+
mutex_lock(&dpm_list_mtx);
pm_transition = state;
async_error = 0;
@@ -965,7 +968,14 @@ static int device_prepare(struct device *dev, pm_message_t state)
device_lock(dev);
- if (dev->type && dev->type->pm) {
+ if (dev->pwr_domain) {
+ pm_dev_dbg(dev, state, "preparing power domain ");
+ if (dev->pwr_domain->ops.prepare)
+ error = dev->pwr_domain->ops.prepare(dev);
+ suspend_report_result(dev->pwr_domain->ops.prepare, error);
+ if (error)
+ goto End;
+ } else if (dev->type && dev->type->pm) {
pm_dev_dbg(dev, state, "preparing type ");
if (dev->type->pm->prepare)
error = dev->type->pm->prepare(dev);
@@ -984,13 +994,6 @@ static int device_prepare(struct device *dev, pm_message_t state)
if (dev->bus->pm->prepare)
error = dev->bus->pm->prepare(dev);
suspend_report_result(dev->bus->pm->prepare, error);
- if (error)
- goto End;
- }
-
- if (dev->pwr_domain && dev->pwr_domain->ops.prepare) {
- pm_dev_dbg(dev, state, "preparing power domain ");
- dev->pwr_domain->ops.prepare(dev);
}
End:
@@ -1005,10 +1008,12 @@ static int device_prepare(struct device *dev, pm_message_t state)
*
* Execute the ->prepare() callback(s) for all devices.
*/
-static int dpm_prepare(pm_message_t state)
+int dpm_prepare(pm_message_t state)
{
int error = 0;
+ might_sleep();
+
mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_list)) {
struct device *dev = to_device(dpm_list.next);
@@ -1057,7 +1062,6 @@ int dpm_suspend_start(pm_message_t state)
{
int error;
- might_sleep();
error = dpm_prepare(state);
if (!error)
error = dpm_suspend(state);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 3172c60d23a..0d4587b15c5 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -168,7 +168,6 @@ static int rpm_check_suspend_allowed(struct device *dev)
static int rpm_idle(struct device *dev, int rpmflags)
{
int (*callback)(struct device *);
- int (*domain_callback)(struct device *);
int retval;
retval = rpm_check_suspend_allowed(dev);
@@ -214,7 +213,9 @@ static int rpm_idle(struct device *dev, int rpmflags)
dev->power.idle_notification = true;
- if (dev->type && dev->type->pm)
+ if (dev->pwr_domain)
+ callback = dev->pwr_domain->ops.runtime_idle;
+ else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_idle;
else if (dev->class && dev->class->pm)
callback = dev->class->pm->runtime_idle;
@@ -223,19 +224,10 @@ static int rpm_idle(struct device *dev, int rpmflags)
else
callback = NULL;
- if (dev->pwr_domain)
- domain_callback = dev->pwr_domain->ops.runtime_idle;
- else
- domain_callback = NULL;
-
- if (callback || domain_callback) {
+ if (callback) {
spin_unlock_irq(&dev->power.lock);
- if (domain_callback)
- retval = domain_callback(dev);
-
- if (!retval && callback)
- callback(dev);
+ callback(dev);
spin_lock_irq(&dev->power.lock);
}
@@ -382,7 +374,9 @@ static int rpm_suspend(struct device *dev, int rpmflags)
__update_runtime_status(dev, RPM_SUSPENDING);
- if (dev->type && dev->type->pm)
+ if (dev->pwr_domain)
+ callback = dev->pwr_domain->ops.runtime_suspend;
+ else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_suspend;
else if (dev->class && dev->class->pm)
callback = dev->class->pm->runtime_suspend;
@@ -400,8 +394,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
else
pm_runtime_cancel_pending(dev);
} else {
- if (dev->pwr_domain)
- rpm_callback(dev->pwr_domain->ops.runtime_suspend, dev);
no_callback:
__update_runtime_status(dev, RPM_SUSPENDED);
pm_runtime_deactivate_timer(dev);
@@ -582,9 +574,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
__update_runtime_status(dev, RPM_RESUMING);
if (dev->pwr_domain)
- rpm_callback(dev->pwr_domain->ops.runtime_resume, dev);
-
- if (dev->type && dev->type->pm)
+ callback = dev->pwr_domain->ops.runtime_resume;
+ else if (dev->type && dev->type->pm)
callback = dev->type->pm->runtime_resume;
else if (dev->class && dev->class->pm)
callback = dev->class->pm->runtime_resume;
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index fff49bee781..a9f5b897961 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -212,8 +212,9 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev,
static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
autosuspend_delay_ms_store);
-#endif
+#endif /* CONFIG_PM_RUNTIME */
+#ifdef CONFIG_PM_SLEEP
static ssize_t
wake_show(struct device * dev, struct device_attribute *attr, char * buf)
{
@@ -248,7 +249,6 @@ wake_store(struct device * dev, struct device_attribute *attr,
static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
-#ifdef CONFIG_PM_SLEEP
static ssize_t wakeup_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index abbbd33e8d8..84f7c7d5a09 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -110,7 +110,6 @@ void wakeup_source_add(struct wakeup_source *ws)
spin_lock_irq(&events_lock);
list_add_rcu(&ws->entry, &wakeup_sources);
spin_unlock_irq(&events_lock);
- synchronize_rcu();
}
EXPORT_SYMBOL_GPL(wakeup_source_add);
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index acde9b5ee13..9dff77bfe1e 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -328,203 +328,8 @@ void sysdev_unregister(struct sys_device *sysdev)
kobject_put(&sysdev->kobj);
}
-
-#ifndef CONFIG_ARCH_NO_SYSDEV_OPS
-/**
- * sysdev_shutdown - Shut down all system devices.
- *
- * Loop over each class of system devices, and the devices in each
- * of those classes. For each device, we call the shutdown method for
- * each driver registered for the device - the auxiliaries,
- * and the class driver.
- *
- * Note: The list is iterated in reverse order, so that we shut down
- * child devices before we shut down their parents. The list ordering
- * is guaranteed by virtue of the fact that child devices are registered
- * after their parents.
- */
-void sysdev_shutdown(void)
-{
- struct sysdev_class *cls;
-
- pr_debug("Shutting Down System Devices\n");
-
- mutex_lock(&sysdev_drivers_lock);
- list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
- struct sys_device *sysdev;
-
- pr_debug("Shutting down type '%s':\n",
- kobject_name(&cls->kset.kobj));
-
- list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
- struct sysdev_driver *drv;
- pr_debug(" %s\n", kobject_name(&sysdev->kobj));
-
- /* Call auxiliary drivers first */
- list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->shutdown)
- drv->shutdown(sysdev);
- }
-
- /* Now call the generic one */
- if (cls->shutdown)
- cls->shutdown(sysdev);
- }
- }
- mutex_unlock(&sysdev_drivers_lock);
-}
-
-static void __sysdev_resume(struct sys_device *dev)
-{
- struct sysdev_class *cls = dev->cls;
- struct sysdev_driver *drv;
-
- /* First, call the class-specific one */
- if (cls->resume)
- cls->resume(dev);
- WARN_ONCE(!irqs_disabled(),
- "Interrupts enabled after %pF\n", cls->resume);
-
- /* Call auxiliary drivers next. */
- list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->resume)
- drv->resume(dev);
- WARN_ONCE(!irqs_disabled(),
- "Interrupts enabled after %pF\n", drv->resume);
- }
-}
-
-/**
- * sysdev_suspend - Suspend all system devices.
- * @state: Power state to enter.
- *
- * We perform an almost identical operation as sysdev_shutdown()
- * above, though calling ->suspend() instead. Interrupts are disabled
- * when this called. Devices are responsible for both saving state and
- * quiescing or powering down the device.
- *
- * This is only called by the device PM core, so we let them handle
- * all synchronization.
- */
-int sysdev_suspend(pm_message_t state)
-{
- struct sysdev_class *cls;
- struct sys_device *sysdev, *err_dev;
- struct sysdev_driver *drv, *err_drv;
- int ret;
-
- pr_debug("Checking wake-up interrupts\n");
-
- /* Return error code if there are any wake-up interrupts pending */
- ret = check_wakeup_irqs();
- if (ret)
- return ret;
-
- WARN_ONCE(!irqs_disabled(),
- "Interrupts enabled while suspending system devices\n");
-
- pr_debug("Suspending System Devices\n");
-
- list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
- pr_debug("Suspending type '%s':\n",
- kobject_name(&cls->kset.kobj));
-
- list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
- pr_debug(" %s\n", kobject_name(&sysdev->kobj));
-
- /* Call auxiliary drivers first */
- list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->suspend) {
- ret = drv->suspend(sysdev, state);
- if (ret)
- goto aux_driver;
- }
- WARN_ONCE(!irqs_disabled(),
- "Interrupts enabled after %pF\n",
- drv->suspend);
- }
-
- /* Now call the generic one */
- if (cls->suspend) {
- ret = cls->suspend(sysdev, state);
- if (ret)
- goto cls_driver;
- WARN_ONCE(!irqs_disabled(),
- "Interrupts enabled after %pF\n",
- cls->suspend);
- }
- }
- }
- return 0;
- /* resume current sysdev */
-cls_driver:
- drv = NULL;
- printk(KERN_ERR "Class suspend failed for %s: %d\n",
- kobject_name(&sysdev->kobj), ret);
-
-aux_driver:
- if (drv)
- printk(KERN_ERR "Class driver suspend failed for %s: %d\n",
- kobject_name(&sysdev->kobj), ret);
- list_for_each_entry(err_drv, &cls->drivers, entry) {
- if (err_drv == drv)
- break;
- if (err_drv->resume)
- err_drv->resume(sysdev);
- }
-
- /* resume other sysdevs in current class */
- list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
- if (err_dev == sysdev)
- break;
- pr_debug(" %s\n", kobject_name(&err_dev->kobj));
- __sysdev_resume(err_dev);
- }
-
- /* resume other classes */
- list_for_each_entry_continue(cls, &system_kset->list, kset.kobj.entry) {
- list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
- pr_debug(" %s\n", kobject_name(&err_dev->kobj));
- __sysdev_resume(err_dev);
- }
- }
- return ret;
-}
-EXPORT_SYMBOL_GPL(sysdev_suspend);
-
-/**
- * sysdev_resume - Bring system devices back to life.
- *
- * Similar to sysdev_suspend(), but we iterate the list forwards
- * to guarantee that parent devices are resumed before their children.
- *
- * Note: Interrupts are disabled when called.
- */
-int sysdev_resume(void)
-{
- struct sysdev_class *cls;
-
- WARN_ONCE(!irqs_disabled(),
- "Interrupts enabled while resuming system devices\n");
-
- pr_debug("Resuming System Devices\n");
-
- list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) {
- struct sys_device *sysdev;
-
- pr_debug("Resuming type '%s':\n",
- kobject_name(&cls->kset.kobj));
-
- list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
- pr_debug(" %s\n", kobject_name(&sysdev->kobj));
-
- __sysdev_resume(sysdev);
- }
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(sysdev_resume);
-#endif /* CONFIG_ARCH_NO_SYSDEV_OPS */
+EXPORT_SYMBOL_GPL(sysdev_register);
+EXPORT_SYMBOL_GPL(sysdev_unregister);
int __init system_bus_init(void)
{
@@ -534,9 +339,6 @@ int __init system_bus_init(void)
return 0;
}
-EXPORT_SYMBOL_GPL(sysdev_register);
-EXPORT_SYMBOL_GPL(sysdev_unregister);
-
#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
ssize_t sysdev_store_ulong(struct sys_device *sysdev,
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index a2eee574784..0b5366b5be2 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -70,12 +70,7 @@ static int xen_suspend(void *data)
BUG_ON(!irqs_disabled());
- err = sysdev_suspend(PMSG_FREEZE);
- if (!err) {
- err = syscore_suspend();
- if (err)
- sysdev_resume();
- }
+ err = syscore_suspend();
if (err) {
printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n",
err);
@@ -102,7 +97,6 @@ static int xen_suspend(void *data)
}
syscore_resume();
- sysdev_resume();
return 0;
}
diff --git a/include/linux/device.h b/include/linux/device.h
index d08399db6e2..0d753500082 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -632,13 +632,6 @@ static inline int devtmpfs_mount(const char *mountpoint) { return 0; }
/* 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);
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 6efd7a78de6..31023182385 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -113,5 +113,6 @@ extern void usermodehelper_init(void);
extern int usermodehelper_disable(void);
extern void usermodehelper_enable(void);
+extern bool usermodehelper_is_disabled(void);
#endif /* __LINUX_KMOD_H__ */
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 744942c95fe..ede1a80e335 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -150,9 +150,6 @@ extern struct platform_device *platform_create_bundle(struct platform_driver *dr
struct resource *res, unsigned int n_res,
const void *data, size_t size);
-extern const struct dev_pm_ops * platform_bus_get_pm_ops(void);
-extern void platform_bus_set_pm_ops(const struct dev_pm_ops *pm);
-
/* early platform driver interface */
struct early_platform_driver {
const char *class_str;
@@ -205,4 +202,64 @@ static inline char *early_platform_driver_setup_func(void) \
}
#endif /* MODULE */
+#ifdef CONFIG_PM_SLEEP
+extern int platform_pm_prepare(struct device *dev);
+extern void platform_pm_complete(struct device *dev);
+#else
+#define platform_pm_prepare NULL
+#define platform_pm_complete NULL
+#endif
+
+#ifdef CONFIG_SUSPEND
+extern int platform_pm_suspend(struct device *dev);
+extern int platform_pm_suspend_noirq(struct device *dev);
+extern int platform_pm_resume(struct device *dev);
+extern int platform_pm_resume_noirq(struct device *dev);
+#else
+#define platform_pm_suspend NULL
+#define platform_pm_resume NULL
+#define platform_pm_suspend_noirq NULL
+#define platform_pm_resume_noirq NULL
+#endif
+
+#ifdef CONFIG_HIBERNATE_CALLBACKS
+extern int platform_pm_freeze(struct device *dev);
+extern int platform_pm_freeze_noirq(struct device *dev);
+extern int platform_pm_thaw(struct device *dev);
+extern int platform_pm_thaw_noirq(struct device *dev);
+extern int platform_pm_poweroff(struct device *dev);
+extern int platform_pm_poweroff_noirq(struct device *dev);
+extern int platform_pm_restore(struct device *dev);
+extern int platform_pm_restore_noirq(struct device *dev);
+#else
+#define platform_pm_freeze NULL
+#define platform_pm_thaw NULL
+#define platform_pm_poweroff NULL
+#define platform_pm_restore NULL
+#define platform_pm_freeze_noirq NULL
+#define platform_pm_thaw_noirq NULL
+#define platform_pm_poweroff_noirq NULL
+#define platform_pm_restore_noirq NULL
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+#define USE_PLATFORM_PM_SLEEP_OPS \
+ .prepare = platform_pm_prepare, \
+ .complete = platform_pm_complete, \
+ .suspend = platform_pm_suspend, \
+ .resume = platform_pm_resume, \
+ .freeze = platform_pm_freeze, \
+ .thaw = platform_pm_thaw, \
+ .poweroff = platform_pm_poweroff, \
+ .restore = platform_pm_restore, \
+ .suspend_noirq = platform_pm_suspend_noirq, \
+ .resume_noirq = platform_pm_resume_noirq, \
+ .freeze_noirq = platform_pm_freeze_noirq, \
+ .thaw_noirq = platform_pm_thaw_noirq, \
+ .poweroff_noirq = platform_pm_poweroff_noirq, \
+ .restore_noirq = platform_pm_restore_noirq,
+#else
+#define USE_PLATFORM_PM_SLEEP_OPS
+#endif
+
#endif /* _PLATFORM_DEVICE_H_ */
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 512e09177e5..3160648ccdd 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -460,6 +460,7 @@ struct dev_pm_info {
unsigned long active_jiffies;
unsigned long suspended_jiffies;
unsigned long accounting_timestamp;
+ void *subsys_data; /* Owned by the subsystem. */
#endif
};
@@ -529,21 +530,17 @@ struct dev_power_domain {
*/
#ifdef CONFIG_PM_SLEEP
-#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 dpm_resume(pm_message_t state);
+extern void dpm_complete(pm_message_t state);
extern void device_pm_unlock(void);
extern int dpm_suspend_noirq(pm_message_t state);
extern int dpm_suspend_start(pm_message_t state);
+extern int dpm_suspend(pm_message_t state);
+extern int dpm_prepare(pm_message_t state);
extern void __suspend_report_result(const char *function, void *fn, int ret);
@@ -553,6 +550,16 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
} while (0)
extern int device_pm_wait_for_dev(struct device *sub, struct device *dev);
+
+extern int pm_generic_prepare(struct device *dev);
+extern int pm_generic_suspend(struct device *dev);
+extern int pm_generic_resume(struct device *dev);
+extern int pm_generic_freeze(struct device *dev);
+extern int pm_generic_thaw(struct device *dev);
+extern int pm_generic_restore(struct device *dev);
+extern int pm_generic_poweroff(struct device *dev);
+extern void pm_generic_complete(struct device *dev);
+
#else /* !CONFIG_PM_SLEEP */
#define device_pm_lock() do {} while (0)
@@ -569,6 +576,15 @@ static inline int device_pm_wait_for_dev(struct device *a, struct device *b)
{
return 0;
}
+
+#define pm_generic_prepare NULL
+#define pm_generic_suspend NULL
+#define pm_generic_resume NULL
+#define pm_generic_freeze NULL
+#define pm_generic_thaw NULL
+#define pm_generic_restore NULL
+#define pm_generic_poweroff NULL
+#define pm_generic_complete NULL
#endif /* !CONFIG_PM_SLEEP */
/* How to reorder dpm_list after device_move() */
@@ -579,11 +595,4 @@ enum dpm_order {
DPM_ORDER_DEV_LAST,
};
-extern int pm_generic_suspend(struct device *dev);
-extern int pm_generic_resume(struct device *dev);
-extern int pm_generic_freeze(struct device *dev);
-extern int pm_generic_thaw(struct device *dev);
-extern int pm_generic_restore(struct device *dev);
-extern int pm_generic_poweroff(struct device *dev);
-
#endif /* _LINUX_PM_H */
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index 8de9aa6e7de..878cf84baeb 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -245,4 +245,46 @@ static inline void pm_runtime_dont_use_autosuspend(struct device *dev)
__pm_runtime_use_autosuspend(dev, false);
}
+struct pm_clk_notifier_block {
+ struct notifier_block nb;
+ struct dev_power_domain *pwr_domain;
+ char *con_ids[];
+};
+
+#ifdef CONFIG_PM_RUNTIME_CLK
+extern int pm_runtime_clk_init(struct device *dev);
+extern void pm_runtime_clk_destroy(struct device *dev);
+extern int pm_runtime_clk_add(struct device *dev, const char *con_id);
+extern void pm_runtime_clk_remove(struct device *dev, const char *con_id);
+extern int pm_runtime_clk_suspend(struct device *dev);
+extern int pm_runtime_clk_resume(struct device *dev);
+#else
+static inline int pm_runtime_clk_init(struct device *dev)
+{
+ return -EINVAL;
+}
+static inline void pm_runtime_clk_destroy(struct device *dev)
+{
+}
+static inline int pm_runtime_clk_add(struct device *dev, const char *con_id)
+{
+ return -EINVAL;
+}
+static inline void pm_runtime_clk_remove(struct device *dev, const char *con_id)
+{
+}
+#define pm_runtime_clock_suspend NULL
+#define pm_runtime_clock_resume NULL
+#endif
+
+#ifdef CONFIG_HAVE_CLK
+extern void pm_runtime_clk_add_notifier(struct bus_type *bus,
+ struct pm_clk_notifier_block *clknb);
+#else
+static inline void pm_runtime_clk_add_notifier(struct bus_type *bus,
+ struct pm_clk_notifier_block *clknb)
+{
+}
+#endif
+
#endif
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index dfb078db8eb..d35e783a598 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -34,12 +34,6 @@ struct sysdev_class {
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 *);
-#endif
};
struct sysdev_class_attribute {
@@ -77,11 +71,6 @@ 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
};
diff --git a/kernel/freezer.c b/kernel/freezer.c
index 66ecd2ead21..7b01de98bb6 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -17,7 +17,7 @@ static inline void frozen_process(void)
{
if (!unlikely(current->flags & PF_NOFREEZE)) {
current->flags |= PF_FROZEN;
- wmb();
+ smp_wmb();
}
clear_freeze_flag(current);
}
@@ -93,7 +93,7 @@ bool freeze_task(struct task_struct *p, bool sig_only)
* the task as frozen and next clears its TIF_FREEZE.
*/
if (!freezing(p)) {
- rmb();
+ smp_rmb();
if (frozen(p))
return false;
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 87b77de03dd..8d814cbc810 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1531,13 +1531,7 @@ int kernel_kexec(void)
if (error)
goto Enable_cpus;
local_irq_disable();
- /* Suspend system devices */
- error = sysdev_suspend(PMSG_FREEZE);
- if (!error) {
- error = syscore_suspend();
- if (error)
- sysdev_resume();
- }
+ error = syscore_suspend();
if (error)
goto Enable_irqs;
} else
@@ -1553,7 +1547,6 @@ int kernel_kexec(void)
#ifdef CONFIG_KEXEC_JUMP
if (kexec_image->preserve_context) {
syscore_resume();
- sysdev_resume();
Enable_irqs:
local_irq_enable();
Enable_cpus:
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 9cd0591c96a..5ae0ff38425 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -245,7 +245,6 @@ static void __call_usermodehelper(struct work_struct *work)
}
}
-#ifdef CONFIG_PM_SLEEP
/*
* If set, call_usermodehelper_exec() will exit immediately returning -EBUSY
* (used for preventing user land processes from being created after the user
@@ -301,6 +300,15 @@ void usermodehelper_enable(void)
usermodehelper_disabled = 0;
}
+/**
+ * usermodehelper_is_disabled - check if new helpers are allowed to be started
+ */
+bool usermodehelper_is_disabled(void)
+{
+ return usermodehelper_disabled;
+}
+EXPORT_SYMBOL_GPL(usermodehelper_is_disabled);
+
static void helper_lock(void)
{
atomic_inc(&running_helpers);
@@ -312,12 +320,6 @@ static void helper_unlock(void)
if (atomic_dec_and_test(&running_helpers))
wake_up(&running_helpers_waitq);
}
-#else /* CONFIG_PM_SLEEP */
-#define usermodehelper_disabled 0
-
-static inline void helper_lock(void) {}
-static inline void helper_unlock(void) {}
-#endif /* CONFIG_PM_SLEEP */
/**
* call_usermodehelper_setup - prepare to call a usermode helper
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 6de9a8fc341..87f4d24b55b 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -125,12 +125,6 @@ config PM_DEBUG
code. This is helpful when debugging and reporting PM bugs, like
suspend support.
-config PM_VERBOSE
- bool "Verbose Power Management debugging"
- depends on PM_DEBUG
- ---help---
- This option enables verbose messages from the Power Management code.
-
config PM_ADVANCED_DEBUG
bool "Extra PM attributes in sysfs for low-level debugging/testing"
depends on PM_DEBUG
@@ -229,3 +223,7 @@ config PM_OPP
representing individual voltage domains and provides SOC
implementations a ready to use framework to manage OPPs.
For more information, read <file:Documentation/power/opp.txt>
+
+config PM_RUNTIME_CLK
+ def_bool y
+ depends on PM_RUNTIME && HAVE_CLK
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 50aae660174..f9bec56d882 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -272,12 +272,7 @@ static int create_image(int platform_mode)
local_irq_disable();
- error = sysdev_suspend(PMSG_FREEZE);
- if (!error) {
- error = syscore_suspend();
- if (error)
- sysdev_resume();
- }
+ error = syscore_suspend();
if (error) {
printk(KERN_ERR "PM: Some system devices failed to power down, "
"aborting hibernation\n");
@@ -302,7 +297,6 @@ static int create_image(int platform_mode)
Power_up:
syscore_resume();
- sysdev_resume();
/* NOTE: dpm_resume_noirq() is just a resume() for devices
* that suspended with irqs off ... no overall powerup.
*/
@@ -333,20 +327,25 @@ static int create_image(int platform_mode)
int hibernation_snapshot(int platform_mode)
{
+ pm_message_t msg = PMSG_RECOVER;
int error;
error = platform_begin(platform_mode);
if (error)
goto Close;
+ error = dpm_prepare(PMSG_FREEZE);
+ if (error)
+ goto Complete_devices;
+
/* Preallocate image memory before shutting down devices. */
error = hibernate_preallocate_memory();
if (error)
- goto Close;
+ goto Complete_devices;
suspend_console();
pm_restrict_gfp_mask();
- error = dpm_suspend_start(PMSG_FREEZE);
+ error = dpm_suspend(PMSG_FREEZE);
if (error)
goto Recover_platform;
@@ -364,13 +363,17 @@ int hibernation_snapshot(int platform_mode)
if (error || !in_suspend)
swsusp_free();
- dpm_resume_end(in_suspend ?
- (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
+ msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE;
+ dpm_resume(msg);
if (error || !in_suspend)
pm_restore_gfp_mask();
resume_console();
+
+ Complete_devices:
+ dpm_complete(msg);
+
Close:
platform_end(platform_mode);
return error;
@@ -409,12 +412,7 @@ static int resume_target_kernel(bool platform_mode)
local_irq_disable();
- error = sysdev_suspend(PMSG_QUIESCE);
- if (!error) {
- error = syscore_suspend();
- if (error)
- sysdev_resume();
- }
+ error = syscore_suspend();
if (error)
goto Enable_irqs;
@@ -442,7 +440,6 @@ static int resume_target_kernel(bool platform_mode)
touch_softlockup_watchdog();
syscore_resume();
- sysdev_resume();
Enable_irqs:
local_irq_enable();
@@ -528,7 +525,6 @@ int hibernation_platform_enter(void)
goto Platform_finish;
local_irq_disable();
- sysdev_suspend(PMSG_HIBERNATE);
syscore_suspend();
if (pm_wakeup_pending()) {
error = -EAGAIN;
@@ -541,7 +537,6 @@ int hibernation_platform_enter(void)
Power_up:
syscore_resume();
- sysdev_resume();
local_irq_enable();
enable_nonboot_cpus();
@@ -982,10 +977,33 @@ static ssize_t image_size_store(struct kobject *kobj, struct kobj_attribute *att
power_attr(image_size);
+static ssize_t reserved_size_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%lu\n", reserved_size);
+}
+
+static ssize_t reserved_size_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned long size;
+
+ if (sscanf(buf, "%lu", &size) == 1) {
+ reserved_size = size;
+ return n;
+ }
+
+ return -EINVAL;
+}
+
+power_attr(reserved_size);
+
static struct attribute * g[] = {
&disk_attr.attr,
&resume_attr.attr,
&image_size_attr.attr,
+ &reserved_size_attr.attr,
NULL,
};
diff --git a/kernel/power/main.c b/kernel/power/main.c
index de9aef8742f..2981af4ce7c 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -337,6 +337,7 @@ static int __init pm_init(void)
if (error)
return error;
hibernate_image_size_init();
+ hibernate_reserved_size_init();
power_kobj = kobject_create_and_add("power", NULL);
if (!power_kobj)
return -ENOMEM;
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 03634be55f6..9a00a0a2628 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -15,6 +15,7 @@ struct swsusp_info {
#ifdef CONFIG_HIBERNATION
/* kernel/power/snapshot.c */
+extern void __init hibernate_reserved_size_init(void);
extern void __init hibernate_image_size_init(void);
#ifdef CONFIG_ARCH_HIBERNATION_HEADER
@@ -55,6 +56,7 @@ extern int hibernation_platform_enter(void);
#else /* !CONFIG_HIBERNATION */
+static inline void hibernate_reserved_size_init(void) {}
static inline void hibernate_image_size_init(void) {}
#endif /* !CONFIG_HIBERNATION */
@@ -72,6 +74,8 @@ static struct kobj_attribute _name##_attr = { \
/* Preferred image size in bytes (default 500 MB) */
extern unsigned long image_size;
+/* Size of memory reserved for drivers (default SPARE_PAGES x PAGE_SIZE) */
+extern unsigned long reserved_size;
extern int in_suspend;
extern dev_t swsusp_resume_device;
extern sector_t swsusp_resume_block;
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index ca0aacc2487..ace55889f70 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -41,16 +41,28 @@ static void swsusp_set_page_forbidden(struct page *);
static void swsusp_unset_page_forbidden(struct page *);
/*
+ * Number of bytes to reserve for memory allocations made by device drivers
+ * from their ->freeze() and ->freeze_noirq() callbacks so that they don't
+ * cause image creation to fail (tunable via /sys/power/reserved_size).
+ */
+unsigned long reserved_size;
+
+void __init hibernate_reserved_size_init(void)
+{
+ reserved_size = SPARE_PAGES * PAGE_SIZE;
+}
+
+/*
* Preferred image size in bytes (tunable via /sys/power/image_size).
- * When it is set to N, the image creating code will do its best to
- * ensure the image size will not exceed N bytes, but if that is
- * impossible, it will try to create the smallest image possible.
+ * When it is set to N, swsusp will do its best to ensure the image
+ * size will not exceed N bytes, but if that is impossible, it will
+ * try to create the smallest image possible.
*/
unsigned long image_size;
void __init hibernate_image_size_init(void)
{
- image_size = (totalram_pages / 3) * PAGE_SIZE;
+ image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE;
}
/* List of PBEs needed for restoring the pages that were allocated before
@@ -1263,11 +1275,13 @@ static unsigned long minimum_image_size(unsigned long saveable)
* frame in use. We also need a number of page frames to be free during
* hibernation for allocations made while saving the image and for device
* drivers, in case they need to allocate memory from their hibernation
- * callbacks (these two numbers are given by PAGES_FOR_IO and SPARE_PAGES,
- * respectively, both of which are rough estimates). To make this happen, we
- * compute the total number of available page frames and allocate at least
+ * callbacks (these two numbers are given by PAGES_FOR_IO (which is a rough
+ * estimate) and reserverd_size divided by PAGE_SIZE (which is tunable through
+ * /sys/power/reserved_size, respectively). To make this happen, we compute the
+ * total number of available page frames and allocate at least
*
- * ([page frames total] + PAGES_FOR_IO + [metadata pages]) / 2 + 2 * SPARE_PAGES
+ * ([page frames total] + PAGES_FOR_IO + [metadata pages]) / 2
+ * + 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE)
*
* of them, which corresponds to the maximum size of a hibernation image.
*
@@ -1322,7 +1336,8 @@ int hibernate_preallocate_memory(void)
count -= totalreserve_pages;
/* Compute the maximum number of saveable pages to leave in memory. */
- max_size = (count - (size + PAGES_FOR_IO)) / 2 - 2 * SPARE_PAGES;
+ max_size = (count - (size + PAGES_FOR_IO)) / 2
+ - 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE);
/* Compute the desired number of image pages specified by image_size. */
size = DIV_ROUND_UP(image_size, PAGE_SIZE);
if (size > max_size)
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 6275970b218..1c41ba21541 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -163,19 +163,13 @@ static int suspend_enter(suspend_state_t state)
arch_suspend_disable_irqs();
BUG_ON(!irqs_disabled());
- error = sysdev_suspend(PMSG_SUSPEND);
- if (!error) {
- error = syscore_suspend();
- if (error)
- sysdev_resume();
- }
+ error = syscore_suspend();
if (!error) {
if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) {
error = suspend_ops->enter(state);
events_check_enabled = false;
}
syscore_resume();
- sysdev_resume();
}
arch_suspend_enable_irqs();
@@ -226,7 +220,7 @@ int suspend_devices_and_enter(suspend_state_t state)
if (suspend_test(TEST_DEVICES))
goto Recover_platform;
- suspend_enter(state);
+ error = suspend_enter(state);
Resume_devices:
suspend_test_start();
diff --git a/kernel/sys.c b/kernel/sys.c
index af468edf096..f0c10385f30 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -315,7 +315,6 @@ void kernel_restart_prepare(char *cmd)
blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
system_state = SYSTEM_RESTART;
device_shutdown();
- sysdev_shutdown();
syscore_shutdown();
}
@@ -354,7 +353,6 @@ static void kernel_shutdown_prepare(enum system_states state)
void kernel_halt(void)
{
kernel_shutdown_prepare(SYSTEM_HALT);
- sysdev_shutdown();
syscore_shutdown();
printk(KERN_EMERG "System halted.\n");
kmsg_dump(KMSG_DUMP_HALT);
@@ -374,7 +372,6 @@ void kernel_power_off(void)
if (pm_power_off_prepare)
pm_power_off_prepare();
disable_nonboot_cpus();
- sysdev_shutdown();
syscore_shutdown();
printk(KERN_EMERG "Power down.\n");
kmsg_dump(KMSG_DUMP_POWEROFF);