From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Michael Trimarchi <trimarchi@gandalf.sssup.it>,
Len Brown <lenb@kernel.org>
Cc: linux-pm@lists.linux-foundation.org
Subject: Re: [RFC Disable suspend on a specific device] This is a little change in linux power scheme
Date: Tue, 7 Apr 2009 15:45:02 +0200 [thread overview]
Message-ID: <200904071545.03167.rjw@sisk.pl> (raw)
In-Reply-To: <20090407102914.GA25796@gandalf.sssup.it>
On Tuesday 07 April 2009, Michael Trimarchi wrote:
> This is a little rework of linux power scheme. TODO:
> - remove recursive call
> - clean-up code
>
> Avoid suspend of a device that is connected with other coprocessor
> like GSM chip.
Well, can you please tell us a bit about the motivation for this work?
I don't like the approach, but I'd like to know what you're trying to achieve.
Rafael
> Signed-off-by: Michael Trimarchi <trimarchi@gandalf.sssup.it>
>
> ---
> diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
> index 3098c46..2a6ddb3 100644
> --- a/drivers/base/power/main.c
> +++ b/drivers/base/power/main.c
> @@ -63,6 +63,40 @@ void device_pm_unlock(void)
> mutex_unlock(&dpm_list_mtx);
> }
>
> +int device_set_may_suspend_enable(struct device *dev, void *data)
> +{
> + /* if the device is suspend the subtree is in may_suspend status */
> + if (!dev->power.can_suspend)
> + goto out;
> +
> + dev->power.may_suspend = (unsigned int)data;
> + device_for_each_child(dev, data,
> + device_set_may_suspend_enable);
> +out:
> + return 0;
> +}
> +
> +/**
> + * device_set_suspend_enable - enable/disable device to suspend
> + */
> +int device_set_suspend_enable(struct device *dev, int enable)
> +{
> + mutex_lock(&dpm_list_mtx);
> +
> + if (dev->power.can_suspend == !!enable)
> + goto out;
> +
> + /* Update device children to avoid suspend */
> + device_for_each_child(dev, (void *)!!enable,
> + device_set_may_suspend_enable);
> +
> + dev->power.can_suspend = !!enable;
> +out:
> + mutex_unlock(&dpm_list_mtx);
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(device_set_suspend_enable);
> +
> /**
> * device_pm_add - add a device to the list of active devices
> * @dev: Device to be added to the list
> @@ -77,6 +111,13 @@ void device_pm_add(struct device *dev)
> if (dev->parent->power.status >= DPM_SUSPENDING)
> dev_warn(dev, "parent %s should not be sleeping\n",
> dev_name(dev->parent));
> + if (!device_can_suspend(dev->parent)) {
> + mutex_unlock(&dpm_list_mtx);
> + /* if the parent has suspend disable, propagate it
> + * to the new child */
> + device_set_may_suspend_enable(dev, 0);
> + mutex_lock(&dpm_list_mtx);
> + }
> } else if (transition_started) {
> /*
> * We refuse to register parentless devices while a PM
> @@ -120,13 +161,13 @@ static int pm_op(struct device *dev, struct dev_pm_ops *ops,
> switch (state.event) {
> #ifdef CONFIG_SUSPEND
> case PM_EVENT_SUSPEND:
> - if (ops->suspend) {
> + if (device_can_suspend(dev) && ops->suspend) {
> error = ops->suspend(dev);
> suspend_report_result(ops->suspend, error);
> }
> break;
> case PM_EVENT_RESUME:
> - if (ops->resume) {
> + if (device_can_suspend(dev) && ops->resume) {
> error = ops->resume(dev);
> suspend_report_result(ops->resume, error);
> }
> diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
> index 41f51fa..1197b13 100644
> --- a/drivers/base/power/power.h
> +++ b/drivers/base/power/power.h
> @@ -1,6 +1,13 @@
> static inline void device_pm_init(struct device *dev)
> {
> dev->power.status = DPM_ON;
> + dev->power.can_suspend = 1;
> + dev->power.may_suspend = 1;
> +}
> +
> +static inline int device_can_suspend(struct device *dev)
> +{
> + return (dev->power.can_suspend && dev->power.may_suspend);
> }
>
> #ifdef CONFIG_PM_SLEEP
> diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
> index 596aeec..25236aa 100644
> --- a/drivers/base/power/sysfs.c
> +++ b/drivers/base/power/sysfs.c
> @@ -43,6 +43,34 @@
> static const char enabled[] = "enabled";
> static const char disabled[] = "disabled";
>
> +static ssize_t suspend_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + return sprintf(buf, "%s\n", device_can_suspend(dev)
> + ? enabled : disabled);
> +}
> +
> +static ssize_t
> +suspend_store(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t n)
> +{
> + char *cp;
> + int len = n;
> +
> + cp = memchr(buf, '\n', n);
> + if (cp)
> + len = cp - buf;
> + if (len == sizeof enabled - 1
> + && strncmp(buf, enabled, sizeof enabled - 1) == 0)
> + device_set_suspend_enable(dev, 1);
> + else if (len == sizeof disabled - 1
> + && strncmp(buf, disabled, sizeof disabled - 1) == 0)
> + device_set_suspend_enable(dev, 0);
> + else
> + return -EINVAL;
> + return n;
> +}
> +
> static ssize_t
> wake_show(struct device * dev, struct device_attribute *attr, char * buf)
> {
> @@ -76,10 +104,11 @@ wake_store(struct device * dev, struct device_attribute *attr,
> }
>
> static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
> -
> +static DEVICE_ATTR(suspend, 0644, suspend_show, suspend_store);
>
> static struct attribute * power_attrs[] = {
> &dev_attr_wakeup.attr,
> + &dev_attr_suspend.attr,
> NULL,
> };
> static struct attribute_group pm_attr_group = {
> diff --git a/include/linux/device.h b/include/linux/device.h
> index fdb073b..dc9f242 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -487,6 +487,7 @@ extern struct device *device_find_child(struct device *dev, void *data,
> int (*match)(struct device *dev, void *data));
> extern int device_rename(struct device *dev, char *new_name);
> extern int device_move(struct device *dev, struct device *new_parent);
> +extern int device_set_suspend_enable(struct device *dev, int enable);
>
> /*
> * Root device objects for grouping under /sys/devices
> diff --git a/include/linux/pm.h b/include/linux/pm.h
> index de2e0a8..7586a90 100644
> --- a/include/linux/pm.h
> +++ b/include/linux/pm.h
> @@ -319,6 +319,9 @@ struct dev_pm_info {
> pm_message_t power_state;
> unsigned can_wakeup:1;
> unsigned should_wakeup:1;
> + unsigned can_suspend:1;
> + unsigned may_suspend:1;
> +
> enum dpm_state status; /* Owned by the PM core */
> #ifdef CONFIG_PM_SLEEP
> struct list_head entry;
next prev parent reply other threads:[~2009-04-07 13:45 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-07 10:29 [RFC Disable suspend on a specific device] This is a little change in linux power scheme Michael Trimarchi
2009-04-07 13:45 ` Rafael J. Wysocki [this message]
2009-04-07 15:39 ` Michael Trimarchi
2009-04-07 18:55 ` Rafael J. Wysocki
2009-04-07 19:01 ` Michael Trimarchi
2009-04-07 20:40 ` Pavel Machek
2009-04-07 20:57 ` Rafael J. Wysocki
2009-04-07 21:31 ` Alan Stern
2009-04-07 21:38 ` Pavel Machek
2009-04-07 22:25 ` Nigel Cunningham
2009-04-08 5:59 ` Michael Trimarchi
2009-04-08 8:13 ` Rafael J. Wysocki
2009-04-08 8:24 ` Michael Trimarchi
2009-04-08 8:34 ` Rafael J. Wysocki
2009-04-08 8:45 ` Michael Trimarchi
2009-04-07 8:06 ` Pavel Machek
2009-04-20 12:46 ` Mark Brown
2009-04-20 12:55 ` Michael Trimarchi
2009-04-08 11:42 ` Mark Brown
2009-04-08 16:44 ` Igor Stoppa
2009-04-08 18:23 ` Mark Brown
2009-04-08 19:53 ` Igor Stoppa
2009-04-09 14:33 ` Mark Brown
2009-04-07 21:40 ` Rafael J. Wysocki
2009-04-08 11:53 ` Mark Brown
2009-04-08 16:45 ` Igor Stoppa
2009-04-10 11:17 ` Pavel Machek
2009-04-08 20:37 ` Alan Stern
2009-04-08 21:25 ` Michael Trimarchi
2009-04-08 21:56 ` Rafael J. Wysocki
2009-04-09 18:27 ` Alan Stern
2009-04-09 22:33 ` Rafael J. Wysocki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200904071545.03167.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=lenb@kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=trimarchi@gandalf.sssup.it \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.