From patchwork Fri Mar 14 12:50:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 14016890 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7483B33062; Fri, 14 Mar 2025 13:23:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.96.170.134 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958591; cv=none; b=bJgiQWhzC6VPtTgpxB1ZiW39ZqyWdFhQArjIqQ23FEIeWruOiQ5zAoSnMzs8BCnT+bHY/sPEAUscaFTKQinFLwTBnvoAt1O8eR+UsWV51ngE/kuC1JIsYOz8wEUOWUt4UHl1cL2/6n87DeeuEeNv/iiFoA2rxCiFQO2/NGEtmlM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958591; c=relaxed/simple; bh=Xi6eAIqF9YoMvolpEr548W5nu/pRhUxpbEp+MqJVoug=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pSjDvQZ8MFnMT2aBOSGd6/9GItcoqL7PEqXIc2QecfIo8Uw0Hal9tARk3nGNsNDuKgv6jJ8NT6JWbodPS7tB3Ukx30OKXT++oI8O5zKn4tl6xXLmbUcuNdpIIgeywAIT4ijND2+I6A8c9UgyyF9MoY3kEEvYe3gEvWViH/7VKSQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net; spf=pass smtp.mailfrom=rjwysocki.net; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b=dnHLHjMi; arc=none smtp.client-ip=79.96.170.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b="dnHLHjMi" Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 6.3.1) id 85438b371985ad6e; Fri, 14 Mar 2025 14:23:07 +0100 Received: from kreacher.localnet (unknown [195.136.19.94]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by cloudserver094114.home.pl (Postfix) with ESMTPSA id 9C612912D03; Fri, 14 Mar 2025 14:23:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rjwysocki.net; s=dkim; t=1741958587; bh=Xi6eAIqF9YoMvolpEr548W5nu/pRhUxpbEp+MqJVoug=; h=From:Subject:Date; b=dnHLHjMi2HqXVGWzEVcSUwKzwM0/LyfPDbbSgWpI7rWUCSCLVkiS32Pm9Xv/AY2/X EU19fnoN+fjI32oF1iuhTANLrOxeeyemK4NzMjDNV6NLnIvYpWsJsLNlq78vNeYaOm bBb3tY1TlYTAxgfSUKH9hDYuTOWmVJ5iwOFGATmWxqEO2vuK4LGCv3IkyU0TZkwr7Z hAfCi+L++U7BqrNThfTnIz6NCImAiydS7uOCaf5Kn95CGJ7p2B12UARl1Fky+2oIJQ MrtBhfigioVsBVu8rj9PcrQfRP2BM20TSUiYAwPfdyRkePwxgtGvyAUYjsUlDXGs97 9Zgg2rCBg+KfQ== From: "Rafael J. Wysocki" To: Linux PM Cc: LKML , Alan Stern , Ulf Hansson , Johan Hovold , Manivannan Sadhasivam , Jon Hunter , Saravana Kannan Subject: [PATCH v3 1/5] PM: sleep: Resume children after resuming the parent Date: Fri, 14 Mar 2025 13:50:09 +0100 Message-ID: <22630663.EfDdHjke4D@rjwysocki.net> In-Reply-To: <10629535.nUPlyArG6x@rjwysocki.net> References: <10629535.nUPlyArG6x@rjwysocki.net> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CLIENT-IP: 195.136.19.94 X-CLIENT-HOSTNAME: 195.136.19.94 X-VADE-SPAMSTATE: spam:low X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddufedtleegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenogfuphgrmhfkphculdeftddtmdenucfjughrpefhvfevufffkfgjfhgggfgtsehtufertddttdejnecuhfhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqnecuggftrfgrthhtvghrnhepfeduudeutdeugfelffduieegiedtueefledvjeegffdttefhhffhtefhleejgfetnecuffhomhgrihhnpehkvghrnhgvlhdrohhrghenucfkphepudelhedrudefiedrudelrdelgeenucfuphgrmhfkphepudelhedrudefiedrudelrdelgeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepihhnvghtpeduleehrddufeeirdduledrleegpdhhvghlohepkhhrvggrtghhvghrrdhlohgtrghlnhgvthdpmhgrihhlfhhrohhmpehrjhifsehrjhifhihsohgtkhhirdhnvghtpdhnsggprhgtphhtthhopeekpdhrtghpthhtoheplhhinhhugidqphhmsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepshhtvghrnhesrhhofihlrghnugdrhhgrrhhvrghrugdrvgguuhdprhg X-DCC--Metrics: v370.home.net.pl 1024; Body=24 Fuz1=24 Fuz2=24 From: Rafael J. Wysocki According to [1], the handling of device suspend and resume, and particularly the latter, involves unnecessary overhead related to starting new async work items for devices that cannot make progress right away because they have to wait for other devices. To reduce this problem in the resume path, use the observation that starting the async resume of the children of a device after resuming the parent is likely to produce less scheduling and memory management noise than starting it upfront while at the same time it should not increase the resume duration substantially. Accordingly, modify the code to start the async resume of the device's children when the processing of the parent has been completed in each stage of device resume and only start async resume upfront for devices without parents. Also make it check if a given device can be resumed asynchronously before starting the synchronous resume of it in case it will have to wait for another that is already resuming asynchronously. In addition to making the async resume of devices more friendly to systems with relatively less computing resources, this change is also preliminary for analogous changes in the suspend path. On the systems where it has been tested, this change by itself does not affect the overall system resume duration in a measurable way. Link: https://lore.kernel.org/linux-pm/20241114220921.2529905-1-saravanak@google.com/ [1] Suggested-by: Saravana Kannan Signed-off-by: Rafael J. Wysocki --- v2 -> v3: Introduce dpm_root_device() as a wrapper around the dev->parent check, adjust comments. v1 -> v2: Use a separate lock for power.work_in_progress protection which should reduce lock contention on dpm_list_mtx. --- drivers/base/power/main.c | 85 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 19 deletions(-) --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -63,6 +63,7 @@ static DEFINE_MUTEX(dpm_list_mtx); static pm_message_t pm_transition; +static DEFINE_MUTEX(async_wip_mtx); static int async_error; static const char *pm_verb(int event) @@ -597,8 +598,11 @@ && !pm_trace_is_enabled(); } -static bool dpm_async_fn(struct device *dev, async_func_t func) +static bool __dpm_async(struct device *dev, async_func_t func) { + if (dev->power.work_in_progress) + return true; + if (!is_async(dev)) return false; @@ -611,14 +615,37 @@ put_device(dev); + return false; +} + +static bool dpm_async_fn(struct device *dev, async_func_t func) +{ + guard(mutex)(&async_wip_mtx); + + return __dpm_async(dev, func); +} + +static int dpm_async_with_cleanup(struct device *dev, void *fn) +{ + guard(mutex)(&async_wip_mtx); + + if (!__dpm_async(dev, fn)) + dev->power.work_in_progress = false; + + return 0; +} + +static void dpm_async_resume_children(struct device *dev, async_func_t func) +{ /* - * async_schedule_dev_nocall() above has returned false, so func() is - * not running and it is safe to update power.work_in_progress without - * extra synchronization. + * Start processing "async" children of the device unless it's been + * started already for them. + * + * This could have been done for the device's "async" consumers too, but + * they either need to wait for their parents or the processing has + * already started for them after their parents were processed. */ - dev->power.work_in_progress = false; - - return false; + device_for_each_child(dev, func, dpm_async_with_cleanup); } static void dpm_clear_async_state(struct device *dev) @@ -627,6 +654,13 @@ dev->power.work_in_progress = false; } +static bool dpm_root_device(struct device *dev) +{ + return !dev->parent; +} + +static void async_resume_noirq(void *data, async_cookie_t cookie); + /** * device_resume_noirq - Execute a "noirq resume" callback for given device. * @dev: Device to handle. @@ -710,6 +744,8 @@ dpm_save_failed_dev(dev_name(dev)); pm_dev_err(dev, state, async ? " async noirq" : " noirq", error); } + + dpm_async_resume_children(dev, async_resume_noirq); } static void async_resume_noirq(void *data, async_cookie_t cookie) @@ -733,19 +769,20 @@ mutex_lock(&dpm_list_mtx); /* - * Trigger the resume of "async" devices upfront so they don't have to - * wait for the "non-async" ones they don't depend on. + * Start processing "async" root devices upfront so they don't wait for + * the "sync" devices they don't depend on. */ list_for_each_entry(dev, &dpm_noirq_list, power.entry) { dpm_clear_async_state(dev); - dpm_async_fn(dev, async_resume_noirq); + if (dpm_root_device(dev)) + dpm_async_with_cleanup(dev, async_resume_noirq); } while (!list_empty(&dpm_noirq_list)) { dev = to_device(dpm_noirq_list.next); list_move_tail(&dev->power.entry, &dpm_late_early_list); - if (!dev->power.work_in_progress) { + if (!dpm_async_fn(dev, async_resume_noirq)) { get_device(dev); mutex_unlock(&dpm_list_mtx); @@ -781,6 +818,8 @@ device_wakeup_disarm_wake_irqs(); } +static void async_resume_early(void *data, async_cookie_t cookie); + /** * device_resume_early - Execute an "early resume" callback for given device. * @dev: Device to handle. @@ -848,6 +887,8 @@ dpm_save_failed_dev(dev_name(dev)); pm_dev_err(dev, state, async ? " async early" : " early", error); } + + dpm_async_resume_children(dev, async_resume_early); } static void async_resume_early(void *data, async_cookie_t cookie) @@ -875,19 +916,20 @@ mutex_lock(&dpm_list_mtx); /* - * Trigger the resume of "async" devices upfront so they don't have to - * wait for the "non-async" ones they don't depend on. + * Start processing "async" root devices upfront so they don't wait for + * the "sync" devices they don't depend on. */ list_for_each_entry(dev, &dpm_late_early_list, power.entry) { dpm_clear_async_state(dev); - dpm_async_fn(dev, async_resume_early); + if (dpm_root_device(dev)) + dpm_async_with_cleanup(dev, async_resume_early); } while (!list_empty(&dpm_late_early_list)) { dev = to_device(dpm_late_early_list.next); list_move_tail(&dev->power.entry, &dpm_suspended_list); - if (!dev->power.work_in_progress) { + if (!dpm_async_fn(dev, async_resume_early)) { get_device(dev); mutex_unlock(&dpm_list_mtx); @@ -919,6 +961,8 @@ } EXPORT_SYMBOL_GPL(dpm_resume_start); +static void async_resume(void *data, async_cookie_t cookie); + /** * device_resume - Execute "resume" callbacks for given device. * @dev: Device to handle. @@ -1018,6 +1062,8 @@ dpm_save_failed_dev(dev_name(dev)); pm_dev_err(dev, state, async ? " async" : "", error); } + + dpm_async_resume_children(dev, async_resume); } static void async_resume(void *data, async_cookie_t cookie) @@ -1049,19 +1095,20 @@ mutex_lock(&dpm_list_mtx); /* - * Trigger the resume of "async" devices upfront so they don't have to - * wait for the "non-async" ones they don't depend on. + * Start processing "async" root devices upfront so they don't wait for + * the "sync" devices they don't depend on. */ list_for_each_entry(dev, &dpm_suspended_list, power.entry) { dpm_clear_async_state(dev); - dpm_async_fn(dev, async_resume); + if (dpm_root_device(dev)) + dpm_async_with_cleanup(dev, async_resume); } while (!list_empty(&dpm_suspended_list)) { dev = to_device(dpm_suspended_list.next); list_move_tail(&dev->power.entry, &dpm_prepared_list); - if (!dev->power.work_in_progress) { + if (!dpm_async_fn(dev, async_resume)) { get_device(dev); mutex_unlock(&dpm_list_mtx); From patchwork Fri Mar 14 13:13:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 14016889 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E94071FF1D2; Fri, 14 Mar 2025 13:23:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.96.170.134 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958590; cv=none; b=EKmixEs84uNQFb0N8vP+RgvhzRxD5e8t+3TI4cLOejP1eweGYClglfkHcCbORXU080hTWsroUIrkO4cR0Z16Qi9OfIZuZcsPZMQPIubPYDmHvTVXm+idrDlsOQE1dz515yMQJaXi7cJ3MT+iIVwJCCOPxZDNw1xgoGw/rwiO5FI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958590; c=relaxed/simple; bh=uFotQyJj/99NJnpmnWY+BRTYNvnCO0dKOi2xTk3WIr0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=OV1oaBF42aOuJU0E+JqntB1Y+lGedtTWcFQtLE6uRussA3Eh+u1m74RMXWLCNgKfKXpZDXkPATdLPypIajoSS0jFzZhnE/jqj2b0/DMKpI7BVzpeAW1lgt8EXIsHd/6kcROORrh8zrWiR3YpuLbk9dUJXk5xgSAO+K1jJZXldws= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net; spf=pass smtp.mailfrom=rjwysocki.net; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b=GHHgdLaI; arc=none smtp.client-ip=79.96.170.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b="GHHgdLaI" Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 6.3.1) id 5de17aa8f3a25c7b; Fri, 14 Mar 2025 14:23:05 +0100 Received: from kreacher.localnet (unknown [195.136.19.94]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by cloudserver094114.home.pl (Postfix) with ESMTPSA id 2E3B5912CFB; Fri, 14 Mar 2025 14:23:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rjwysocki.net; s=dkim; t=1741958585; bh=uFotQyJj/99NJnpmnWY+BRTYNvnCO0dKOi2xTk3WIr0=; h=From:Subject:Date; b=GHHgdLaIMXUTiGKuSUVr6lEFdPG9psLgesVI0wS/xscN1qw+KUWRyxEXlrzU8zn9l 0xCiAD+OOoRh6tpe0SehW6TdmGTUn4XCqmjptMSG6Z0CuGdi4rqtIyODGCmm9zOEA1 CnSJXviVIc/XzpnG+CJk3CR4HnDckLG0Yuj3QJpqaBIQm5qEs44app460CK28i3vVs ElcQFtv6OMW6kau6Ow00Qgz6BHQw09xb0MzJm/FyG030wcXIJdmCyeCyJJ8bUMaEPZ ANH79PmAD7BIEzIMF/70izwEPL7udYCQ06I6dek75Oq6kPhizHp27wujqaswCyg9sM kg4MEE6yYMHGQ== From: "Rafael J. Wysocki" To: Linux PM Cc: LKML , Alan Stern , Ulf Hansson , Johan Hovold , Manivannan Sadhasivam , Jon Hunter , Saravana Kannan Subject: [PATCH v3 2/5] PM: sleep: Suspend async parents after suspending children Date: Fri, 14 Mar 2025 14:13:53 +0100 Message-ID: <3541233.QJadu78ljV@rjwysocki.net> In-Reply-To: <10629535.nUPlyArG6x@rjwysocki.net> References: <10629535.nUPlyArG6x@rjwysocki.net> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CLIENT-IP: 195.136.19.94 X-CLIENT-HOSTNAME: 195.136.19.94 X-VADE-SPAMSTATE: spam:low X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddufedtleegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenogfuphgrmhfkphculdeftddtmdenucfjughrpefhvfevufffkfgjfhgggfgtsehtufertddttdejnecuhfhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqnecuggftrfgrthhtvghrnhepvdffueeitdfgvddtudegueejtdffteetgeefkeffvdeftddttdeuhfegfedvjefhnecukfhppeduleehrddufeeirdduledrleegnecuufhprghmkfhppeduleehrddufeeirdduledrleegnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepudelhedrudefiedrudelrdelgedphhgvlhhopehkrhgvrggthhgvrhdrlhhotggrlhhnvghtpdhmrghilhhfrhhomheprhhjfiesrhhjfiihshhotghkihdrnhgvthdpnhgspghrtghpthhtohepkedprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehsthgvrhhnsehrohiflhgrnhgurdhhrghrvhgrrhgurdgvughupdhrtghpthhtohepuhhlfhdrhhgrnhhsshhonheslhh X-DCC--Metrics: v370.home.net.pl 1024; Body=24 Fuz1=24 Fuz2=24 From: Rafael J. Wysocki In analogy with the previous change affecting the resume path, make device_suspend() start the async suspend of the device's parent after the device itself has been processed and make dpm_suspend() start processing "async" leaf devices (that is, devices without children) upfront so they don't need to wait for the "sync" devices they don't depend on. On the Dell XPS13 9360 in my office, this change reduces the total duration of device suspend by approximately 100 ms (over 20%). Suggested-by: Saravana Kannan Signed-off-by: Rafael J. Wysocki --- v2 -> v3: * When starting async processing early, only take parents and children into account. * Refine parent check in dpm_async_suspend_parent(). * Use list_splice() for merging lists on errors. * Adjust subject and changelog. * Adjust comments. v1 -> v2: * Adjust for the changes in patch [1/3]. * Fix walking suppliers in dpm_async_suspend_superior(). * Use device links read locking in dpm_async_suspend_superior() (Saravana). * Move all devices to the target list even if there are errors in dpm_suspend() so they are properly resumed during rollback (Saravana). --- drivers/base/power/main.c | 67 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 4 deletions(-) --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1236,6 +1236,41 @@ /*------------------------- Suspend routines -------------------------*/ +static bool dpm_leaf_device(struct device *dev) +{ + struct device *child; + + lockdep_assert_held(&dpm_list_mtx); + + child = device_find_any_child(dev); + if (child) { + put_device(child); + + return false; + } + + return true; +} + +static void dpm_async_suspend_parent(struct device *dev, async_func_t func) +{ + guard(mutex)(&dpm_list_mtx); + + /* + * If the device is suspended asynchronously and the parent's callback + * deletes both the device and the parent itself, the parent object may + * be freed while this function is running, so avoid that by checking + * if the device has been deleted already as the parent cannot be + * deleted before it. + */ + if (!device_pm_initialized(dev)) + return; + + /* Start processing the device's parent if it is "async". */ + if (dev->parent) + dpm_async_with_cleanup(dev->parent, func); +} + /** * resume_event - Return a "resume" message for given "suspend" sleep state. * @sleep_state: PM message representing a sleep state. @@ -1661,6 +1696,8 @@ device_links_read_unlock(idx); } +static void async_suspend(void *data, async_cookie_t cookie); + /** * device_suspend - Execute "suspend" callbacks for given device. * @dev: Device to handle. @@ -1790,7 +1827,13 @@ complete_all(&dev->power.completion); TRACE_SUSPEND(error); - return error; + + if (error || async_error) + return error; + + dpm_async_suspend_parent(dev, async_suspend); + + return 0; } static void async_suspend(void *data, async_cookie_t cookie) @@ -1808,6 +1851,7 @@ int dpm_suspend(pm_message_t state) { ktime_t starttime = ktime_get(); + struct device *dev; int error = 0; trace_suspend_resume(TPS("dpm_suspend"), state.event, true); @@ -1821,12 +1865,21 @@ mutex_lock(&dpm_list_mtx); + /* + * Start processing "async" leaf devices upfront so they don't need to + * wait for the "sync" devices they don't depend on. + */ + list_for_each_entry_reverse(dev, &dpm_prepared_list, power.entry) { + dpm_clear_async_state(dev); + if (dpm_leaf_device(dev)) + dpm_async_with_cleanup(dev, async_suspend); + } + while (!list_empty(&dpm_prepared_list)) { - struct device *dev = to_device(dpm_prepared_list.prev); + dev = to_device(dpm_prepared_list.prev); list_move(&dev->power.entry, &dpm_suspended_list); - dpm_clear_async_state(dev); if (dpm_async_fn(dev, async_suspend)) continue; @@ -1840,8 +1893,14 @@ mutex_lock(&dpm_list_mtx); - if (error || async_error) + if (error || async_error) { + /* + * Move all devices to the target list to resume them + * properly. + */ + list_splice(&dpm_prepared_list, &dpm_suspended_list); break; + } } mutex_unlock(&dpm_list_mtx); From patchwork Fri Mar 14 13:14:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 14016877 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6C9E21FE44C; Fri, 14 Mar 2025 13:19:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.96.170.134 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958367; cv=none; b=dZzKxdFq65V+s4FCZYurLovWfXhWkLY+H/OoKRdVyxJAI3O6olvoCfY/fDx82eTa6xOCuNEL6V8PRziQTE1h6mK22dzLH2Ns9pzJ/4Z5g5pn7jxLXACqPAmJY88kULCpwaZna7AJa4c2tAVrYJcormYqbY23s/dpWaNduWQ3HKE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958367; c=relaxed/simple; bh=+TLFi6zGn84ndYCYlPnSlEB/FndOyxFdAhy3aD2xDak=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mMS+jeY5QjMXxzSHr8MpMp/wuFO5OZEugcGS5qIKwStkX4KHlCz02QDPPgupKISn1pCoDLnqPO6Q4StUSXxUKciMaW1fZBH3tWpcD9BXFOtApZSY+y4wPCwLFHSGJDoNv1wEN9bzSl7h3ZVuYEQ7Uh6CMRcC36NLXpx99r/RvG4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net; spf=pass smtp.mailfrom=rjwysocki.net; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b=bE5qpaLT; arc=none smtp.client-ip=79.96.170.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b="bE5qpaLT" Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 6.3.1) id f27c172963a66e5f; Fri, 14 Mar 2025 14:19:23 +0100 Received: from kreacher.localnet (unknown [195.136.19.94]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by cloudserver094114.home.pl (Postfix) with ESMTPSA id D2222912CFA; Fri, 14 Mar 2025 14:19:22 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rjwysocki.net; s=dkim; t=1741958363; bh=+TLFi6zGn84ndYCYlPnSlEB/FndOyxFdAhy3aD2xDak=; h=From:Subject:Date; b=bE5qpaLT5vih/iOq8DV5KaLz0Ofx5+j4ScSmVus2TpkE6eS/nbiI3l8G5dnjcaWkA xo3aRAlD4GylZihdVT70Z1C89APc87bqyHJWwGz+RDd4llxrV3bjPwuFp/EtCTWmeT YFeqtvVfOQR4gm11Nr/llg997C6Qu93RMq9yNMBfFRXIcVAjy8GM3lwgWpvKR/Kt26 jSyQXtsg8aAOwXu5/SyBgfxW1kU4N6i1zV84QBVsOdPrMP7tgUp0q4t4o1TxFjqwOd tRMcM+66ziEyn3+LnBQv2QJPyCjruQ+F1x3SUJqKvQWVO3LM6HU7DT/YtZ4TdwlVng 4t5jxLJfMUe6A== From: "Rafael J. Wysocki" To: Linux PM Cc: LKML , Alan Stern , Ulf Hansson , Johan Hovold , Manivannan Sadhasivam , Jon Hunter , Saravana Kannan Subject: [PATCH v3 3/5] PM: sleep: Make suspend of devices more asynchronous Date: Fri, 14 Mar 2025 14:14:30 +0100 Message-ID: <1924195.CQOukoFCf9@rjwysocki.net> In-Reply-To: <10629535.nUPlyArG6x@rjwysocki.net> References: <10629535.nUPlyArG6x@rjwysocki.net> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CLIENT-IP: 195.136.19.94 X-CLIENT-HOSTNAME: 195.136.19.94 X-VADE-SPAMSTATE: spam:low X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddufedtleegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenogfuphgrmhfkphculdeftddtmdenucfjughrpefhvfevufffkfgjfhgggfgtsehtufertddttdejnecuhfhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqnecuggftrfgrthhtvghrnhepvdffueeitdfgvddtudegueejtdffteetgeefkeffvdeftddttdeuhfegfedvjefhnecukfhppeduleehrddufeeirdduledrleegnecuufhprghmkfhppeduleehrddufeeirdduledrleegnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepudelhedrudefiedrudelrdelgedphhgvlhhopehkrhgvrggthhgvrhdrlhhotggrlhhnvghtpdhmrghilhhfrhhomheprhhjfiesrhhjfiihshhotghkihdrnhgvthdpnhgspghrtghpthhtohepkedprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehsthgvrhhnsehrohiflhgrnhgurdhhrghrvhgrrhgurdgvughupdhrtghpthhtohepuhhlfhdrhhgrnhhsshhonheslhh X-DCC--Metrics: v370.home.net.pl 1024; Body=16 Fuz1=16 Fuz2=16 From: Rafael J. Wysocki In analogy with previous changes, make device_suspend_late() and device_suspend_noirq() start the async suspend of the device's parent after the device itself has been processed and make dpm_suspend_late() and dpm_noirq_suspend_devices() start processing "async" leaf devices (that is, devices without children) upfront so they don't need to wait for the other devices they don't depend on. This change reduces the total duration of device suspend on some systems measurably, but not significantly. Suggested-by: Saravana Kannan Signed-off-by: Rafael J. Wysocki --- v2 -> v3: * Adjust for the changes made in patch [2/5]. * Use list_splice() for merging lists on errors. * Adjust changelog. v1 -> v2: * Adjust for the changes in patches [1-2/3]. * Move all devices to the target lists even if there are errors in dpm_suspend_late() and dpm_noirq_suspend_devices() so they are properly resumed during rollback (Saravana). --- drivers/base/power/main.c | 64 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1308,6 +1308,8 @@ device_links_read_unlock(idx); } +static void async_suspend_noirq(void *data, async_cookie_t cookie); + /** * device_suspend_noirq - Execute a "noirq suspend" callback for given device. * @dev: Device to handle. @@ -1386,7 +1388,13 @@ Complete: complete_all(&dev->power.completion); TRACE_SUSPEND(error); - return error; + + if (error || async_error) + return error; + + dpm_async_suspend_parent(dev, async_suspend_noirq); + + return 0; } static void async_suspend_noirq(void *data, async_cookie_t cookie) @@ -1400,6 +1408,7 @@ static int dpm_noirq_suspend_devices(pm_message_t state) { ktime_t starttime = ktime_get(); + struct device *dev; int error = 0; trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, true); @@ -1409,12 +1418,21 @@ mutex_lock(&dpm_list_mtx); + /* + * Start processing "async" leaf devices upfront so they don't need to + * wait for the "sync" devices they don't depend on. + */ + list_for_each_entry_reverse(dev, &dpm_late_early_list, power.entry) { + dpm_clear_async_state(dev); + if (dpm_leaf_device(dev)) + dpm_async_with_cleanup(dev, async_suspend_noirq); + } + while (!list_empty(&dpm_late_early_list)) { - struct device *dev = to_device(dpm_late_early_list.prev); + dev = to_device(dpm_late_early_list.prev); list_move(&dev->power.entry, &dpm_noirq_list); - dpm_clear_async_state(dev); if (dpm_async_fn(dev, async_suspend_noirq)) continue; @@ -1428,8 +1446,14 @@ mutex_lock(&dpm_list_mtx); - if (error || async_error) + if (error || async_error) { + /* + * Move all devices to the target list to resume them + * properly. + */ + list_splice(&dpm_late_early_list, &dpm_noirq_list); break; + } } mutex_unlock(&dpm_list_mtx); @@ -1482,6 +1506,8 @@ spin_unlock_irq(&parent->power.lock); } +static void async_suspend_late(void *data, async_cookie_t cookie); + /** * device_suspend_late - Execute a "late suspend" callback for given device. * @dev: Device to handle. @@ -1558,7 +1584,13 @@ Complete: TRACE_SUSPEND(error); complete_all(&dev->power.completion); - return error; + + if (error || async_error) + return error; + + dpm_async_suspend_parent(dev, async_suspend_late); + + return 0; } static void async_suspend_late(void *data, async_cookie_t cookie) @@ -1576,6 +1608,7 @@ int dpm_suspend_late(pm_message_t state) { ktime_t starttime = ktime_get(); + struct device *dev; int error = 0; trace_suspend_resume(TPS("dpm_suspend_late"), state.event, true); @@ -1587,12 +1620,21 @@ mutex_lock(&dpm_list_mtx); + /* + * Start processing "async" leaf devices upfront so they don't need to + * wait for the "sync" devices they don't depend on. + */ + list_for_each_entry_reverse(dev, &dpm_suspended_list, power.entry) { + dpm_clear_async_state(dev); + if (dpm_leaf_device(dev)) + dpm_async_with_cleanup(dev, async_suspend_late); + } + while (!list_empty(&dpm_suspended_list)) { - struct device *dev = to_device(dpm_suspended_list.prev); + dev = to_device(dpm_suspended_list.prev); list_move(&dev->power.entry, &dpm_late_early_list); - dpm_clear_async_state(dev); if (dpm_async_fn(dev, async_suspend_late)) continue; @@ -1606,8 +1648,14 @@ mutex_lock(&dpm_list_mtx); - if (error || async_error) + if (error || async_error) { + /* + * Move all devices to the target list to resume them + * properly. + */ + list_splice(&dpm_suspended_list, &dpm_late_early_list); break; + } } mutex_unlock(&dpm_list_mtx); From patchwork Fri Mar 14 13:16:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 14016876 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2E3B33062; Fri, 14 Mar 2025 13:19:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.96.170.134 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958367; cv=none; b=GZkSQkip+FH5o0OTL0UfDth/aVUMKOJpxYAav9S/unSVM+5iVZ8vTfGN5JmHQj4F56lRXGMv1TFzsTz2EuEaa5j/QXbWnb9QHpRl3Wfi9F59ABa+UJssc8kRHq3EHLbUNiKt2Ijh5ZghaKUOWRXaL4L+8WIsFQC1cvq+aaj+pw8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958367; c=relaxed/simple; bh=QmeYUs+yErlkIvOvXDo3UhtL+w7L7+0X2Hz8PQcj7Ak=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UQLD3Wbu0S0ekvIicrazKplMmByJGIqn4cRRrekIf0V6clXDxgdYkrVFbolIi2MNya+jD9Q2HRFTMOFQZi0Kjpo4/KrdB3oWvZgEYaycDISFWhqcJLT6FGrqNfiEP9uc8j87Bome0UrjI3I2jt6aWFG1+jzRTfZXwu3nGoHXW60= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net; spf=pass smtp.mailfrom=rjwysocki.net; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b=fCGRUF1r; arc=none smtp.client-ip=79.96.170.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b="fCGRUF1r" Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 6.3.1) id 6c10fbdd4048e413; Fri, 14 Mar 2025 14:19:22 +0100 Received: from kreacher.localnet (unknown [195.136.19.94]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by cloudserver094114.home.pl (Postfix) with ESMTPSA id 11B66912CFB; Fri, 14 Mar 2025 14:19:22 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rjwysocki.net; s=dkim; t=1741958362; bh=QmeYUs+yErlkIvOvXDo3UhtL+w7L7+0X2Hz8PQcj7Ak=; h=From:Subject:Date; b=fCGRUF1rQZGrG8nnY8L26mFuDsV767N9RBeDfEnDqHSFsiw3H6yd9pTwOiLbcjDU7 5tn1bjI484/5T2dInlx0Fl41aCk3cRaUlx41qxxB034f0/ytRASU9lkH0sxkb6Kk4P hz1ks4jcq48vluuTzXIhKO7WO27vc/R9DHjXZ6IwP4hqICNViQaIr9/5GaNb6kwj9E oMxbkMQ7EI3yzynRUbhQrqGje2Hu0y6t0DNWKtOvDmsOuCcnDy4FdTDa2CjHqwbyOj LcTvQd8jno5UugUZDnl+QItZWRp4fnkuBo9hJZN15L0BW/wqAWxInqjx4apwsfPeeu LTmJV/i8p2UXg== From: "Rafael J. Wysocki" To: Linux PM Cc: LKML , Alan Stern , Ulf Hansson , Johan Hovold , Manivannan Sadhasivam , Jon Hunter , Saravana Kannan Subject: [PATCH v3 4/5] PM: sleep: Make async suspend handle suppliers like parents Date: Fri, 14 Mar 2025 14:16:33 +0100 Message-ID: <2651185.Lt9SDvczpP@rjwysocki.net> In-Reply-To: <10629535.nUPlyArG6x@rjwysocki.net> References: <10629535.nUPlyArG6x@rjwysocki.net> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CLIENT-IP: 195.136.19.94 X-CLIENT-HOSTNAME: 195.136.19.94 X-VADE-SPAMSTATE: spam:low X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddufedtleegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenogfuphgrmhfkphculdeftddtmdenucfjughrpefhvfevufffkfgjfhgggfgtsehtufertddttdejnecuhfhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqnecuggftrfgrthhtvghrnhepvdffueeitdfgvddtudegueejtdffteetgeefkeffvdeftddttdeuhfegfedvjefhnecukfhppeduleehrddufeeirdduledrleegnecuufhprghmkfhppeduleehrddufeeirdduledrleegnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepudelhedrudefiedrudelrdelgedphhgvlhhopehkrhgvrggthhgvrhdrlhhotggrlhhnvghtpdhmrghilhhfrhhomheprhhjfiesrhhjfiihshhotghkihdrnhgvthdpnhgspghrtghpthhtohepkedprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehsthgvrhhnsehrohiflhgrnhgurdhhrghrvhgrrhgurdgvughupdhrtghpthhtohepuhhlfhdrhhgrnhhsshhonheslhh X-DCC--Metrics: v370.home.net.pl 1024; Body=16 Fuz1=16 Fuz2=16 From: Rafael J. Wysocki Following previous changes, avoid starting "async" suspend processing upfront for devices that have consumers and start "async" suspend processing for the supplies of a device after suspending the device itself. Suggested-by: Saravana Kannan Signed-off-by: Rafael J. Wysocki --- New patch in v3. --- drivers/base/power/main.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1249,10 +1249,15 @@ return false; } - return true; + /* + * Since this function is required to run under dpm_list_mtx, the + * list_empty() below will only return true if the device's list of + * consumers is actually empty before calling it. + */ + return list_empty(&dev->links.consumers); } -static void dpm_async_suspend_parent(struct device *dev, async_func_t func) +static bool dpm_async_suspend_parent(struct device *dev, async_func_t func) { guard(mutex)(&dpm_list_mtx); @@ -1264,11 +1269,31 @@ * deleted before it. */ if (!device_pm_initialized(dev)) - return; + return false; /* Start processing the device's parent if it is "async". */ if (dev->parent) dpm_async_with_cleanup(dev->parent, func); + + return true; +} + +static void dpm_async_suspend_superior(struct device *dev, async_func_t func) +{ + struct device_link *link; + int idx; + + if (!dpm_async_suspend_parent(dev, func)) + return; + + idx = device_links_read_lock(); + + /* Start processing the device's "async" suppliers. */ + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) + if (READ_ONCE(link->status) != DL_STATE_DORMANT) + dpm_async_with_cleanup(link->supplier, func); + + device_links_read_unlock(idx); } /** @@ -1392,7 +1417,7 @@ if (error || async_error) return error; - dpm_async_suspend_parent(dev, async_suspend_noirq); + dpm_async_suspend_superior(dev, async_suspend_noirq); return 0; } @@ -1588,7 +1613,7 @@ if (error || async_error) return error; - dpm_async_suspend_parent(dev, async_suspend_late); + dpm_async_suspend_superior(dev, async_suspend_late); return 0; } @@ -1879,7 +1904,7 @@ if (error || async_error) return error; - dpm_async_suspend_parent(dev, async_suspend); + dpm_async_suspend_superior(dev, async_suspend); return 0; } From patchwork Fri Mar 14 13:17:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 14016875 Received: from cloudserver094114.home.pl (cloudserver094114.home.pl [79.96.170.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E664933062; Fri, 14 Mar 2025 13:18:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.96.170.134 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958295; cv=none; b=Qbg2M5y2nGDtZU7MgKBikro6AoZGZqqftK7ZPi2F9m/BCNBijI57x8b6REhx0O/uWYKz0iYf+jWmCMmJ56wYKC8Xe33umUKA23wG0oSpl3kvCoQrcWUkhLwdEIN6UhPZhZK6KuIh3AkPoblMZSHucTpXV+3xuA4N+Y7wNQFd1g8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741958295; c=relaxed/simple; bh=blpXADKX8e7JmQIhOP9B/BojEHJX9bhu7Scx5IP2vT0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qEVeIYNNar9RnUgqU/yzEQeaApyhxZwMkSb2DWja4ENRp2Qj7ni8V7XhV1Zjt8eHEEHEOTj31QNuztvp7ZEDn97WUbTbv1KHvRSdrnMwLBZtYu6TlTfztNCR5iOD2ALulWTCOicgRvvU0Q8q6ieLneJgQsWrw4izyZyfNu3S2IA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net; spf=pass smtp.mailfrom=rjwysocki.net; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b=KaM7EbtN; arc=none smtp.client-ip=79.96.170.134 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rjwysocki.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rjwysocki.net header.i=@rjwysocki.net header.b="KaM7EbtN" Received: from localhost (127.0.0.1) (HELO v370.home.net.pl) by /usr/run/smtp (/usr/run/postfix/private/idea_relay_lmtp) via UNIX with SMTP (IdeaSmtpServer 6.3.1) id 7074daa21ebd8cc8; Fri, 14 Mar 2025 14:18:10 +0100 Received: from kreacher.localnet (unknown [195.136.19.94]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by cloudserver094114.home.pl (Postfix) with ESMTPSA id F2C72912CFA; Fri, 14 Mar 2025 14:18:09 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=rjwysocki.net; s=dkim; t=1741958290; bh=blpXADKX8e7JmQIhOP9B/BojEHJX9bhu7Scx5IP2vT0=; h=From:Subject:Date; b=KaM7EbtNkeayM2Ox260zSpqSdOmFz+w/1v6yltjdsJE4ix9ruAWbcbD3b/0mCnWTz v76Kj0XkfNCeYs3wvWpyKuXoISwmRFNmnm8rhpaOlJHnCZouDFGhGyAVZZ/NNzNgUE pA4dNaU1CTl84kHaxV487WMV54TvBgXSeOkOEQSjJR1sqTw1RnvtBH/d4TzaayVSYp 2S09+TdkiGIboXHCYkF4W4ztGtYAfGk63bnpbGEYfzd2o8/Z7qvtS52PyGZ+8+jKSq GZI/6odfCsyqd7nstoGl78Z6S0t73D95stERQe6YKtNeWOcgnDWxoj7MC18P1yJ+c7 hM0kIp78r5ryQ== From: "Rafael J. Wysocki" To: Linux PM Cc: LKML , Alan Stern , Ulf Hansson , Johan Hovold , Manivannan Sadhasivam , Jon Hunter , Saravana Kannan Subject: [PATCH v3 5/5] PM: sleep: Make async resume handle consumers like children Date: Fri, 14 Mar 2025 14:17:49 +0100 Message-ID: <2229735.Mh6RI2rZIc@rjwysocki.net> In-Reply-To: <10629535.nUPlyArG6x@rjwysocki.net> References: <10629535.nUPlyArG6x@rjwysocki.net> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CLIENT-IP: 195.136.19.94 X-CLIENT-HOSTNAME: 195.136.19.94 X-VADE-SPAMSTATE: spam:low X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddufedtleefucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffqoffgrffnpdggtffipffknecuuegrihhlohhuthemucduhedtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenogfuphgrmhfkphculdeftddtmdenucfjughrpefhvfevufffkfgjfhgggfgtsehtufertddttdejnecuhfhrohhmpedftfgrfhgrvghlucflrdcuhgihshhotghkihdfuceorhhjfiesrhhjfiihshhotghkihdrnhgvtheqnecuggftrfgrthhtvghrnhepvdffueeitdfgvddtudegueejtdffteetgeefkeffvdeftddttdeuhfegfedvjefhnecukfhppeduleehrddufeeirdduledrleegnecuufhprghmkfhppeduleehrddufeeirdduledrleegnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepudelhedrudefiedrudelrdelgedphhgvlhhopehkrhgvrggthhgvrhdrlhhotggrlhhnvghtpdhmrghilhhfrhhomheprhhjfiesrhhjfiihshhotghkihdrnhgvthdpnhgspghrtghpthhtohepkedprhgtphhtthhopehlihhnuhigqdhpmhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehsthgvrhhnsehrohiflhgrnhgurdhhrghrvhgrrhgurdgvughupdhrtghpthhtohepuhhlfhdrhhgrnhhsshhonheslhh X-DCC--Metrics: v370.home.net.pl 1024; Body=8 Fuz1=8 Fuz2=8 From: Rafael J. Wysocki Following previous changes, avoid starting "async" resume processing upfront for devices that have suppliers and start "async" resume processing for the consumers of a device after resuming the device itself. Suggested-by: Saravana Kannan Signed-off-by: Rafael J. Wysocki --- New patch in v3. --- drivers/base/power/main.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -635,17 +635,25 @@ return 0; } -static void dpm_async_resume_children(struct device *dev, async_func_t func) +static void dpm_async_resume_subordinate(struct device *dev, async_func_t func) { + struct device_link *link; + int idx; + /* * Start processing "async" children of the device unless it's been * started already for them. - * - * This could have been done for the device's "async" consumers too, but - * they either need to wait for their parents or the processing has - * already started for them after their parents were processed. */ device_for_each_child(dev, func, dpm_async_with_cleanup); + + idx = device_links_read_lock(); + + /* Start processing the device's "async" consumers. */ + list_for_each_entry_rcu(link, &dev->links.consumers, s_node) + if (READ_ONCE(link->status) != DL_STATE_DORMANT) + dpm_async_with_cleanup(link->consumer, func); + + device_links_read_unlock(idx); } static void dpm_clear_async_state(struct device *dev) @@ -656,7 +664,14 @@ static bool dpm_root_device(struct device *dev) { - return !dev->parent; + lockdep_assert_held(&dpm_list_mtx); + + /* + * Since this function is required to run under dpm_list_mtx, the + * list_empty() below will only return true if the device's list of + * consumers is actually empty before calling it. + */ + return !dev->parent && list_empty(&dev->links.suppliers); } static void async_resume_noirq(void *data, async_cookie_t cookie); @@ -745,7 +760,7 @@ pm_dev_err(dev, state, async ? " async noirq" : " noirq", error); } - dpm_async_resume_children(dev, async_resume_noirq); + dpm_async_resume_subordinate(dev, async_resume_noirq); } static void async_resume_noirq(void *data, async_cookie_t cookie) @@ -888,7 +903,7 @@ pm_dev_err(dev, state, async ? " async early" : " early", error); } - dpm_async_resume_children(dev, async_resume_early); + dpm_async_resume_subordinate(dev, async_resume_early); } static void async_resume_early(void *data, async_cookie_t cookie) @@ -1063,7 +1078,7 @@ pm_dev_err(dev, state, async ? " async" : "", error); } - dpm_async_resume_children(dev, async_resume); + dpm_async_resume_subordinate(dev, async_resume); } static void async_resume(void *data, async_cookie_t cookie)