Skip to content

Commit

Permalink
PM / Domains: Move syscore flag from subsys data to struct device
Browse files Browse the repository at this point in the history
The syscore device PM flag is used to mark the devices (belonging to
a PM domain) that should never be turned off, except for the system
core (syscore) suspend/hibernation and resume stages.  That flag is
stored in the device's struct pm_subsys_data object whose address is
available from struct device.  However, in some situations it may be
convenient to set that flag before the device is added to a PM
domain, so it is better to move it directly to the "power" member of
struct device.  Then, it can be checked by the routines in
drivers/base/power/runtime.c and drivers/base/power/main.c, which is
more straightforward.

This also reduces the number of dev_gpd_data() invocations in the
generic PM domains framework, so the overhead related to the syscore
flag is slightly smaller.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Magnus Damm <damm@opensource.se>
  • Loading branch information
Rafael J. Wysocki committed Sep 3, 2012
1 parent 6fb28ba commit dbf3741
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 38 deletions.
15 changes: 15 additions & 0 deletions drivers/base/power/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,18 @@ int dev_pm_put_subsys_data(struct device *dev)
return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data);

/**
* dev_pm_syscore_device - Set/unset the given device's power.syscore flag.
* @dev: Device whose flag is to be modified.
* @val: New value of the flag.
*/
void dev_pm_syscore_device(struct device *dev, bool val)
{
unsigned long flags;

spin_lock_irqsave(&dev->power.lock, flags);
dev->power.syscore = val;
spin_unlock_irqrestore(&dev->power.lock, flags);
}
EXPORT_SYMBOL_GPL(dev_pm_syscore_device);
37 changes: 6 additions & 31 deletions drivers/base/power/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
not_suspended = 0;
list_for_each_entry(pdd, &genpd->dev_list, list_node)
if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
|| pdd->dev->power.irq_safe || to_gpd_data(pdd)->syscore))
|| pdd->dev->power.irq_safe || pdd->dev->power.syscore))
not_suspended++;

if (not_suspended > genpd->in_progress)
Expand Down Expand Up @@ -578,9 +578,6 @@ static int pm_genpd_runtime_suspend(struct device *dev)

might_sleep_if(!genpd->dev_irq_safe);

if (dev_gpd_data(dev)->syscore)
return -EBUSY;

stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
if (stop_ok && !stop_ok(dev))
return -EBUSY;
Expand Down Expand Up @@ -983,7 +980,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
if (IS_ERR(genpd))
return -EINVAL;

