Commit 9480e307 authored by Russell King's avatar Russell King Committed by Greg Kroah-Hartman
Browse files

[PATCH] DRIVER MODEL: Get rid of the obsolete tri-level suspend/resume callbacks



In PM v1, all devices were called at SUSPEND_DISABLE level.  Then
all devices were called at SUSPEND_SAVE_STATE level, and finally
SUSPEND_POWER_DOWN level.  However, with PM v2, to maintain
compatibility for platform devices, I arranged for the PM v2
suspend/resume callbacks to call the old PM v1 suspend/resume
callbacks three times with each level in order so that existing
drivers continued to work.

Since this is obsolete infrastructure which is no longer necessary,
we can remove it.  Here's an (untested) patch to do exactly that.
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a3a3395e
......@@ -196,67 +196,11 @@ it into a supported low-power state.
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
suspend is called to put the device in a low power state. There are
several stages to successfully suspending a device, which is denoted in
the @level parameter. Breaking the suspend transition into several
stages affords the platform flexibility in performing device power
management based on the requirements of the system and the
user-defined policy.
SUSPEND_NOTIFY notifies the device that a suspend transition is about
to happen. This happens on system power state transitions to verify
that all devices can successfully suspend.
A driver may choose to fail on this call, which should cause the
entire suspend transition to fail. A driver should fail only if it
knows that the device will not be able to be resumed properly when the
system wakes up again. It could also fail if it somehow determines it
is in the middle of an operation too important to stop.
SUSPEND_DISABLE tells the device to stop I/O transactions. When it
stops transactions, or what it should do with unfinished transactions
is a policy of the driver. After this call, the driver should not
accept any other I/O requests.
SUSPEND_SAVE_STATE tells the device to save the context of the
hardware. This includes any bus-specific hardware state and
device-specific hardware state. A pointer to this saved state can be
stored in the device's saved_state field.
SUSPEND_POWER_DOWN tells the driver to place the device in the low
power state requested.
Whether suspend is called with a given level is a policy of the
platform. Some levels may be omitted; drivers must not assume the
reception of any level. However, all levels must be called in the
order above; i.e. notification will always come before disabling;
disabling the device will come before suspending the device.
All calls are made with interrupts enabled, except for the
SUSPEND_POWER_DOWN level.
suspend is called to put the device in a low power state.
int (*resume) (struct device * dev, u32 level);
Resume is used to bring a device back from a low power state. Like the
suspend transition, it happens in several stages.
RESUME_POWER_ON tells the driver to set the power state to the state
before the suspend call (The device could have already been in a low
power state before the suspend call to put in a lower power state).
RESUME_RESTORE_STATE tells the driver to restore the state saved by
the SUSPEND_SAVE_STATE suspend call.
RESUME_ENABLE tells the driver to start accepting I/O transactions
again. Depending on driver policy, the device may already have pending
I/O requests.
RESUME_POWER_ON is called with interrupts disabled. The other resume
levels are called with interrupts enabled.
As with the various suspend stages, the driver must not assume that
any other resume calls have been or will be made. Each call should be
self-contained and not dependent on any external state.
Resume is used to bring a device back from a low power state.
Attributes
......
......@@ -550,15 +550,12 @@ struct locomo_save_data {
u16 LCM_SPIMD;
};
static int locomo_suspend(struct device *dev, pm_message_t state, u32 level)
static int locomo_suspend(struct device *dev, pm_message_t state)
{
struct locomo *lchip = dev_get_drvdata(dev);
struct locomo_save_data *save;
unsigned long flags;
if (level != SUSPEND_DISABLE)
return 0;
save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);
if (!save)
return -ENOMEM;
......@@ -597,16 +594,13 @@ static int locomo_suspend(struct device *dev, pm_message_t state, u32 level)
return 0;
}
static int locomo_resume(struct device *dev, u32 level)
static int locomo_resume(struct device *dev)
{
struct locomo *lchip = dev_get_drvdata(dev);
struct locomo_save_data *save;
unsigned long r;
unsigned long flags;
if (level != RESUME_ENABLE)
return 0;
save = (struct locomo_save_data *) dev->power.saved_state;
if (!save)
return 0;
......
......@@ -801,7 +801,7 @@ struct sa1111_save_data {
#ifdef CONFIG_PM
static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level)
static int sa1111_suspend(struct device *dev, pm_message_t state)
{
struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save;
......@@ -809,9 +809,6 @@ static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level)
unsigned int val;
void __iomem *base;
if (level != SUSPEND_DISABLE)
return 0;
save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
if (!save)
return -ENOMEM;
......@@ -856,23 +853,19 @@ static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level)
/*
* sa1111_resume - Restore the SA1111 device state.
* @dev: device to restore
* @level: resume level
*
* Restore the general state of the SA1111; clock control and
* interrupt controller. Other parts of the SA1111 must be
* restored by their respective drivers, and must be called
* via LDM after this function.
*/
static int sa1111_resume(struct device *dev, u32 level)
static int sa1111_resume(struct device *dev)
{
struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save;
unsigned long flags, id;
void __iomem *base;
if (level != RESUME_ENABLE)
return 0;
save = (struct sa1111_save_data *)dev->power.saved_state;
if (!save)
return 0;
......
......@@ -102,26 +102,24 @@ static void check_scoop_reg(struct scoop_dev *sdev)
}
#ifdef CONFIG_PM
static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level)
static int scoop_suspend(struct device *dev, pm_message_t state)
{
if (level == SUSPEND_POWER_DOWN) {
struct scoop_dev *sdev = dev_get_drvdata(dev);
struct scoop_dev *sdev = dev_get_drvdata(dev);
check_scoop_reg(sdev);
sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
check_scoop_reg(sdev);
sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
}
return 0;
}
static int scoop_resume(struct device *dev, uint32_t level)
static int scoop_resume(struct device *dev)
{
if (level == RESUME_POWER_ON) {
struct scoop_dev *sdev = dev_get_drvdata(dev);
struct scoop_dev *sdev = dev_get_drvdata(dev);
check_scoop_reg(sdev);
SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
check_scoop_reg(sdev);
SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
}
return 0;
}
#else
......
......@@ -222,24 +222,22 @@ static int corgi_ssp_remove(struct device *dev)
return 0;
}
static int corgi_ssp_suspend(struct device *dev, pm_message_t state, u32 level)
static int corgi_ssp_suspend(struct device *dev, pm_message_t state)
{
if (level == SUSPEND_POWER_DOWN) {
ssp_flush(&corgi_ssp_dev);
ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
}
ssp_flush(&corgi_ssp_dev);
ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
return 0;
}
static int corgi_ssp_resume(struct device *dev, u32 level)
static int corgi_ssp_resume(struct device *dev)
{
if (level == RESUME_POWER_ON) {
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
ssp_enable(&corgi_ssp_dev);
}
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
ssp_enable(&corgi_ssp_dev);
return 0;
}
......
......@@ -178,33 +178,27 @@ static int neponset_probe(struct device *dev)
/*
* LDM power management.
*/
static int neponset_suspend(struct device *dev, pm_message_t state, u32 level)
static int neponset_suspend(struct device *dev, pm_message_t state)
{
/*
* Save state.
*/
if (level == SUSPEND_SAVE_STATE ||
level == SUSPEND_DISABLE ||
level == SUSPEND_POWER_DOWN) {
if (!dev->power.saved_state)
dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
if (!dev->power.saved_state)
return -ENOMEM;
*(unsigned int *)dev->power.saved_state = NCR_0;
}
if (!dev->power.saved_state)
dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
if (!dev->power.saved_state)
return -ENOMEM;
*(unsigned int *)dev->power.saved_state = NCR_0;
return 0;
}
static int neponset_resume(struct device *dev, u32 level)
static int neponset_resume(struct device *dev)
{
if (level == RESUME_RESTORE_STATE || level == RESUME_ENABLE) {
if (dev->power.saved_state) {
NCR_0 = *(unsigned int *)dev->power.saved_state;
kfree(dev->power.saved_state);
dev->power.saved_state = NULL;
}
if (dev->power.saved_state) {
NCR_0 = *(unsigned int *)dev->power.saved_state;
kfree(dev->power.saved_state);
dev->power.saved_state = NULL;
}
return 0;
......
......@@ -281,13 +281,9 @@ static int platform_suspend(struct device * dev, pm_message_t state)
{
int ret = 0;
if (dev->driver && dev->driver->suspend) {
ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE);
if (ret == 0)
ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);
if (ret == 0)
ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
}
if (dev->driver && dev->driver->suspend)
ret = dev->driver->suspend(dev, state);
return ret;
}
......@@ -295,13 +291,9 @@ static int platform_resume(struct device * dev)
{
int ret = 0;
if (dev->driver && dev->driver->resume) {
ret = dev->driver->resume(dev, RESUME_POWER_ON);
if (ret == 0)
ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);
if (ret == 0)
ret = dev->driver->resume(dev, RESUME_ENABLE);
}
if (dev->driver && dev->driver->resume)
ret = dev->driver->resume(dev);
return ret;
}
......
......@@ -519,30 +519,28 @@ static struct timespec s3c2410_rtc_delta;
static int ticnt_save;
static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state, u32 level)
static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state)
{
struct rtc_time tm;
struct timespec time;
time.tv_nsec = 0;
if (level == SUSPEND_POWER_DOWN) {
/* save TICNT for anyone using periodic interrupts */
/* save TICNT for anyone using periodic interrupts */
ticnt_save = readb(S3C2410_TICNT);
ticnt_save = readb(S3C2410_TICNT);
/* calculate time delta for suspend */
/* calculate time delta for suspend */
s3c2410_rtc_gettime(&tm);
rtc_tm_to_time(&tm, &time.tv_sec);
save_time_delta(&s3c2410_rtc_delta, &time);
s3c2410_rtc_enable(dev, 0);
}
s3c2410_rtc_gettime(&tm);
rtc_tm_to_time(&tm, &time.tv_sec);
save_time_delta(&s3c2410_rtc_delta, &time);
s3c2410_rtc_enable(dev, 0);
return 0;
}
static int s3c2410_rtc_resume(struct device *dev, u32 level)
static int s3c2410_rtc_resume(struct device *dev)
{
struct rtc_time tm;
struct timespec time;
......
......@@ -1167,19 +1167,17 @@ static int sonypi_disable(void)
#ifdef CONFIG_PM
static int old_camera_power;
static int sonypi_suspend(struct device *dev, pm_message_t state, u32 level)
static int sonypi_suspend(struct device *dev, pm_message_t state)
{
if (level == SUSPEND_DISABLE) {
old_camera_power = sonypi_device.camera_power;
sonypi_disable();
}
old_camera_power = sonypi_device.camera_power;
sonypi_disable();
return 0;
}
static int sonypi_resume(struct device *dev, u32 level)
static int sonypi_resume(struct device *dev)
{
if (level == RESUME_ENABLE)
sonypi_enable(old_camera_power);
sonypi_enable(old_camera_power);
return 0;
}
#endif
......
......@@ -464,32 +464,28 @@ static void s3c2410wdt_shutdown(struct device *dev)
static unsigned long wtcon_save;
static unsigned long wtdat_save;
static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level)
static int s3c2410wdt_suspend(struct device *dev, pm_message_t state)
{
if (level == SUSPEND_POWER_DOWN) {
/* Save watchdog state, and turn it off. */
wtcon_save = readl(wdt_base + S3C2410_WTCON);
wtdat_save = readl(wdt_base + S3C2410_WTDAT);
/* Save watchdog state, and turn it off. */
wtcon_save = readl(wdt_base + S3C2410_WTCON);
wtdat_save = readl(wdt_base + S3C2410_WTDAT);
/* Note that WTCNT doesn't need to be saved. */
s3c2410wdt_stop();
}
/* Note that WTCNT doesn't need to be saved. */
s3c2410wdt_stop();
return 0;
}
static int s3c2410wdt_resume(struct device *dev, u32 level)
static int s3c2410wdt_resume(struct device *dev)
{
if (level == RESUME_POWER_ON) {
/* Restore watchdog state. */
/* Restore watchdog state. */
writel(wtdat_save, wdt_base + S3C2410_WTDAT);
writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
writel(wtcon_save, wdt_base + S3C2410_WTCON);
writel(wtdat_save, wdt_base + S3C2410_WTDAT);
writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
writel(wtcon_save, wdt_base + S3C2410_WTCON);
printk(KERN_INFO PFX "watchdog %sabled\n",
(wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
}
printk(KERN_INFO PFX "watchdog %sabled\n",
(wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
return 0;
}
......
......@@ -296,11 +296,9 @@ static int hdaps_probe(struct device *dev)
return 0;
}
static int hdaps_resume(struct device *dev, u32 level)
static int hdaps_resume(struct device *dev)
{
if (level == RESUME_ENABLE)
return hdaps_device_init();
return 0;
return hdaps_device_init();
}
static struct device_driver hdaps_driver = {
......
......@@ -879,14 +879,12 @@ static int s3c24xx_i2c_remove(struct device *dev)
}
#ifdef CONFIG_PM
static int s3c24xx_i2c_resume(struct device *dev, u32 level)
static int s3c24xx_i2c_resume(struct device *dev)
{
struct s3c24xx_i2c *i2c = dev_get_drvdata(dev);
if (i2c != NULL && level == RESUME_ENABLE) {
dev_dbg(dev, "resume: level %d\n", level);
if (i2c != NULL)
s3c24xx_i2c_init(i2c);
}
return 0;
}
......
......@@ -48,7 +48,7 @@ static int i2c_bus_suspend(struct device * dev, pm_message_t state)
int rc = 0;
if (dev->driver && dev->driver->suspend)
rc = dev->driver->suspend(dev,state,0);
rc = dev->driver->suspend(dev, state);
return rc;
}
......@@ -57,7 +57,7 @@ static int i2c_bus_resume(struct device * dev)
int rc = 0;
if (dev->driver && dev->driver->resume)
rc = dev->driver->resume(dev,0);
rc = dev->driver->resume(dev);
return rc;
}
......
......@@ -1292,7 +1292,7 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
if (ud->device.driver &&
(!ud->device.driver->suspend ||
ud->device.driver->suspend(&ud->device, PMSG_SUSPEND, 0)))
ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
device_release_driver(&ud->device);
}
up_write(&ne->device.bus->subsys.rwsem);
......@@ -1315,7 +1315,7 @@ static void nodemgr_resume_ne(struct node_entry *ne)
continue;
if (ud->device.driver && ud->device.driver->resume)
ud->device.driver->resume(&ud->device, 0);
ud->device.driver->resume(&ud->device);
}
up_read(&ne->device.bus->subsys.rwsem);
......
......@@ -259,24 +259,22 @@ static void corgikbd_hinge_timer(unsigned long data)
}
#ifdef CONFIG_PM
static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
static int corgikbd_suspend(struct device *dev, pm_message_t state)
{
if (level == SUSPEND_POWER_DOWN) {
struct corgikbd *corgikbd = dev_get_drvdata(dev);
corgikbd->suspended = 1;
}
struct corgikbd *corgikbd = dev_get_drvdata(dev);
corgikbd->suspended = 1;
return 0;
}
static int corgikbd_resume(struct device *dev, uint32_t level)
static int corgikbd_resume(struct device *dev)
{
if (level == RESUME_POWER_ON) {
struct corgikbd *corgikbd = dev_get_drvdata(dev);
struct corgikbd *corgikbd = dev_get_drvdata(dev);
/* Upon resume, ignore the suspend key for a short while */
corgikbd->suspend_jiffies=jiffies;
corgikbd->suspended = 0;
/* Upon resume, ignore the suspend key for a short while */
corgikbd->suspend_jiffies=jiffies;
corgikbd->suspended = 0;
}
return 0;
}
#else
......
......@@ -309,34 +309,32 @@ static void spitzkbd_hinge_timer(unsigned long data)
}
#ifdef CONFIG_PM
static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
static int spitzkbd_suspend(struct device *dev, pm_message_t state)
{
if (level == SUSPEND_POWER_DOWN) {
int i;
struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
spitzkbd->suspended = 1;
/* Set Strobe lines as inputs - *except* strobe line 0 leave this
enabled so we can detect a power button press for resume */
for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
}
int i;
struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
spitzkbd->suspended = 1;
/* Set Strobe lines as inputs - *except* strobe line 0 leave this
enabled so we can detect a power button press for resume */
for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
return 0;
}
static int spitzkbd_resume(struct device *dev, uint32_t level)
static int spitzkbd_resume(struct device *dev)
{
if (level == RESUME_POWER_ON) {
int i;
struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
int i;
struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
/* Upon resume, ignore the suspend key for a short while */
spitzkbd->suspend_jiffies = jiffies;
spitzkbd->suspended = 0;
/* Upon resume, ignore the suspend key for a short while */
spitzkbd->suspend_jiffies = jiffies;
spitzkbd->suspended = 0;
}
return 0;
}
#else
......
......@@ -911,12 +911,10 @@ static long i8042_panic_blink(long count)
* Here we try to restore the original BIOS settings
*/
static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
static int i8042_suspend(struct device *dev, pm_message_t state)
{
if (level == SUSPEND_DISABLE) {
del_timer_sync(&i8042_timer);
i8042_controller_reset();
}
del_timer_sync(&i8042_timer);
i8042_controller_reset();
return 0;
}
......@@ -926,13 +924,10 @@ static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
* Here we try to reset everything back to a state in which suspended
*/
static int i8042_resume(struct device *dev, u32