Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2225199/?format=api
{ "id": 2225199, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2225199/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/patch/20260420152608.6244-4-djeffery@redhat.com/", "project": { "id": 28, "url": "http://patchwork.ozlabs.org/api/1.1/projects/28/?format=api", "name": "Linux PCI development", "link_name": "linux-pci", "list_id": "linux-pci.vger.kernel.org", "list_email": "linux-pci@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null }, "msgid": "<20260420152608.6244-4-djeffery@redhat.com>", "date": "2026-04-20T15:26:06", "name": "[3/5] driver core: async device shutdown infrastructure", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "3a4b8dcd82dbdebeead6bbb0d9b20b9efad496b3", "submitter": { "id": 24471, "url": "http://patchwork.ozlabs.org/api/1.1/people/24471/?format=api", "name": "David Jeffery", "email": "djeffery@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-pci/patch/20260420152608.6244-4-djeffery@redhat.com/mbox/", "series": [ { "id": 500621, "url": "http://patchwork.ozlabs.org/api/1.1/series/500621/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/list/?series=500621", "date": "2026-04-20T15:26:04", "name": "shut down devices asynchronously", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/500621/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2225199/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2225199/checks/", "tags": {}, "headers": { "Return-Path": "\n <linux-pci+bounces-52787-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-pci@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=Fv0UEh8g;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.232.135.74; helo=sto.lore.kernel.org;\n envelope-from=linux-pci+bounces-52787-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.b=\"Fv0UEh8g\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=170.10.133.124", "smtp.subspace.kernel.org;\n dmarc=pass (p=quarantine dis=none) header.from=redhat.com", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=redhat.com" ], "Received": [ "from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fzqL43jVfz1yGs\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 21 Apr 2026 01:34:52 +1000 (AEST)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sto.lore.kernel.org (Postfix) with ESMTP id 655B43041B27\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 15:27:14 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id E92FB2FDC53;\n\tMon, 20 Apr 2026 15:26:53 +0000 (UTC)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C3262F5A34\n\tfor <linux-pci@vger.kernel.org>; Mon, 20 Apr 2026 15:26:49 +0000 (UTC)", "from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-626-PBUATNn4NMiljq0Z2UR1Qw-1; Mon,\n 20 Apr 2026 11:26:44 -0400", "from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id BDCFA1800473;\n\tMon, 20 Apr 2026 15:26:36 +0000 (UTC)", "from fedora-work.redhat.com (unknown [10.22.65.236])\n\tby mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 1494519560AB;\n\tMon, 20 Apr 2026 15:26:32 +0000 (UTC)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776698812; cv=none;\n b=JJLp8RsDDwR5v4HEEwzH5lfScpHsNO0R8W85bw5Rdi334sWZkEl77QhiAzoaBDMSQTMxObAua4BhGBBQZyt8jM9+SD82O74Aj8tW2FGUYpkRJ/IFpS83+VHIAJvwpzusbmXuB9Z8pOgNMsfY8L3jwBmjk8NvIdCbOY9GFlIR0A8=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776698812; c=relaxed/simple;\n\tbh=O30oSc4d6sJlnbWft49fam2+wUGO4ozeEfpz38lhXhY=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=i6GvXZP8NE/6HxPGVDEYbqXEAvBTCXZr4EIiDliryKLrzJ6VVvdEQhbm2fkULpIfN02uE68qU1WAhkCay6IQUJ7MyIB5SMGoVyklN06aVhdCOgP5QvZsUDuv81vG1WV3jCOiwawlNosbNuXO2siI3GyXsvSxHzNdz0i1bEhJYYo=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=quarantine dis=none) header.from=redhat.com;\n spf=pass smtp.mailfrom=redhat.com;\n dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.b=Fv0UEh8g; arc=none smtp.client-ip=170.10.133.124", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1776698808;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\t to:to:cc:cc:mime-version:mime-version:\n\t content-transfer-encoding:content-transfer-encoding:\n\t in-reply-to:in-reply-to:references:references;\n\tbh=cQ5AT1tbzICKr3jOKLeamrF5qJVCjqopcrnJXPTkUYk=;\n\tb=Fv0UEh8gTitEDW6WR3bjmuA5/L302KbR/bxIbFOsTwtzRDLapKvjcLXQu88XVTvn79ZyUI\n\tyXd8ErvOaSEH81M35piuSb8yPvaoExeEurJwofQYe5gYXOkMyzz8z+vGIoFnOxGXTl/pWO\n\tf2QOtKHiMw8SmewLe0boT+cwlN3afUc=", "X-MC-Unique": "PBUATNn4NMiljq0Z2UR1Qw-1", "X-Mimecast-MFC-AGG-ID": "PBUATNn4NMiljq0Z2UR1Qw_1776698796", "From": "David Jeffery <djeffery@redhat.com>", "To": "linux-kernel@vger.kernel.org,\n\tdriver-core@lists.linux.dev,\n\tlinux-pci@vger.kernel.org,\n\tlinux-scsi@vger.kernel.org,\n\tGreg Kroah-Hartman <gregkh@linuxfoundation.org>,\n\t\"Rafael J. Wysocki\" <rafael@kernel.org>,\n\tDanilo Krummrich <dakr@kernel.org>", "Cc": "Tarun Sahu <tarunsahu@google.com>, Pasha Tatashin <tatashin@google.com>,\n\t=?utf-8?b?TWljaGHFgiBDxYJhcGnFhHNraQ==?= <mclapinski@google.com>,\n Jordan Richards <jordanrichards@google.com>, Ewan Milne <emilne@redhat.com>,\n John Meneghini <jmeneghi@redhat.com>, \"Lombardi,\n Maurizio\" <mlombard@redhat.com>, Stuart Hayes <stuart.w.hayes@gmail.com>,\n Laurence Oberman <loberman@redhat.com>, Bart Van Assche <bvanassche@acm.org>,\n Bjorn Helgaas <helgaas@kernel.org>,\n \"Martin K . Petersen\" <martin.petersen@oracle.com>,\n John Garry <john.g.garry@oracle.com>, David Jeffery <djeffery@redhat.com>", "Subject": "[PATCH 3/5] driver core: async device shutdown infrastructure", "Date": "Mon, 20 Apr 2026 11:26:06 -0400", "Message-ID": "<20260420152608.6244-4-djeffery@redhat.com>", "In-Reply-To": "<20260420152608.6244-1-djeffery@redhat.com>", "References": "<20260420152608.6244-1-djeffery@redhat.com>", "Precedence": "bulk", "X-Mailing-List": "linux-pci@vger.kernel.org", "List-Id": "<linux-pci.vger.kernel.org>", "List-Subscribe": "<mailto:linux-pci+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-pci+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.12" }, "content": "Patterned after async suspend, allow devices to mark themselves as wanting\nto perform async shutdown. Devices using async shutdown wait only for their\ndependencies to shutdown before executing their shutdown routine.\n\nSync shutdown devices are shut down one at a time and will only wait for an\nasync shutdown device if the async device is a dependency.\n\nSigned-off-by: David Jeffery <djeffery@redhat.com>\nSigned-off-by: Stuart Hayes <stuart.w.hayes@gmail.com>\nTested-by: Laurence Oberman <loberman@redhat.com>\n---\n drivers/base/base.h | 2 +\n drivers/base/core.c | 101 ++++++++++++++++++++++++++++++++++++++++-\n include/linux/device.h | 13 ++++++\n 3 files changed, 115 insertions(+), 1 deletion(-)", "diff": "diff --git a/drivers/base/base.h b/drivers/base/base.h\nindex 1af95ac68b77..cd435adeeac5 100644\n--- a/drivers/base/base.h\n+++ b/drivers/base/base.h\n@@ -113,6 +113,7 @@ struct driver_type {\n * @device - pointer back to the struct device that this structure is\n * associated with.\n * @driver_type - The type of the bound Rust driver.\n+ * @complete - completion for device shutdown ordering\n * @dead - This device is currently either in the process of or has been\n *\tremoved from the system. Any asynchronous events scheduled for this\n *\tdevice should exit without taking any action.\n@@ -132,6 +133,7 @@ struct device_private {\n #ifdef CONFIG_RUST\n \tstruct driver_type driver_type;\n #endif\n+\tstruct completion complete;\n \tu8 dead:1;\n };\n #define to_device_private_parent(obj)\t\\\ndiff --git a/drivers/base/core.c b/drivers/base/core.c\nindex a32fc7141957..2319c643b11f 100644\n--- a/drivers/base/core.c\n+++ b/drivers/base/core.c\n@@ -9,6 +9,7 @@\n */\n \n #include <linux/acpi.h>\n+#include <linux/async.h>\n #include <linux/blkdev.h>\n #include <linux/cleanup.h>\n #include <linux/cpufreq.h>\n@@ -37,6 +38,10 @@\n #include \"physical_location.h\"\n #include \"power/power.h\"\n \n+static bool async_shutdown = true;\n+module_param(async_shutdown, bool, 0644);\n+MODULE_PARM_DESC(async_shutdown, \"Enable asynchronous device shutdown support\");\n+\n /* Device links support. */\n static LIST_HEAD(deferred_sync);\n static unsigned int defer_sync_state_count = 1;\n@@ -3539,6 +3544,7 @@ static int device_private_init(struct device *dev)\n \tklist_init(&dev->p->klist_children, klist_children_get,\n \t\t klist_children_put);\n \tINIT_LIST_HEAD(&dev->p->deferred_probe);\n+\tinit_completion(&dev->p->complete);\n \treturn 0;\n }\n \n@@ -4783,6 +4789,37 @@ int device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid)\n \treturn error;\n }\n \n+static bool wants_async_shutdown(struct device *dev)\n+{\n+\treturn async_shutdown && dev->async_shutdown;\n+}\n+\n+static int wait_for_device_shutdown(struct device *dev, void *data)\n+{\n+\tbool async = *(bool *)data;\n+\n+\tif (async || wants_async_shutdown(dev))\n+\t\twait_for_completion(&dev->p->complete);\n+\n+\treturn 0;\n+}\n+\n+static void wait_for_shutdown_dependencies(struct device *dev, bool async)\n+{\n+\tstruct device_link *link;\n+\tint idx;\n+\n+\tdevice_for_each_child(dev, &async, wait_for_device_shutdown);\n+\n+\tidx = device_links_read_lock();\n+\n+\tdev_for_each_link_to_consumer(link, dev)\n+\t\tif (!device_link_flag_is_sync_state_only(link->flags))\n+\t\t\twait_for_device_shutdown(link->consumer, &async);\n+\n+\tdevice_links_read_unlock(idx);\n+}\n+\n static void __shutdown_one_device(struct device *dev)\n {\n \tdevice_lock(dev);\n@@ -4806,6 +4843,8 @@ static void __shutdown_one_device(struct device *dev)\n \t\tdev->driver->shutdown(dev);\n \t}\n \n+\tcomplete_all(&dev->p->complete);\n+\n \tdevice_unlock(dev);\n }\n \n@@ -4827,6 +4866,55 @@ static void shutdown_one_device(struct device *dev)\n \tput_device(dev);\n }\n \n+static void async_shutdown_handler(void *data, async_cookie_t cookie)\n+{\n+\tstruct device *dev = data;\n+\n+\twait_for_shutdown_dependencies(dev, true);\n+\tshutdown_one_device(dev);\n+}\n+\n+static bool shutdown_device_async(struct device *dev)\n+{\n+\tif (async_schedule_dev_nocall(async_shutdown_handler, dev))\n+\t\treturn true;\n+\treturn false;\n+}\n+\n+\n+static void early_async_shutdown_devices(void)\n+{\n+\tstruct device *dev, *next, *needs_put = NULL;\n+\n+\tif (!async_shutdown)\n+\t\treturn;\n+\n+\tspin_lock(&devices_kset->list_lock);\n+\n+\tlist_for_each_entry_safe_reverse(dev, next, &devices_kset->list,\n+\t\t\t\t\t kobj.entry) {\n+\t\tif (wants_async_shutdown(dev)) {\n+\t\t\tget_device(dev);\n+\n+\t\t\tif (shutdown_device_async(dev)) {\n+\t\t\t\tlist_del_init(&dev->kobj.entry);\n+\t\t\t} else {\n+\t\t\t\t/*\n+\t\t\t\t * async failed, clean up extra references\n+\t\t\t\t * and run from the standard shutdown loop\n+\t\t\t\t */\n+\t\t\t\tneeds_put = dev;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tspin_unlock(&devices_kset->list_lock);\n+\n+\tif (needs_put)\n+\t\tput_device(needs_put);\n+}\n+\n /**\n * device_shutdown - call ->shutdown() on each device to shutdown.\n */\n@@ -4839,6 +4927,12 @@ void device_shutdown(void)\n \n \tcpufreq_suspend();\n \n+\t/*\n+\t * Start async device threads where possible to maximize potential\n+\t * parallelism and minimize false dependency on unrelated sync devices\n+\t */\n+\tearly_async_shutdown_devices();\n+\n \tspin_lock(&devices_kset->list_lock);\n \t/*\n \t * Walk the devices list backward, shutting down each in turn.\n@@ -4857,11 +4951,16 @@ void device_shutdown(void)\n \t\tlist_del_init(&dev->kobj.entry);\n \t\tspin_unlock(&devices_kset->list_lock);\n \n-\t\tshutdown_one_device(dev);\n+\t\tif (!wants_async_shutdown(dev) || !shutdown_device_async(dev)) {\n+\t\t\twait_for_shutdown_dependencies(dev, false);\n+\t\t\tshutdown_one_device(dev);\n+\t\t}\n \n \t\tspin_lock(&devices_kset->list_lock);\n \t}\n \tspin_unlock(&devices_kset->list_lock);\n+\n+\tasync_synchronize_full();\n }\n \n /*\ndiff --git a/include/linux/device.h b/include/linux/device.h\nindex e65d564f01cd..cdc890e5d6ae 100644\n--- a/include/linux/device.h\n+++ b/include/linux/device.h\n@@ -553,6 +553,8 @@ struct device_physical_location {\n * @dma_skip_sync: DMA sync operations can be skipped for coherent buffers.\n * @dma_iommu: Device is using default IOMMU implementation for DMA and\n *\t\tdoesn't rely on dma_ops structure.\n+ * @async_shutdown: Device shutdown may be run asynchronously and in parallel\n+ *\t\tto the shutdown of unrelated devices\n *\n * At the lowest level, every device in a Linux system is represented by an\n * instance of struct device. The device structure contains the information\n@@ -675,6 +677,7 @@ struct device {\n #ifdef CONFIG_IOMMU_DMA\n \tbool\t\t\tdma_iommu:1;\n #endif\n+\tbool\t\t\tasync_shutdown:1;\n };\n \n /**\n@@ -878,6 +881,16 @@ static inline bool device_async_suspend_enabled(struct device *dev)\n \treturn !!dev->power.async_suspend;\n }\n \n+static inline void device_enable_async_shutdown(struct device *dev)\n+{\n+\tdev->async_shutdown = true;\n+}\n+\n+static inline bool device_async_shutdown_enabled(struct device *dev)\n+{\n+\treturn !!dev->async_shutdown;\n+}\n+\n static inline bool device_pm_not_required(struct device *dev)\n {\n \treturn dev->power.no_pm;\n", "prefixes": [ "3/5" ] }