if (genpd->suspend_power_off || dev_gpd_data(dev)->syscore
if (genpd->suspend_power_off
|| (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
return 0;

Expand Down Expand Up @@ -1016,7 +1013,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
if (IS_ERR(genpd))
return -EINVAL;

if (genpd->suspend_power_off || dev_gpd_data(dev)->syscore
if (genpd->suspend_power_off
|| (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
return 0;

Expand Down Expand Up @@ -1136,8 +1133,7 @@ static int pm_genpd_freeze_noirq(struct device *dev)
if (IS_ERR(genpd))
return -EINVAL;

return genpd->suspend_power_off || dev_gpd_data(dev)->syscore ?
0 : genpd_stop_dev(genpd, dev);
return genpd->suspend_power_off ? 0 : genpd_stop_dev(genpd, dev);
}

/**
Expand All @@ -1157,8 +1153,7 @@ static int pm_genpd_thaw_noirq(struct device *dev)
if (IS_ERR(genpd))
return -EINVAL;

return genpd->suspend_power_off || dev_gpd_data(dev)->syscore ?
0 : genpd_start_dev(genpd, dev);
return genpd->suspend_power_off ? 0 : genpd_start_dev(genpd, dev);
}

/**
Expand Down Expand Up @@ -1253,7 +1248,7 @@ static int pm_genpd_restore_noirq(struct device *dev)

pm_genpd_sync_poweron(genpd);

return dev_gpd_data(dev)->syscore ? 0 : genpd_start_dev(genpd, dev);
return genpd_start_dev(genpd, dev);
}

/**
Expand Down Expand Up @@ -1525,26 +1520,6 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
return ret;
}

/**
* pm_genpd_dev_syscore - Set/unset the "syscore" flag for a given device.
* @dev: Device to set/unset the flag for.
* @val: The new value of the device's "syscore" flag.
*/
void pm_genpd_dev_syscore(struct device *dev, bool val)
{
struct pm_subsys_data *psd;
unsigned long flags;

spin_lock_irqsave(&dev->power.lock, flags);

psd = dev_to_psd(dev);
if (psd && psd->domain_data)
to_gpd_data(psd->domain_data)->syscore = val;

spin_unlock_irqrestore(&dev->power.lock, flags);
}
EXPORT_SYMBOL_GPL(pm_genpd_dev_syscore);

/**
* pm_genpd_dev_need_restore - Set/unset the device's "need restore" flag.
* @dev: Device to set/unset the flag for.
Expand Down
28 changes: 28 additions & 0 deletions drivers/base/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
TRACE_DEVICE(dev);
TRACE_RESUME(0);

if (dev->power.syscore)
goto Out;

if (dev->pm_domain) {
info = "noirq power domain ";
callback = pm_noirq_op(&dev->pm_domain->ops, state);
Expand All @@ -426,6 +429,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)

error = dpm_run_callback(callback, dev, state, info);

Out:
TRACE_RESUME(error);
return error;
}
Expand Down Expand Up @@ -483,6 +487,9 @@ static int device_resume_early(struct device *dev, pm_message_t state)
TRACE_DEVICE(dev);
TRACE_RESUME(0);

if (dev->power.syscore)
goto Out;

if (dev->pm_domain) {
info = "early power domain ";
callback = pm_late_early_op(&dev->pm_domain->ops, state);
Expand All @@ -504,6 +511,7 @@ static int device_resume_early(struct device *dev, pm_message_t state)

error = dpm_run_callback(callback, dev, state, info);

Out:
TRACE_RESUME(error);
return error;
}
Expand Down Expand Up @@ -567,6 +575,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
TRACE_DEVICE(dev);
TRACE_RESUME(0);

if (dev->power.syscore)
goto Complete;

dpm_wait(dev->parent, async);
device_lock(dev);

Expand Down Expand Up @@ -629,6 +640,8 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)

Unlock:
device_unlock(dev);

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

TRACE_RESUME(error);
Expand Down Expand Up @@ -719,6 +732,9 @@ static void device_complete(struct device *dev, pm_message_t state)
void (*callback)(struct device *) = NULL;
char *info = NULL;

if (dev->power.syscore)
return;

device_lock(dev);

if (dev->pm_domain) {
Expand Down Expand Up @@ -831,6 +847,9 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
pm_callback_t callback = NULL;
char *info = NULL;

if (dev->power.syscore)
return 0;

if (dev->pm_domain) {
info = "noirq power domain ";
callback = pm_noirq_op(&dev->pm_domain->ops, state);
Expand Down Expand Up @@ -914,6 +933,9 @@ static int device_suspend_late(struct device *dev, pm_message_t state)
pm_callback_t callback = NULL;
char *info = NULL;

if (dev->power.syscore)
return 0;

if (dev->pm_domain) {
info = "late power domain ";
callback = pm_late_early_op(&dev->pm_domain->ops, state);
Expand Down Expand Up @@ -1050,6 +1072,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
goto Complete;
}

if (dev->power.syscore)
goto Complete;

device_lock(dev);

if (dev->pm_domain) {
Expand Down Expand Up @@ -1206,6 +1231,9 @@ static int device_prepare(struct device *dev, pm_message_t state)
char *info = NULL;
int error = 0;

if (dev->power.syscore)
return 0;

device_lock(dev);

dev->power.wakeup_path = device_may_wakeup(dev);
Expand Down
2 changes: 1 addition & 1 deletion drivers/base/power/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ static int rpm_check_suspend_allowed(struct device *dev)

if (dev->power.runtime_error)
retval = -EINVAL;
else if (dev->power.disable_depth > 0)
else if (dev->power.disable_depth > 0 || dev->power.syscore)
retval = -EACCES;
else if (atomic_read(&dev->power.usage_count) > 0)
retval = -EAGAIN;
Expand Down
2 changes: 1 addition & 1 deletion drivers/clocksource/sh_cmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev)
struct sh_timer_config *cfg = pdev->dev.platform_data;

if (cfg->clocksource_rating || cfg->clockevent_rating)
pm_genpd_dev_syscore(&pdev->dev, true);
dev_pm_syscore_device(&pdev->dev, true);
}

if (p) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/clocksource/sh_mtu2.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ static int __devinit sh_mtu2_probe(struct platform_device *pdev)
struct sh_timer_config *cfg = pdev->dev.platform_data;

if (cfg->clockevent_rating)
pm_genpd_dev_syscore(&pdev->dev, true);
dev_pm_syscore_device(&pdev->dev, true);
}

if (p) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/clocksource/sh_tmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev)
struct sh_timer_config *cfg = pdev->dev.platform_data;

if (cfg->clocksource_rating || cfg->clockevent_rating)
pm_genpd_dev_syscore(&pdev->dev, true);
dev_pm_syscore_device(&pdev->dev, true);
}

if (p) {
Expand Down
5 changes: 5 additions & 0 deletions include/linux/pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ struct device;

#ifdef CONFIG_PM
extern const char power_group_name[]; /* = "power" */

extern void dev_pm_syscore_device(struct device *dev, bool val);
#else
#define power_group_name NULL

static inline void dev_pm_syscore_device(struct device *dev, bool val) {}
#endif

typedef struct pm_message {
Expand Down Expand Up @@ -511,6 +515,7 @@ struct dev_pm_info {
bool is_suspended:1; /* Ditto */
bool ignore_children:1;
bool early_init:1; /* Owned by the PM core */
bool syscore:1;
spinlock_t lock;
#ifdef CONFIG_PM_SLEEP
struct list_head entry;
Expand Down
3 changes: 0 additions & 3 deletions include/linux/pm_domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ struct generic_pm_domain_data {
struct mutex lock;
unsigned int refcount;
bool need_restore;
bool syscore;
};

#ifdef CONFIG_PM_GENERIC_DOMAINS
Expand Down Expand Up @@ -153,7 +152,6 @@ static inline int pm_genpd_of_add_device(struct device_node *genpd_node,

extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
struct device *dev);
extern void pm_genpd_dev_syscore(struct device *dev, bool val);
extern void pm_genpd_dev_need_restore(struct device *dev, bool val);
extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *new_subdomain);
Expand Down Expand Up @@ -199,7 +197,6 @@ static inline int pm_genpd_remove_device(struct generic_pm_domain *genpd,
{
return -ENOSYS;
}
static inline void pm_genpd_dev_syscore(struct device *dev, bool val) {}
static inline void pm_genpd_dev_need_restore(struct device *dev, bool val) {}
static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *new_sd)
Expand Down

0 comments on commit dbf3741

Please sign in to comment.