Skip to content

Commit

Permalink
Merge branch 'pm-runtime' into for-linus
Browse files Browse the repository at this point in the history
* pm-runtime:
  OMAP: PM: disable idle on suspend for GPIO and UART
  OMAP: PM: omap_device: add API to disable idle on suspend
  OMAP: PM: omap_device: add system PM methods for PM domain handling
  OMAP: PM: omap_device: conditionally use PM domain runtime helpers
  PM / Runtime: Add new helper function: pm_runtime_status_suspended()
  PM / Runtime: Consistent utilization of deferred_resume
  PM / Runtime: Prevent runtime_resume from racing with probe
  PM / Runtime: Replace "run-time" with "runtime" in documentation
  PM / Runtime: Improve documentation of enable, disable and barrier
  PM: Limit race conditions between runtime PM and system sleep (v2)
  PCI / PM: Detect early wakeup in pci_pm_prepare()
  PM / Runtime: Return special error code if runtime PM is disabled
  PM / Runtime: Update documentation of interactions with system sleep
  • Loading branch information
Rafael J. Wysocki committed Jul 15, 2011
2 parents ba1389d + c8c9fda commit 7ae033c
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 137 deletions.
6 changes: 3 additions & 3 deletions Documentation/power/devices.txt
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ state temporarily, for example so that its system wakeup capability can be
disabled. This all depends on the hardware and the design of the subsystem and
device driver in question.

During system-wide resume from a sleep state it's best to put devices into the
full-power state, as explained in Documentation/power/runtime_pm.txt. Refer to
that document for more information regarding this particular issue as well as
During system-wide resume from a sleep state it's easiest to put devices into
the full-power state, as explained in Documentation/power/runtime_pm.txt. Refer
to that document for more information regarding this particular issue as well as
for information on the device runtime power management framework in general.
197 changes: 122 additions & 75 deletions Documentation/power/runtime_pm.txt

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions arch/arm/mach-omap2/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
return PTR_ERR(od);
}

omap_device_disable_idle_on_suspend(od);

gpio_bank_count++;
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-omap2/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
name, oh->name);

omap_device_disable_idle_on_suspend(od);
oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);

uart->irq = oh->mpu_irqs[0].irq;
Expand Down
9 changes: 9 additions & 0 deletions arch/arm/plat-omap/include/plat/omap_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ extern struct device omap_device_parent;
#define OMAP_DEVICE_STATE_IDLE 2
#define OMAP_DEVICE_STATE_SHUTDOWN 3

/* omap_device.flags values */
#define OMAP_DEVICE_SUSPENDED BIT(0)
#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1)

/**
* struct omap_device - omap_device wrapper for platform_devices
* @pdev: platform_device
Expand Down Expand Up @@ -73,6 +77,7 @@ struct omap_device {
s8 pm_lat_level;
u8 hwmods_cnt;
u8 _state;
u8 flags;
};

/* Device driver interface (call via platform_data fn ptrs) */
Expand Down Expand Up @@ -117,6 +122,10 @@ int omap_device_enable_hwmods(struct omap_device *od);
int omap_device_disable_clocks(struct omap_device *od);
int omap_device_enable_clocks(struct omap_device *od);

static inline void omap_device_disable_idle_on_suspend(struct omap_device *od)
{
od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
}

/*
* Entries should be kept in latency order ascending
Expand Down
49 changes: 46 additions & 3 deletions arch/arm/plat-omap/omap_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ int omap_early_device_register(struct omap_device *od)
return 0;
}

#ifdef CONFIG_PM_RUNTIME
static int _od_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
Expand All @@ -563,13 +564,55 @@ static int _od_runtime_resume(struct device *dev)

return pm_generic_runtime_resume(dev);
}
#endif

#ifdef CONFIG_SUSPEND
static int _od_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od = to_omap_device(pdev);
int ret;

if (od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)
return pm_generic_suspend_noirq(dev);

ret = pm_generic_suspend_noirq(dev);

if (!ret && !pm_runtime_status_suspended(dev)) {
if (pm_generic_runtime_suspend(dev) == 0) {
omap_device_idle(pdev);
od->flags |= OMAP_DEVICE_SUSPENDED;
}
}

return ret;
}

static int _od_resume_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od = to_omap_device(pdev);

if (od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)
return pm_generic_resume_noirq(dev);

if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
!pm_runtime_status_suspended(dev)) {
od->flags &= ~OMAP_DEVICE_SUSPENDED;
omap_device_enable(pdev);
pm_generic_runtime_resume(dev);
}

return pm_generic_resume_noirq(dev);
}
#endif

static struct dev_pm_domain omap_device_pm_domain = {
.ops = {
.runtime_suspend = _od_runtime_suspend,
.runtime_idle = _od_runtime_idle,
.runtime_resume = _od_runtime_resume,
SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
_od_runtime_idle)
USE_PLATFORM_PM_SLEEP_OPS
SET_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq, _od_resume_noirq)
}
};

Expand Down
35 changes: 23 additions & 12 deletions drivers/base/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
static int device_resume(struct device *dev, pm_message_t state, bool async)
{
int error = 0;
bool put = false;

TRACE_DEVICE(dev);
TRACE_RESUME(0);
Expand All @@ -521,6 +522,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
if (!dev->power.is_suspended)
goto Unlock;

pm_runtime_enable(dev);
put = true;

if (dev->pm_domain) {
pm_dev_dbg(dev, state, "power domain ");
error = pm_op(dev, &dev->pm_domain->ops, state);
Expand Down Expand Up @@ -563,6 +567,10 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
complete_all(&dev->power.completion);

TRACE_RESUME(error);

if (put)
pm_runtime_put_sync(dev);

return error;
}

Expand Down Expand Up @@ -843,16 +851,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
int error = 0;

dpm_wait_for_children(dev, async);
device_lock(dev);

if (async_error)
goto Unlock;
return 0;

pm_runtime_get_noresume(dev);
if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
pm_wakeup_event(dev, 0);

if (pm_wakeup_pending()) {
pm_runtime_put_sync(dev);
async_error = -EBUSY;
goto Unlock;
return 0;
}

device_lock(dev);

if (dev->pm_domain) {
pm_dev_dbg(dev, state, "power domain ");
error = pm_op(dev, &dev->pm_domain->ops, state);
Expand Down Expand Up @@ -890,12 +904,15 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
End:
dev->power.is_suspended = !error;

Unlock:
device_unlock(dev);
complete_all(&dev->power.completion);

if (error)
if (error) {
pm_runtime_put_sync(dev);
async_error = error;
} else if (dev->power.is_suspended) {
__pm_runtime_disable(dev, false);
}

return error;
}
Expand Down Expand Up @@ -1035,13 +1052,7 @@ int dpm_prepare(pm_message_t state)
get_device(dev);
mutex_unlock(&dpm_list_mtx);

pm_runtime_get_noresume(dev);
if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
pm_wakeup_event(dev, 0);

pm_runtime_put_sync(dev);
error = pm_wakeup_pending() ?
-EBUSY : device_prepare(dev, state);
error = device_prepare(dev, state);

mutex_lock(&dpm_list_mtx);
if (error) {
Expand Down
Loading

0 comments on commit 7ae033c

Please sign in to comment.