From: Guan-Yu Lin <guanyulin@google.com>
To: rafael@kernel.org, pavel@ucw.cz, len.brown@intel.com,
gregkh@linuxfoundation.org, andriy.shevchenko@linux.intel.com,
petr.tesarik.ext@huawei.com, rdunlap@infradead.org,
james@equiv.tech, broonie@kernel.org, james.clark@arm.com,
masahiroy@kernel.org
Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org,
Guan-Yu Lin <guanyulin@google.com>
Subject: [PATCH v3] PM / core: conditionally skip system pm in device/driver model
Date: Fri, 23 Feb 2024 14:38:29 +0000 [thread overview]
Message-ID: <20240223143833.1509961-1-guanyulin@google.com> (raw)
In systems with a main processor and a co-processor, asynchronous
controller management can lead to conflicts. One example is the main
processor attempting to suspend a device while the co-processor is
actively using it. To address this, we introduce a new sysfs entry
called "conditional_skip". This entry allows the system to selectively
skip certain device power management state transitions. To use this
feature, set the value in "conditional_skip" to indicate the type of
state transition you want to avoid. Please review /Documentation/ABI/
testing/sysfs-devices-power for more detailed information.
Signed-off-by: Guan-Yu Lin <guanyulin@google.com>
---
V2 -> V3: Integrate the feature with the pm core framework.
V1 -> V2: Cosmetics changes on coding style.
[v2] usb: host: enable suspend-to-RAM control in userspace
[v1] [RFC] usb: host: Allow userspace to control usb suspend flows
---
Documentation/ABI/testing/sysfs-devices-power | 11 ++++++++
drivers/base/power/main.c | 16 ++++++++++++
drivers/base/power/sysfs.c | 26 +++++++++++++++++++
include/linux/device.h | 7 +++++
include/linux/pm.h | 1 +
5 files changed, 61 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 54195530e97a..3ac4e40f07a0 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -305,3 +305,14 @@ Description:
Reports the runtime PM children usage count of a device, or
0 if the children will be ignored.
+What: /sys/devices/.../power/conditional_skip
+Date: Feburary 2024
+Contact: Guan-Yu Lin <guanyulin@google.com>
+Description:
+ The /sys/devices/.../conditional_skip attribute provides a way
+ to selectively skip system-wide power transitions like
+ suspend-to-RAM or hibernation. To skip a specific transition,
+ write its corresponding value to this attribute. For skipping
+ multiple transitions, combine their values using a bitwise OR
+ and write the result to this attribute.
+
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index fadcd0379dc2..d507626c7892 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1881,6 +1881,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
*/
int dpm_prepare(pm_message_t state)
{
+ struct list_head list;
int error = 0;
trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
@@ -1900,12 +1901,26 @@ int dpm_prepare(pm_message_t state)
*/
device_block_probing();
+ INIT_LIST_HEAD(&list);
mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_list) && !error) {
struct device *dev = to_device(dpm_list.next);
get_device(dev);
+ if (dev->power.conditional_skip_pm & state.event) {
+ dev_info(dev, "skip system PM transition (event = 0x%04x)\n",
+ state.event);
+
+ if (!list_empty(&dev->power.entry))
+ list_move_tail(&dev->power.entry, &list);
+
+ mutex_unlock(&dpm_list_mtx);
+ put_device(dev);
+ mutex_lock(&dpm_list_mtx);
+ continue;
+ }
+
mutex_unlock(&dpm_list_mtx);
trace_device_pm_callback_start(dev, "", state.event);
@@ -1931,6 +1946,7 @@ int dpm_prepare(pm_message_t state)
mutex_lock(&dpm_list_mtx);
}
+ list_splice(&list, &dpm_list);
mutex_unlock(&dpm_list_mtx);
trace_suspend_resume(TPS("dpm_prepare"), state.event, false);
return error;
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a1474fb67db9..1feacb01b1e9 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -610,6 +610,31 @@ static DEVICE_ATTR_RW(async);
#endif /* CONFIG_PM_SLEEP */
#endif /* CONFIG_PM_ADVANCED_DEBUG */
+static ssize_t conditional_skip_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "0x%04x\n", dev->power.conditional_skip_pm);
+}
+
+static ssize_t conditional_skip_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ int ret;
+
+ if (kstrtoint(buf, 0, &ret))
+ return -EINVAL;
+
+ ret &= (PM_EVENT_FREEZE|PM_EVENT_SUSPEND|PM_EVENT_HIBERNATE);
+
+ dev->power.conditional_skip_pm = ret;
+
+ return n;
+}
+
+static DEVICE_ATTR_RW(conditional_skip);
+
static struct attribute *power_attrs[] = {
#ifdef CONFIG_PM_ADVANCED_DEBUG
#ifdef CONFIG_PM_SLEEP
@@ -620,6 +645,7 @@ static struct attribute *power_attrs[] = {
&dev_attr_runtime_active_kids.attr,
&dev_attr_runtime_enabled.attr,
#endif /* CONFIG_PM_ADVANCED_DEBUG */
+ &dev_attr_conditional_skip.attr,
NULL,
};
static const struct attribute_group pm_attr_group = {
diff --git a/include/linux/device.h b/include/linux/device.h
index 97c4b046c09d..f2c73dd00211 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -968,6 +968,13 @@ static inline void device_set_pm_not_required(struct device *dev)
dev->power.no_pm = true;
}
+static inline void device_set_pm_conditional_skip(struct device *dev,
+ int condition)
+{
+ condition &= (PM_EVENT_FREEZE|PM_EVENT_SUSPEND|PM_EVENT_HIBERNATE);
+ dev->power.conditional_skip_pm = condition;
+}
+
static inline void dev_pm_syscore_device(struct device *dev, bool val)
{
#ifdef CONFIG_PM_SLEEP
diff --git a/include/linux/pm.h b/include/linux/pm.h
index a2f3e53a8196..890c7a601c2a 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -713,6 +713,7 @@ struct dev_pm_info {
enum rpm_status last_status;
int runtime_error;
int autosuspend_delay;
+ int conditional_skip_pm;
u64 last_busy;
u64 active_time;
u64 suspended_time;
--
2.44.0.rc0.258.g7320e95886-goog
next reply other threads:[~2024-02-23 14:38 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-23 14:38 Guan-Yu Lin [this message]
2024-02-23 15:18 ` [PATCH v3] PM / core: conditionally skip system pm in device/driver model Andy Shevchenko
2024-02-26 9:15 ` Guan-Yu Lin
2024-02-26 14:02 ` Andy Shevchenko
2024-02-27 6:47 ` Guan-Yu Lin
2024-02-23 17:43 ` Rafael J. Wysocki
2024-02-26 9:45 ` Guan-Yu Lin
2024-02-27 11:28 ` Rafael J. Wysocki
2024-02-29 10:09 ` Guan-Yu Lin
2024-02-23 18:20 ` Florian Fainelli
2024-02-26 10:28 ` Guan-Yu Lin
2024-02-26 18:40 ` Florian Fainelli
2024-02-27 8:56 ` Guan-Yu Lin
2024-02-27 9:15 ` Greg KH
2024-02-29 10:27 ` Guan-Yu Lin
2024-02-27 17:57 ` Florian Fainelli
2024-02-29 9:08 ` Guan-Yu Lin
2024-02-29 20:34 ` Greg KH
2024-03-08 18:04 ` Guan-Yu Lin
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=20240223143833.1509961-1-guanyulin@google.com \
--to=guanyulin@google.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=broonie@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=james.clark@arm.com \
--cc=james@equiv.tech \
--cc=len.brown@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=masahiroy@kernel.org \
--cc=pavel@ucw.cz \
--cc=petr.tesarik.ext@huawei.com \
--cc=rafael@kernel.org \
--cc=rdunlap@infradead.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox