From patchwork Wed Feb 7 18:40:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Jeffery X-Patchwork-Id: 198033 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:168b:b0:106:860b:bbdd with SMTP id ma11csp2432395dyb; Wed, 7 Feb 2024 10:43:17 -0800 (PST) X-Google-Smtp-Source: AGHT+IEbBLS9uT1HJ9awFZjNup3cR42axEjYOHHOXkCLqhyQJio3sIEgOGmWCLyciJS8UuQkZ+tm X-Received: by 2002:a05:6214:19e2:b0:68c:746f:734b with SMTP id q2-20020a05621419e200b0068c746f734bmr8596117qvc.26.1707331397428; Wed, 07 Feb 2024 10:43:17 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707331397; cv=pass; d=google.com; s=arc-20160816; b=Fj2HUKrXSHzJzo2OLloruHtXDXxjRcFFU49+oNovR5Y0GXJ023yebgV3hSel6A2gN5 9onjXB2Q5JhiuUKAz9/irpfXTx/de6IaIVfJkSBDmnilMGfl0YvvkJD1IFViect3Er++ KDZxYVxNNsNkRBTASi/ijrJBnZzvLAdVIqrzyKA9XjV8H+Y+aL7NFxr0ANcw/qAtmd8M Aow2fpX5LuRoDcEYe/B5sPKCCQCd4vS48I5IvgYh7I817SscLpDJReu2vSmRnO0zIkiP QD8LXnqulS/sXvaKJ19+p2tlxptUuUrcrq9WMb6pyM7heGTvLz37yUNAn9R0Nl1Xf/m7 Z/Aw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=wxUXCNijSG3JpoO3vioYJ7kD0cZUoEnLjl7wb2EW6H8=; fh=j9edcREVypRtHtP85bzKZijyPx0uJqrCMBwSoxFXsBU=; b=AybXdWfthvD6FE2MU+Pqk5QPaJ00/gAuEBZhjTkxR/mzo02EqhU2PGG9a130R/MXwV v6qkoyPg8SRK8i41nLoyTo/ghEMp7mGXej/obWOlmn3y1kUPQ5YaflDuYpWtNuoDEvE2 dEdNOgFzMpHKIROTXLEcpSWP6fDftUCQ91L6GzlfJO/+c8iN4QU+oa4QhrrzpJDgTvSM lathueaHxlUce4Xes6FE5u8N7E32VL1+QgMQYePsDUAUNydD++BhiqlK0qhCl9UL2wxE f1tKOiy8FRQLJJ8Tll7KivcHCunjZyoe7sh9OgHsyNNfrapNrc0A70zpl1RQiceFy2oT CJLw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=iETjnd9T; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56917-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56917-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com X-Forwarded-Encrypted: i=2; AJvYcCUwthfENDkGJuG0jhPvjwSaXQhhMztU6CzKeWE4l1Cytjr7NLHI65MoO9wwWaq0bltbBxh/ch5+1HfggYin6mp7jm6L0w== Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id r7-20020a056214212700b0068cbfcc13cfsi1391415qvc.498.2024.02.07.10.43.17 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Feb 2024 10:43:17 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-56917-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=iETjnd9T; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56917-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56917-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 2D3361C21776 for ; Wed, 7 Feb 2024 18:43:17 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A37AB85C4A; Wed, 7 Feb 2024 18:42:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="iETjnd9T" Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 28D1484FC7 for ; Wed, 7 Feb 2024 18:42:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331345; cv=none; b=jqNaH6GUl+C5uOt99VO0nh5ItSIekY+7TpD1g5jOx7Y+mkOD6moDg05pDycdIk+anvi/U5a0+oYe8I1nJnMhQi6y0omhm2YuLA76BUzz1iD4ZN0ho+Pw/P6HyqEVPsEvpK8S/hxQVoHN9bvfUiFp6vV7ri1KBnIgKhLgLylMa04= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331345; c=relaxed/simple; bh=ZCRVA2mffIeaQus1dOlcK54spGmEXo1fw7BGH0JkEM4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZrSTbkX+9HQ2YEVwCYSwbT8R/qEyTZWa8QLFTdNvkOX0KnR8gWEcJ/PP2NTqaLiv/NmsEYSAmi00W9h3eORErxtR/EWgVUkedc33WAxdGD0DCiCTcVDhh9rJzcblXlx7zb/biJ7wKJXTgIL9XkdVUuA2oAuwWqQOEomJgWxbmH0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=iETjnd9T; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1707331343; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wxUXCNijSG3JpoO3vioYJ7kD0cZUoEnLjl7wb2EW6H8=; b=iETjnd9TLpN8WIYM74+NocBWhY59Ra7SXCVdn0B5OwvbQPpgZLpUJTqAbqsP12rT0cHVmp AmYB8jtRVYTQTYk2IK8K/lHG2j9H7Lrix4oy+cO4bIOtNTboGhZC4Gd8Sr1Y6Z8oM8UWvz aGcDdjoNo/X2jFKZL3v4iFfzFbYMWAY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-376-l26M5vl5PByd4fVcW48V4g-1; Wed, 07 Feb 2024 13:42:20 -0500 X-MC-Unique: l26M5vl5PByd4fVcW48V4g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2579483B86B; Wed, 7 Feb 2024 18:42:19 +0000 (UTC) Received: from fedora-work.redhat.com (unknown [10.22.32.236]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9C76C4011FF1; Wed, 7 Feb 2024 18:42:18 +0000 (UTC) From: David Jeffery To: linux-kernel@vger.kernel.org Cc: linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, Greg Kroah-Hartman , "Rafael J . Wysocki" , David Jeffery , Laurence Oberman Subject: [RFC PATCH 1/6] minimal async shutdown infrastructure Date: Wed, 7 Feb 2024 13:40:55 -0500 Message-ID: <20240207184100.18066-2-djeffery@redhat.com> In-Reply-To: <20240207184100.18066-1-djeffery@redhat.com> References: <20240207184100.18066-1-djeffery@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790266727566306922 X-GMAIL-MSGID: 1790266727566306922 Adds the async_shutdown_start and async_shutdown_end calls to perform async shutdown. Implements a very minimalist method of async shutdown support within device_shutdown(). The device at the head of the shutdown list is checked against a list of devices under async shutdown. If the head is a parent of a device on the async list, all active async shutdown operations are completed before the parent's shutdown call is performed. The number of async operations also has a max limit to prevent the list being checked for a child from getting overly large. Signed-off-by: David Jeffery Tested-by: Laurence Oberman --- drivers/base/core.c | 116 +++++++++++++++++++++++++++++++++- include/linux/device/bus.h | 8 ++- include/linux/device/driver.h | 7 ++ 3 files changed, 127 insertions(+), 4 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 14d46af40f9a..5bc2282c00cd 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -4719,12 +4719,92 @@ int device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid) } EXPORT_SYMBOL_GPL(device_change_owner); + +#define MAX_ASYNC_SHUTDOWNS 32 +static int async_shutdown_count; +static LIST_HEAD(async_shutdown_list); + +/** + * If a device has a child busy with an async shutdown or there are too many + * async shutdowns active, the device may not be shut down at this time. + */ +static bool may_shutdown_device(struct device *dev) +{ + struct device *tmp; + + if (async_shutdown_count >= MAX_ASYNC_SHUTDOWNS) + return false; + + list_for_each_entry(tmp, &async_shutdown_list, kobj.entry) { + if (tmp->parent == dev) + return false; + } + return true; +} + +/** + * Call and track each async shutdown call + */ +static void async_shutdown_start(struct device *dev, void (*callback) (struct device *)) +{ + if (initcall_debug) + dev_info(dev, "async_shutdown_start\n"); + + (*callback)(dev); + list_add_tail(&dev->kobj.entry, &async_shutdown_list); + async_shutdown_count++; +} + +/** + * Wait for all async shutdown operations currently active to complete + */ +static void wait_for_active_async_shutdown(void) +{ + struct device *dev, *parent; + + while (!list_empty(&async_shutdown_list)) { + dev = list_entry(async_shutdown_list.next, struct device, + kobj.entry); + + parent = dev->parent; + + /* + * Make sure the device is off the list + */ + list_del_init(&dev->kobj.entry); + if (parent) + device_lock(parent); + device_lock(dev); + if (dev->bus && dev->bus->async_shutdown_end) { + if (initcall_debug) + dev_info(dev, + "async_shutdown_end called\n"); + dev->bus->async_shutdown_end(dev); + } else if (dev->driver && dev->driver->async_shutdown_end) { + if (initcall_debug) + dev_info(dev, + "async_shutdown_end called\n"); + dev->driver->async_shutdown_end(dev); + } + device_unlock(dev); + if (parent) + device_unlock(parent); + + put_device(dev); + put_device(parent); + } + if (initcall_debug) + printk(KERN_INFO "device shutdown: waited for %d async shutdown callbacks\n", async_shutdown_count); + async_shutdown_count = 0; +} + /** * device_shutdown - call ->shutdown() on each device to shutdown. */ void device_shutdown(void) { struct device *dev, *parent; + bool async_busy; wait_for_device_probe(); device_block_probing(); @@ -4741,6 +4821,8 @@ void device_shutdown(void) dev = list_entry(devices_kset->list.prev, struct device, kobj.entry); + async_busy = false; + /* * hold reference count of device's parent to * prevent it from being freed because parent's @@ -4748,6 +4830,17 @@ void device_shutdown(void) */ parent = get_device(dev->parent); get_device(dev); + + if (!may_shutdown_device(dev)) { + put_device(dev); + put_device(parent); + + spin_unlock(&devices_kset->list_lock); + wait_for_active_async_shutdown(); + spin_lock(&devices_kset->list_lock); + continue; + } + /* * Make sure the device is off the kset list, in the * event that dev->*->shutdown() doesn't remove it. @@ -4769,26 +4862,43 @@ void device_shutdown(void) dev_info(dev, "shutdown_pre\n"); dev->class->shutdown_pre(dev); } - if (dev->bus && dev->bus->shutdown) { + if (dev->bus && dev->bus->async_shutdown_start) { + async_shutdown_start(dev, dev->bus->async_shutdown_start); + async_busy = true; + } else if (dev->bus && dev->bus->shutdown) { if (initcall_debug) dev_info(dev, "shutdown\n"); dev->bus->shutdown(dev); + } else if (dev->driver && dev->driver->async_shutdown_start) { + async_shutdown_start(dev, dev->driver->async_shutdown_start); + async_busy = true; } else if (dev->driver && dev->driver->shutdown) { if (initcall_debug) dev_info(dev, "shutdown\n"); dev->driver->shutdown(dev); + } else { + if (initcall_debug) + dev_info(dev, "no shutdown callback\n"); } device_unlock(dev); if (parent) device_unlock(parent); - put_device(dev); - put_device(parent); + /* if device has an async shutdown, drop the ref when done */ + if (!async_busy) { + put_device(dev); + put_device(parent); + } spin_lock(&devices_kset->list_lock); } spin_unlock(&devices_kset->list_lock); + /* + * Wait for any async shutdown still running. + */ + if (!list_empty(&async_shutdown_list)) + wait_for_active_async_shutdown(); } /* diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index 5ef4ec1c36c3..7a4a2ff0bc23 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -48,7 +48,11 @@ struct fwnode_handle; * will never get called until they do. * @remove: Called when a device removed from this bus. * @shutdown: Called at shut-down time to quiesce the device. - * + * @async_shutdown_start: Optional call to support and begin the shutdown + * process on the device in an asynchronous manner. + * @async_shutdown_end: Optional call to complete an asynchronous + * shutdown of the device. Must be provided if a + * sync_shutdown_start call is provided. * @online: Called to put the device back online (after offlining it). * @offline: Called to put the device offline for hot-removal. May fail. * @@ -87,6 +91,8 @@ struct bus_type { void (*sync_state)(struct device *dev); void (*remove)(struct device *dev); void (*shutdown)(struct device *dev); + void (*async_shutdown_start)(struct device *dev); + void (*async_shutdown_end)(struct device *dev); int (*online)(struct device *dev); int (*offline)(struct device *dev); diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index 7738f458995f..af0ad2d3687a 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -71,6 +71,11 @@ enum probe_type { * @remove: Called when the device is removed from the system to * unbind a device from this driver. * @shutdown: Called at shut-down time to quiesce the device. + * @async_shutdown_start: Optional call to support and begin the shutdown + * process on the device in an asynchronous manner. + * @async_shutdown_end: Optional call to complete an asynchronous + * shutdown of the device. Must be provided if a + * sync_shutdown_start call is provided. * @suspend: Called to put the device to sleep mode. Usually to a * low power state. * @resume: Called to bring a device from sleep mode. @@ -110,6 +115,8 @@ struct device_driver { void (*sync_state)(struct device *dev); int (*remove) (struct device *dev); void (*shutdown) (struct device *dev); + void (*async_shutdown_start) (struct device *dev); + void (*async_shutdown_end) (struct device *dev); int (*suspend) (struct device *dev, pm_message_t state); int (*resume) (struct device *dev); const struct attribute_group **groups; From patchwork Wed Feb 7 18:40:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Jeffery X-Patchwork-Id: 198035 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:168b:b0:106:860b:bbdd with SMTP id ma11csp2432564dyb; Wed, 7 Feb 2024 10:43:41 -0800 (PST) X-Google-Smtp-Source: AGHT+IEDxXZ+mbxBlb3hYm9/gKh7iO1JcJz4QzL5fPvkFpg1sq4FQJQ9vlOB7vDbBGZjfsD7i+QT X-Received: by 2002:a17:906:b782:b0:a37:2566:e248 with SMTP id dt2-20020a170906b78200b00a372566e248mr5407406ejb.37.1707331421677; Wed, 07 Feb 2024 10:43:41 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707331421; cv=pass; d=google.com; s=arc-20160816; b=cLxsoh9zad/3vrXvNegb2/RtACt74+1svDQK/6mzDV0W4I1oLS5+D3WeMF5iYwO2U5 JGnN7Yoiyi67kXABRSzSEK1QYeD3Nt8RxCp5djA5EJcJ5W1XHkjSaQZtS9vXSOWGSnQc +sjZai8jBGikCsQ1C8u+oho3YER+CJJth3is/7bVSmaKnROIR4xj/e15y1F4YdgbVeEL u7BEFRMPT4drDl/ZJR1wZp08B6EMxEFRdBIP11P5HMLDKqyV8SEtug1kIRramZ7diMkc 0CBqRXrKES4Kf6oATPX+AKGQ7G/vAtSA/KJQio2DbbnSW4pBgGMNTS3Rp9ho7kLiHZf1 6/Cw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=oTFy4nGaIuyAjRSeWWj3icZv9u9DGODaCpUqVFylGh8=; fh=CUGqtF502lv9gGK18FSe7X1w/AdCFD+QTfTBM4uuoEA=; b=CkeppR42yjuLt8SxBTTPklot8TZZczIeXJmXOWl1MGxa/xXxK5yXkfVu5bj4hN9M+8 s3qyE6Eeh9p3VNhiS3SoLxm0f5nWCbwgCIki0NfJBPGL8XraRpEC8ELokpKEpm3WAr2n O6eAx1d1gxhbZRLsHOS2Ud5fDthco8IUD8o+s6u2AZvaBkC3ZcyNGpFBR67AdlEKtbrb hQ6fVgc2G6nqcVwm3Ctyv2eo4z6nQ6WSWyJQvP/Ok8XTowIInyIf5F6WFUPDophnxrOp fn3/waw62kjQCmz4qxsantIcd9Bmar8zuIciTkf8MgLbGkYFr2UB1oyGQkYbrKWcri7U YqpA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=FNO4T+9B; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56919-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56919-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com X-Forwarded-Encrypted: i=2; AJvYcCWW7LggnrxoJH6XlnOc6NxkIcLXtuC+veFr8CkM+WS5zCoX3yFCtiTR0Sl0zHL3FDkVwiiGAIo8NZYlqC0n+YnRc2rBcQ== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id g19-20020a170906395300b00a384e265dcdsi1229221eje.54.2024.02.07.10.43.41 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Feb 2024 10:43:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-56919-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) client-ip=2604:1380:4601:e00::3; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=FNO4T+9B; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56919-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56919-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 227111F22C21 for ; Wed, 7 Feb 2024 18:43:41 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D541486147; Wed, 7 Feb 2024 18:42:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="FNO4T+9B" Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 D58B882889 for ; Wed, 7 Feb 2024 18:42:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331348; cv=none; b=cZQv2ypLAAq64lVg9+z12cWkZ2xai0q2HYBOR4dXToR9LAjGF6g3eA7zcYiD9eZ6JkIu+zXYr73FibT6oCufH9rbe3iYAl7l80kd9/oaZDKczGMLc8T1LGd9TICjvwihwaINsqe5fxMzM5pi9g2QFBaWIPIouC8OGWrBB0zNDqc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331348; c=relaxed/simple; bh=IAD5k7mJ5GTdKJh3kH8fpJh/ezNJOFY0mEoN0yEKfYk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZLfwIDx9L3oE1UcbYlQINGx7nl/NfpmgxtDSh0NEs+/2LWOylAbVcaJNG939P1K1wyDN3RRZCDfxS7Euv8k7XK5ePA3PdxiSQi3Gpfzc9n/l2fA+7jDl5eSZA1hzYzn+ikVLSHdUhK1AJRWmMHPG+SKu5bnxpmENS7hpiXf2BLw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=FNO4T+9B; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1707331344; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oTFy4nGaIuyAjRSeWWj3icZv9u9DGODaCpUqVFylGh8=; b=FNO4T+9BLt37qyocVqxh7WZpBdhVDEAFm0IXUC8sZJSGsN49OJrj18LRdnCRZWaFnRnLce 13oni/405hzaelV6/W+S6ZqBGVkVGHzQfIlGZrK7TpyKLPD5/Nwg0eaSh4rzoY87nX6xn3 hcavhR8CNChjq56FTvPbqM7kdhjlb5A= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-590-K0PNYfJIP2qWNiPNid8kCQ-1; Wed, 07 Feb 2024 13:42:21 -0500 X-MC-Unique: K0PNYfJIP2qWNiPNid8kCQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id D2C5338212C5; Wed, 7 Feb 2024 18:42:20 +0000 (UTC) Received: from fedora-work.redhat.com (unknown [10.22.32.236]) by smtp.corp.redhat.com (Postfix) with ESMTP id 66FB2400D6D2; Wed, 7 Feb 2024 18:42:20 +0000 (UTC) From: David Jeffery To: linux-kernel@vger.kernel.org Cc: linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, Greg Kroah-Hartman , "Rafael J . Wysocki" , David Jeffery , Laurence Oberman Subject: [RFC PATCH 2/6] Improve ability to perform async shutdown in parallel Date: Wed, 7 Feb 2024 13:40:56 -0500 Message-ID: <20240207184100.18066-3-djeffery@redhat.com> In-Reply-To: <20240207184100.18066-1-djeffery@redhat.com> References: <20240207184100.18066-1-djeffery@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790266752333615734 X-GMAIL-MSGID: 1790266752333615734 Expands the async shutdown implementation to allow more cases of parallel async shutdown. A field is added so that a device under async shutdown can mark its parent as busy due to the async shutdown. A busy parent on reaching the head of the shutdown list gets stored and flags its own parent as busy. Once the async shutdown operations are completed, the stored parents are returned to the shutdown list and shut down in an order maintaining their parent-child ordering. Unlike the minimal implementation, this allows more end nodes of the device tree to be under async shutdown in parallel. A cap on the number of async shutdown devices is still enforced, though not required and could be removed if desired. Signed-off-by: David Jeffery Tested-by: Laurence Oberman --- drivers/base/base.h | 1 + drivers/base/core.c | 71 ++++++++++++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index eb4c0ace9242..954008bd39e5 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -116,6 +116,7 @@ struct device_private { char *deferred_probe_reason; struct device *device; u8 dead:1; + u8 child_shutdown:1; }; #define to_device_private_parent(obj) \ container_of(obj, struct device_private, knode_parent) diff --git a/drivers/base/core.c b/drivers/base/core.c index 5bc2282c00cd..e88d418bf0fd 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -4720,9 +4720,10 @@ int device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid) EXPORT_SYMBOL_GPL(device_change_owner); -#define MAX_ASYNC_SHUTDOWNS 32 +#define MAX_ASYNC_SHUTDOWNS 256 static int async_shutdown_count; static LIST_HEAD(async_shutdown_list); +static LIST_HEAD(async_delayed_list); /** * If a device has a child busy with an async shutdown or there are too many @@ -4730,15 +4731,15 @@ static LIST_HEAD(async_shutdown_list); */ static bool may_shutdown_device(struct device *dev) { - struct device *tmp; - - if (async_shutdown_count >= MAX_ASYNC_SHUTDOWNS) + if (dev->p->child_shutdown) { + if (list_empty(&async_shutdown_list)) { + dev_err(dev, "child_shutdown set but no children? Clearing\n"); + dev->p->child_shutdown = 0; + return true; + } return false; - - list_for_each_entry(tmp, &async_shutdown_list, kobj.entry) { - if (tmp->parent == dev) - return false; } + return true; } @@ -4753,6 +4754,9 @@ static void async_shutdown_start(struct device *dev, void (*callback) (struct de (*callback)(dev); list_add_tail(&dev->kobj.entry, &async_shutdown_list); async_shutdown_count++; + + if (dev->parent) + dev->parent->p->child_shutdown = 1; } /** @@ -4760,7 +4764,7 @@ static void async_shutdown_start(struct device *dev, void (*callback) (struct de */ static void wait_for_active_async_shutdown(void) { - struct device *dev, *parent; + struct device *dev, *parent, *tmp; while (!list_empty(&async_shutdown_list)) { dev = list_entry(async_shutdown_list.next, struct device, @@ -4787,15 +4791,29 @@ static void wait_for_active_async_shutdown(void) dev->driver->async_shutdown_end(dev); } device_unlock(dev); - if (parent) - device_unlock(parent); - + if (parent) { + tmp = parent; + do { + tmp->p->child_shutdown = 0; + device_unlock(tmp); + + tmp = tmp->parent; + if (!tmp || !tmp->p->child_shutdown) + break; + device_lock(tmp); + } while (1); + } put_device(dev); put_device(parent); } if (initcall_debug) printk(KERN_INFO "device shutdown: waited for %d async shutdown callbacks\n", async_shutdown_count); + async_shutdown_count = 0; + spin_lock(&devices_kset->list_lock); + list_splice_tail_init(&async_delayed_list, &devices_kset->list); + spin_unlock(&devices_kset->list_lock); + } /** @@ -4810,7 +4828,7 @@ void device_shutdown(void) device_block_probing(); cpufreq_suspend(); - +restart: spin_lock(&devices_kset->list_lock); /* * Walk the devices list backward, shutting down each in turn. @@ -4832,12 +4850,15 @@ void device_shutdown(void) get_device(dev); if (!may_shutdown_device(dev)) { + list_move(&dev->kobj.entry, &async_delayed_list); + if (parent) { + device_lock(parent); + parent->p->child_shutdown = 1; + device_unlock(parent); + } + put_device(dev); put_device(parent); - - spin_unlock(&devices_kset->list_lock); - wait_for_active_async_shutdown(); - spin_lock(&devices_kset->list_lock); continue; } @@ -4863,14 +4884,16 @@ void device_shutdown(void) dev->class->shutdown_pre(dev); } if (dev->bus && dev->bus->async_shutdown_start) { - async_shutdown_start(dev, dev->bus->async_shutdown_start); + async_shutdown_start(dev, + dev->bus->async_shutdown_start); async_busy = true; } else if (dev->bus && dev->bus->shutdown) { if (initcall_debug) dev_info(dev, "shutdown\n"); dev->bus->shutdown(dev); } else if (dev->driver && dev->driver->async_shutdown_start) { - async_shutdown_start(dev, dev->driver->async_shutdown_start); + async_shutdown_start(dev, + dev->driver->async_shutdown_start); async_busy = true; } else if (dev->driver && dev->driver->shutdown) { if (initcall_debug) @@ -4891,14 +4914,22 @@ void device_shutdown(void) put_device(parent); } + if (async_shutdown_count == MAX_ASYNC_SHUTDOWNS) + wait_for_active_async_shutdown(); + spin_lock(&devices_kset->list_lock); } spin_unlock(&devices_kset->list_lock); /* - * Wait for any async shutdown still running. + * Wait for any async shutdown still running, then restart the loop + * if the list is no longer empty from delayed entries returning to + * the list. */ if (!list_empty(&async_shutdown_list)) wait_for_active_async_shutdown(); + + if(!list_empty(&devices_kset->list)) + goto restart; } /* From patchwork Wed Feb 7 18:40:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Jeffery X-Patchwork-Id: 198034 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:168b:b0:106:860b:bbdd with SMTP id ma11csp2432413dyb; Wed, 7 Feb 2024 10:43:19 -0800 (PST) X-Google-Smtp-Source: AGHT+IG/rbKl3u+oDw3G5LJTHBBaBkLOnDzlknpvviPwYf76zi8Xg+exeFE1i5YzeO6uESxRL3GG X-Received: by 2002:a17:90b:480b:b0:295:a8b8:97b3 with SMTP id kn11-20020a17090b480b00b00295a8b897b3mr3407620pjb.40.1707331399330; Wed, 07 Feb 2024 10:43:19 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707331399; cv=pass; d=google.com; s=arc-20160816; b=Q7JTOaeFoO1zGiNtVgAuChuVEpbPdNjomCtU0LgcW/XObmUj60w8ql6Vj/riOWuX+k KIi7lEvE0+FVwuH8Qk38eZ17Exa/w0PFz8PrpJtPwrC+flQ7QOyWgDRIgLz6mGH6viHl pYTj1LQ1rNjKPJQNjNdyXhpiUYJho95MZ0h2MWpXQhoNcamWkl3NAqLiM0FBUJwHBSQc qudapRocvS5xS5VDSlyyUb+IayahL46YY9KeORzhy+D96wJcH3O2YCM6jDpSE47MQ7Vc C4BqRCjcVHQ4ueUGJ3wUZN6cgWTHfWZ3T6sXeEigJqMHsbiplNW1289034Egm5EbtN4/ JthA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=F7841DLyqRx4+GFENMTDanBPrbVQXHzKvu3LLMhu66w=; fh=HFkasXwwPa7nTq8dr66zNXYtSwDlLu/MP3JrwwrEqg4=; b=eQ0mEoLS4zJexhRVW0/ATdz7ZOLedj2rhe8Fq69YnoANN98hVRAEmq07LlrMqwtU2+ gDyDKuvMPX8NTCWoOlNif+XfP5upNoGHZW803K53I6PVf/Op3RqmEVSp4qHWeerg//iS THUvcb3Hc5sAScmHZAfGAHZ4w1owj+BJLWzuiLIzfLh3rbseL1EyVQdH4zcLQmssIVoq oY2b1YODCyLaboAHvEYE4GvB8TAttPDgUQiwhVXzQaFYrLrnF3DKwf4Sf6MyFs2MYnKU wIJ7DG7ZAv7llSiezhE26AY18skqe20FJ9EN4JMT8l1NWqdipb14XOk5a6O5uxAIXLGe bCQA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=NT4AAfqD; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56918-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56918-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com X-Forwarded-Encrypted: i=2; AJvYcCV7XC8jC+ZeMccLZ0KMeOOBBLAyaZLpWmibA4DqvgdA5zxsUzsGiOQyZApsxFgXx4ZNTbZY+jXKGhE/zfFGFrAjH/Pagg== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id w15-20020a17090a5e0f00b00294c68dfcb1si2172921pjf.121.2024.02.07.10.43.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Feb 2024 10:43:19 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-56918-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=NT4AAfqD; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56918-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56918-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 1E9F4289666 for ; Wed, 7 Feb 2024 18:43:19 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E329285C4F; Wed, 7 Feb 2024 18:42:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="NT4AAfqD" Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 6B5C783CBE for ; Wed, 7 Feb 2024 18:42:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331347; cv=none; b=YJYHkM/ciriMXtXcQnhvguaWNk0ZuTfhiNi3kI2Q5U7z+7Y9v/4E7L3HQGx2c70iZ8Prm2JGe6OAhQvXvEiPFMUeLSJGmuKEvsBnYC6fYNi9u/S/j5fwrdjKO+tGodWdLEhWI6jin1RhhRI2mtSHXmyNB/PPRctxlXG/rCSa14I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331347; c=relaxed/simple; bh=Dwy/u3XKKFj/qy3AWoxAcE6kPy3lkPw+HkoBS6KoqLw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s9cCqkXjXROw+P8HKECQWVryWEc//SBDnbjtSMbffm0aC0D/nhW9Dk779KP2mbl3wphK+RRGURotH1+SqNUPMkXD4JDHcKOHAVg4ndQZSlNPhZ/g3DIjYL9P7KlNQwR4LJUEnJZcYoR8H9zKKqC6FqG/teP/hd6EVthDlT4st9c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=NT4AAfqD; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1707331344; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=F7841DLyqRx4+GFENMTDanBPrbVQXHzKvu3LLMhu66w=; b=NT4AAfqDI6FVn8ldfJL1w74g5NhlQHEWElchsxd1s9HmS15rmD//ainlZ/Gzs/ooIfA3jZ wpxTZXvrD4mbzZd6jRSzsTpq8MMWIfLk5BkizdcXdPU/ailyjRYYcDhzvlT4cd9XPzxyBC ujJqIIz90g0EwDp1y3KQgerECGlJRmE= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-223-g0k1TawDMgiM8jXxLRJciw-1; Wed, 07 Feb 2024 13:42:22 -0500 X-MC-Unique: g0k1TawDMgiM8jXxLRJciw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 602F2185A780; Wed, 7 Feb 2024 18:42:22 +0000 (UTC) Received: from fedora-work.redhat.com (unknown [10.22.32.236]) by smtp.corp.redhat.com (Postfix) with ESMTP id E6DB24011FF1; Wed, 7 Feb 2024 18:42:21 +0000 (UTC) From: David Jeffery To: linux-kernel@vger.kernel.org Cc: linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, Greg Kroah-Hartman , "Rafael J . Wysocki" , David Jeffery , Laurence Oberman Subject: [RFC PATCH 3/6] pci bus async shutdown support Date: Wed, 7 Feb 2024 13:40:57 -0500 Message-ID: <20240207184100.18066-4-djeffery@redhat.com> In-Reply-To: <20240207184100.18066-1-djeffery@redhat.com> References: <20240207184100.18066-1-djeffery@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790266729646607051 X-GMAIL-MSGID: 1790266729646607051 Add async shutdown shutdown fields and Convert pci's shutdown logic into async shutdown calls so that individual pci device drivers can implement async shutdown. Signed-off-by: David Jeffery Tested-by: Laurence Oberman --- drivers/pci/pci-driver.c | 24 ++++++++++++++++++++++-- include/linux/pci.h | 4 ++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 51ec9e7e784f..0ad418905115 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -502,16 +502,28 @@ static void pci_device_remove(struct device *dev) pci_dev_put(pci_dev); } -static void pci_device_shutdown(struct device *dev) +static void pci_device_async_shutdown_start(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_driver *drv = pci_dev->driver; pm_runtime_resume(dev); - if (drv && drv->shutdown) + if (drv && drv->async_shutdown_start) + drv->async_shutdown_start(pci_dev); + else if (drv && drv->shutdown) drv->shutdown(pci_dev); +} + +static void pci_device_async_shutdown_end(struct device *dev) +{ + struct pci_dev *pci_dev = to_pci_dev(dev); + struct pci_driver *drv = pci_dev->driver; + + if (drv && drv->async_shutdown_end) + drv->async_shutdown_end(pci_dev); + /* * If this is a kexec reboot, turn off Bus Master bit on the * device to tell it to not continue to do DMA. Don't touch @@ -523,6 +535,12 @@ static void pci_device_shutdown(struct device *dev) pci_clear_master(pci_dev); } +static void pci_device_shutdown(struct device *dev) +{ + pci_device_async_shutdown_start(dev); + pci_device_async_shutdown_end(dev); +} + #ifdef CONFIG_PM_SLEEP /* Auxiliary functions used for system resume */ @@ -1682,6 +1700,8 @@ struct bus_type pci_bus_type = { .probe = pci_device_probe, .remove = pci_device_remove, .shutdown = pci_device_shutdown, + .async_shutdown_start = pci_device_async_shutdown_start, + .async_shutdown_end = pci_device_async_shutdown_end, .dev_groups = pci_dev_groups, .bus_groups = pci_bus_groups, .drv_groups = pci_drv_groups, diff --git a/include/linux/pci.h b/include/linux/pci.h index add9368e6314..6f61325c956a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -917,6 +917,8 @@ struct module; * Useful for enabling wake-on-lan (NIC) or changing * the power state of a device before reboot. * e.g. drivers/net/e100.c. + * @async_shutdown_start: This starts the asynchronous shutdown + * @async_shutdown_end: This completes the started asynchronous shutdown * @sriov_configure: Optional driver callback to allow configuration of * number of VFs to enable via sysfs "sriov_numvfs" file. * @sriov_set_msix_vec_count: PF Driver callback to change number of MSI-X @@ -947,6 +949,8 @@ struct pci_driver { int (*suspend)(struct pci_dev *dev, pm_message_t state); /* Device suspended */ int (*resume)(struct pci_dev *dev); /* Device woken up */ void (*shutdown)(struct pci_dev *dev); + void (*async_shutdown_start)(struct pci_dev *dev); + void (*async_shutdown_end)(struct pci_dev *dev); int (*sriov_configure)(struct pci_dev *dev, int num_vfs); /* On PF */ int (*sriov_set_msix_vec_count)(struct pci_dev *vf, int msix_vec_count); /* On PF */ u32 (*sriov_get_vf_total_msix)(struct pci_dev *pf); From patchwork Wed Feb 7 18:40:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Jeffery X-Patchwork-Id: 198036 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:168b:b0:106:860b:bbdd with SMTP id ma11csp2432645dyb; Wed, 7 Feb 2024 10:43:49 -0800 (PST) X-Google-Smtp-Source: AGHT+IGcQKyhXcPbE5HsZBoQyRC9bBn1OB4ol62yZiMj2j5CT9tkSZiLIDbsI1+Lx9yCMng/DGKk X-Received: by 2002:ac8:5bd4:0:b0:42c:41bd:329c with SMTP id b20-20020ac85bd4000000b0042c41bd329cmr1816140qtb.0.1707331429551; Wed, 07 Feb 2024 10:43:49 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707331429; cv=pass; d=google.com; s=arc-20160816; b=v5F3tgzVJaAIXTZs3+ZB0cJKXp/ixjx2C1Mm+kkXVUyJATzQfEnnf3UwnOVPMHfj/l SQiiXl8W2na8rE3et7G/vYqnr2Ka0ovqrkID5Fm9BTGP4sSbp3V5SHKFs0d1y5Tl9W9f EVELgvqdQcQ3TLcxB0I+G610qtBelPNj+AzfyAXNpEISxwdlfCwjvK173aaNxLLT521a tOSp7t6y4J1oztBv70YOv93cnkpFeeCnXGi0HJS5IqbCHS2CpMPAnHuiV0Ts11wGWWun GuZqWMLO4+ZNCbrSBIE982GElL7kb1NGs6Vt6UT5irHhmvLsXbopYBx2m8aPBYmHFPcc v0NQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=cuv9rvzEed+0pQINLR4eZlmzvTUXMYlIRXYRIOt5NJQ=; fh=zmbN32ajG2gAW+W7IBul3Agq15dVgmSU7uvcp3FhAkA=; b=Fb7H4wJbjnVvp88CRr5K47BTUtojP4iFgMamcYbGxGUcZOphRdMS7a9RR3ffzi4SqM VjM3iCcfP5aMljOXNBm38TWr2I3mth879WNgutSuluLUDB2IAVwxczP3qvNl7OXXe26O 5JCPVhn8PAMHK9jTAftxlGgbFk6MNyVVtAFlIRqYZxRNQa+zea/RKrJ6s8K+0cclQNid 1bLPnEg3SsFJSQSTxxlwayvZhB0oHuPlz/3EGlfxOyoCQ968MNxsuzdPNsdhZe4sYUNt 01vOtzfHtk2JOdndKaLAVaksj89GXXMosRHlcdG1udmz6BIpBGInJInyhOeArY6Vwe1q mwgw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=hQdUkb2A; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56920-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56920-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com X-Forwarded-Encrypted: i=2; AJvYcCWVje1VK5KbrimT2sk+LYbvpcYeJ/02ho4RXuI/36cAmIDza5/3FrV1r9sxchn9diSaMRsgdo/uyXYBYX2jowB8P35BLQ== Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id g12-20020ac85d4c000000b0042c371969d2si1716667qtx.512.2024.02.07.10.43.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Feb 2024 10:43:49 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-56920-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=hQdUkb2A; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56920-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56920-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 4B75F1C2517C for ; Wed, 7 Feb 2024 18:43:49 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4043C86157; Wed, 7 Feb 2024 18:42:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="hQdUkb2A" Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 D080F8529D for ; Wed, 7 Feb 2024 18:42:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331349; cv=none; b=cd4Ofj2aqgfSOlGqS3W2fRNEiAIa3gqJCnxT/pneZnlYb/1EUKVtdp/35EpVTpKEkiR8pfDNgWVxLg+O14pY7irl7Xav2Ub3Wzn0GdXqcQEp1A/12ZLtD1/MmqiJZgiHos3ddqwmLQnPgwF1iMtUNKV/a3gRZqS5Mwam8CJZQfw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331349; c=relaxed/simple; bh=UeygM9npBEUq1MKQwn5tUh8m7ES9H0uWtUU1AqB2VWY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=c5OmLJjlz2QV79JOUa7V9l/3Km9ENHj+ASSc1qnZqqQBXekuFvdB+6CuJ4wtN3FBIxvO8yfqTLGtwhzOx3hBH45189UjfGiuY/0EqYlSXd8J0xLtvuI6Xoh1P7qghNS5mBjhtD4kCgFOHUrpi86Ex23sSmN25GiHv6B17yO5wUk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=hQdUkb2A; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1707331346; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cuv9rvzEed+0pQINLR4eZlmzvTUXMYlIRXYRIOt5NJQ=; b=hQdUkb2A4TuKqF5vVQFX2zuhjv55gntocFpadqGy3TIiMSHaalZkGxi8LQ918t2HkJpGNS xSQJGFIvP0krvy3h7ycQC9lRC/xSGmgmNzo1i+CtvUyffrU7B5rfVXIHTOA9k2Z4HgFF3u sGlpOV5VX5B4HmR1QJr8WzDFoCw9TQc= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-664-s5caMUuGOx6vwEyw6XmQ_A-1; Wed, 07 Feb 2024 13:42:25 -0500 X-MC-Unique: s5caMUuGOx6vwEyw6XmQ_A-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 1A62D29AC012; Wed, 7 Feb 2024 18:42:25 +0000 (UTC) Received: from fedora-work.redhat.com (unknown [10.22.32.236]) by smtp.corp.redhat.com (Postfix) with ESMTP id A15F140C9444; Wed, 7 Feb 2024 18:42:24 +0000 (UTC) From: David Jeffery To: linux-kernel@vger.kernel.org Cc: linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, Greg Kroah-Hartman , "Rafael J . Wysocki" , David Jeffery , Laurence Oberman Subject: [RFC PATCH 4/6] pci nvme async shutdown support Date: Wed, 7 Feb 2024 13:40:58 -0500 Message-ID: <20240207184100.18066-5-djeffery@redhat.com> In-Reply-To: <20240207184100.18066-1-djeffery@redhat.com> References: <20240207184100.18066-1-djeffery@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790266761166543461 X-GMAIL-MSGID: 1790266761166543461 Alter nvme so that the pci nvme driver may shut down the hardware asynchronously, providing a large benefit to shutdown time with large numbers of nvme devices in some configurations. The functionality of nvme_disable_ctrl is split in separate functions for starting disabling the hardware and for waiting for the hardware to report success. A wrapper is created which provides the same interface for the other nvme types so they remain unchanged. And new field is added to nvme-pci's nvme_dev to track the nvme shutdown state so that the nvme async_shutdown_end call knows what if anything it still needs to do. Signed-off-by: David Jeffery Tested-by: Laurence Oberman --- drivers/nvme/host/core.c | 26 +++++++++++++++----- drivers/nvme/host/nvme.h | 2 ++ drivers/nvme/host/pci.c | 53 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 85ab0fcf9e88..b24985a843a8 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2242,20 +2242,21 @@ static int nvme_wait_ready(struct nvme_ctrl *ctrl, u32 mask, u32 val, return ret; } -int nvme_disable_ctrl(struct nvme_ctrl *ctrl, bool shutdown) +int nvme_disable_ctrl_send(struct nvme_ctrl *ctrl, bool shutdown) { - int ret; - ctrl->ctrl_config &= ~NVME_CC_SHN_MASK; if (shutdown) ctrl->ctrl_config |= NVME_CC_SHN_NORMAL; else ctrl->ctrl_config &= ~NVME_CC_ENABLE; - ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config); - if (ret) - return ret; + return ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config); +} +EXPORT_SYMBOL_GPL(nvme_disable_ctrl_send); + +int nvme_disable_ctrl_wait(struct nvme_ctrl *ctrl, bool shutdown) +{ if (shutdown) { return nvme_wait_ready(ctrl, NVME_CSTS_SHST_MASK, NVME_CSTS_SHST_CMPLT, @@ -2266,6 +2267,19 @@ int nvme_disable_ctrl(struct nvme_ctrl *ctrl, bool shutdown) return nvme_wait_ready(ctrl, NVME_CSTS_RDY, 0, (NVME_CAP_TIMEOUT(ctrl->cap) + 1) / 2, "reset"); } +EXPORT_SYMBOL_GPL(nvme_disable_ctrl_wait); + + +int nvme_disable_ctrl(struct nvme_ctrl *ctrl, bool shutdown) +{ + int ret; + + ret = nvme_disable_ctrl_send(ctrl, shutdown); + if (!ret) + ret = nvme_disable_ctrl_wait(ctrl, shutdown); + + return ret; +} EXPORT_SYMBOL_GPL(nvme_disable_ctrl); int nvme_enable_ctrl(struct nvme_ctrl *ctrl) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 030c80818240..5bdd862328d4 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -761,6 +761,8 @@ void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl); bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, enum nvme_ctrl_state new_state); int nvme_disable_ctrl(struct nvme_ctrl *ctrl, bool shutdown); +int nvme_disable_ctrl_send(struct nvme_ctrl *ctrl, bool shutdown); +int nvme_disable_ctrl_wait(struct nvme_ctrl *ctrl, bool shutdown); int nvme_enable_ctrl(struct nvme_ctrl *ctrl); int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, const struct nvme_ctrl_ops *ops, unsigned long quirks); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index c1d6357ec98a..c2a7b3d28a56 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -112,6 +112,12 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown); static void nvme_delete_io_queues(struct nvme_dev *dev); static void nvme_update_attrs(struct nvme_dev *dev); +enum nvme_disable_state { + NVME_DISABLE_START = 0, + NVME_DISABLE_WAIT = 1, + NVME_DISABLE_DONE = 2, +}; + /* * Represents an NVM Express device. Each nvme_dev is a PCI function. */ @@ -159,6 +165,7 @@ struct nvme_dev { unsigned int nr_allocated_queues; unsigned int nr_write_queues; unsigned int nr_poll_queues; + enum nvme_disable_state disable_state; }; static int io_queue_depth_set(const char *val, const struct kernel_param *kp) @@ -2574,12 +2581,14 @@ static bool nvme_pci_ctrl_is_dead(struct nvme_dev *dev) return (csts & NVME_CSTS_CFS) || !(csts & NVME_CSTS_RDY); } -static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) +static void nvme_dev_disable_start(struct nvme_dev *dev, bool shutdown) { enum nvme_ctrl_state state = nvme_ctrl_state(&dev->ctrl); struct pci_dev *pdev = to_pci_dev(dev->dev); bool dead; + dev->disable_state = NVME_DISABLE_START; + mutex_lock(&dev->shutdown_lock); dead = nvme_pci_ctrl_is_dead(dev); if (state == NVME_CTRL_LIVE || state == NVME_CTRL_RESETTING) { @@ -2597,7 +2606,20 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) if (!dead && dev->ctrl.queue_count > 0) { nvme_delete_io_queues(dev); - nvme_disable_ctrl(&dev->ctrl, shutdown); + nvme_disable_ctrl_send(&dev->ctrl, shutdown); + dev->disable_state = NVME_DISABLE_WAIT; + } +} + +static void nvme_dev_disable_end(struct nvme_dev *dev, bool shutdown) +{ + struct pci_dev *pdev = to_pci_dev(dev->dev); + + if (dev->disable_state == NVME_DISABLE_DONE) + return; + + if (dev->disable_state == NVME_DISABLE_WAIT) { + nvme_disable_ctrl_wait(&dev->ctrl, shutdown); nvme_poll_irqdisable(&dev->queues[0]); } nvme_suspend_io_queues(dev); @@ -2623,6 +2645,12 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) mutex_unlock(&dev->shutdown_lock); } +static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) +{ + nvme_dev_disable_start(dev, shutdown); + nvme_dev_disable_end(dev, shutdown); +} + static int nvme_disable_prepare_reset(struct nvme_dev *dev, bool shutdown) { if (!nvme_wait_reset(&dev->ctrl)) @@ -3120,6 +3148,25 @@ static void nvme_shutdown(struct pci_dev *pdev) nvme_disable_prepare_reset(dev, true); } +static void nvme_shutdown_start(struct pci_dev *pdev) +{ + struct nvme_dev *dev = pci_get_drvdata(pdev); + + if (!nvme_wait_reset(&dev->ctrl)) { + dev->disable_state = NVME_DISABLE_DONE; + return; + } + nvme_dev_disable_start(dev, true); +} + +static void nvme_shutdown_end(struct pci_dev *pdev) +{ + struct nvme_dev *dev = pci_get_drvdata(pdev); + + nvme_dev_disable_end(dev, true); +} + + /* * The driver's remove may be called on a device in a partially initialized * state. This function must not have any dependencies on the device state in @@ -3511,6 +3558,8 @@ static struct pci_driver nvme_driver = { .probe = nvme_probe, .remove = nvme_remove, .shutdown = nvme_shutdown, + .async_shutdown_start = nvme_shutdown_start, + .async_shutdown_end = nvme_shutdown_end, .driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, #ifdef CONFIG_PM_SLEEP From patchwork Wed Feb 7 18:40:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Jeffery X-Patchwork-Id: 198037 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:168b:b0:106:860b:bbdd with SMTP id ma11csp2432927dyb; Wed, 7 Feb 2024 10:44:24 -0800 (PST) X-Google-Smtp-Source: AGHT+IEjEmKJWzKxRQzxOD/uW9A9dKvd4gK4HqR4pdmZ6wUgqruu1Jjxc+hXixR3eTbBAlxZln5W X-Received: by 2002:a81:5d8a:0:b0:5ff:5867:e675 with SMTP id r132-20020a815d8a000000b005ff5867e675mr5137267ywb.28.1707331464598; Wed, 07 Feb 2024 10:44:24 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707331464; cv=pass; d=google.com; s=arc-20160816; b=HFVtfdFIqwoDJepDqmXE4E9r1uOb7Js5lU27Q6sy65EFkfI7mq1Vye9aRbn4uOHy3l qTu/1pnA86PP2wV2YTDtbdVbi9qYNNb5Xk3WVQuM6eejqbMYpjOdq0niVLnmTRAqsuTj j6ca5JahyfgBE5SmcenM2knxK70e2YICHSCVkiDHQ609nAkkA4oJWnaKIiEQZslnx+/Z te7PKeHtzHmv5y5SiEvhsua7bRwUVY67fZJ1tIPezK+0ltLZ+ustKaAK/cafTmuUdVp+ 0pe1yicpZawNz+MghM6Cuo6m8WnYU5HfLEAXjPv7jZnQKEBpabgfgHYIkraMaWvHJFmZ m7uA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=CkqM01Ya14Nn8HXhASJf/0/vp8tMuDctYMCTKWoKrUI=; fh=Wf/1FxiMTzR3xv1oFEtw74o/65+ySTxmQBkM3opS4mU=; b=rjkLoz9j29aErsdLDG+yceksIBJs5M9vj6y5hhbXACX99Di6pvaoNE1mFSfXvyaNA2 o1r8xA/Yqj4RN8Y4kBWjLZgblXiIzczC4LGuGpYC4N6f9Z5D/ZjdHxUC6RBvzyY/vuiM B27lVUSgv8YSvSzFDIkvRft+vmk59fHTiCAtZiguKf1vo5vClHbGWeUlvS7iexHNAl9/ 1M4lm6gUmZwmjhJuLcUVVakWAZtR28ikc0SpV5E+Yf4CUhesyXWwfe49VbhhmBzcdHJS mYUlkYRD1TFqLHKa3ErFvW/wrKlB4ExXoTyYTszKFnkE+NYmsg/vMcgPXFUrW8ED67cS pKZQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Qez9rF5q; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56921-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56921-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com X-Forwarded-Encrypted: i=2; AJvYcCV3INIwbkvFfNiDRUUjzV2iXSyB38hckw1YbjIdG+YnnWNtToNJWuVt73WtZWxCdxL6mWn1DVGVWXXaXqwbzQ+cKmtnJQ== Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id k1-20020ac85fc1000000b0042c3ec67952si1729576qta.10.2024.02.07.10.44.24 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Feb 2024 10:44:24 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-56921-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Qez9rF5q; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56921-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56921-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 565441C24A1B for ; Wed, 7 Feb 2024 18:44:24 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8F1B3126F37; Wed, 7 Feb 2024 18:42:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Qez9rF5q" Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 0087885C55 for ; Wed, 7 Feb 2024 18:42:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331354; cv=none; b=tBvasGo3yb3+U/Ld3cK3XD6+Q+uooEVwjOTwaKpnAcEJp5YXWk6REpaynM48/efa2WpZgvEL+5LQMQJFqOi7OlohXoDkJLQIAG6RQwJFMHgjUuKJ13YYKro6wE6UToNWdRNLF5qk/df5Zu/MLWDEzU4UloJWqJM0hmErAkvSEHI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331354; c=relaxed/simple; bh=WqtFxcWaLhMLfcgOm6/fPisBGllXDcSk/ewd1nnwqAo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PGXVQ7A6IHm+eltN/5TOtbV4f4m8kmDiDloxLir9Ib04vc6gqvnCg4DZQlk8EEhfBYTuLzJx1NXChYL06tXnfMcq/Gx3a+PTYqDT+eXdt8RuSVTEgcqpLnQXr6RCWhDamMOGZhYpHlPBapT4UFSQA+Sw01TtUY6qdtWRob6hJf0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Qez9rF5q; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1707331352; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CkqM01Ya14Nn8HXhASJf/0/vp8tMuDctYMCTKWoKrUI=; b=Qez9rF5q83g+zLRbfk8AG8419pUiEpu+YN8evHmwO+y9a6LM3n0a02QSF/aQYJsSOf1Wb0 gKf3Re9aRUk+2a+0x6muWMtaQcNprTAQ6OujsnTzAeG/MDFbWpUHaFJzXcNNlp4Ti3S+HK gk3/fGVS3ENWcLprC0wO2V1mE+Nv9Mo= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-180-Nw_CWQa9P_abWidS2p2VLA-1; Wed, 07 Feb 2024 13:42:26 -0500 X-MC-Unique: Nw_CWQa9P_abWidS2p2VLA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 7AE253C23FC6; Wed, 7 Feb 2024 18:42:26 +0000 (UTC) Received: from fedora-work.redhat.com (unknown [10.22.32.236]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1127740C9444; Wed, 7 Feb 2024 18:42:26 +0000 (UTC) From: David Jeffery To: linux-kernel@vger.kernel.org Cc: linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, Greg Kroah-Hartman , "Rafael J . Wysocki" , David Jeffery , Laurence Oberman Subject: [RFC PATCH 5/6] scsi mid layer support for async command submit Date: Wed, 7 Feb 2024 13:40:59 -0500 Message-ID: <20240207184100.18066-6-djeffery@redhat.com> In-Reply-To: <20240207184100.18066-1-djeffery@redhat.com> References: <20240207184100.18066-1-djeffery@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790266797860408236 X-GMAIL-MSGID: 1790266797860408236 Create scsi_execute_cmd_nowait to allow asynchronous scsi command submit. Parts of the code originally in scsi_execute_cmd are shifted into helper functions used by both scsi_execute_cmd and the new scsi_execute_cmd_nowait. The scsi_exec_args struct is expanded to contain the fields needed for the completion and callback for the async path. Signed-off-by: David Jeffery Tested-by: Laurence Oberman --- drivers/scsi/scsi_lib.c | 138 +++++++++++++++++++++++++++++-------- include/scsi/scsi_device.h | 8 +++ 2 files changed, 118 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1fb80eae9a63..fe35bc2021e3 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -185,42 +185,37 @@ void scsi_queue_insert(struct scsi_cmnd *cmd, int reason) } /** - * scsi_execute_cmd - insert request and wait for the result + * scsi_execute_init - helper for setting up a scsi_cmnd in a request * @sdev: scsi_device * @cmd: scsi command * @opf: block layer request cmd_flags - * @buffer: data buffer - * @bufflen: len of buffer * @timeout: request timeout in HZ * @retries: number of times to retry request - * @args: Optional args. See struct definition for field descriptions + * @args: scsi command args * - * Returns the scsi_cmnd result field if a command was executed, or a negative - * Linux error code if we didn't get that far. + * Returns a request if successful, or an error pointer if there was a failure. */ -int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd, - blk_opf_t opf, void *buffer, unsigned int bufflen, - int timeout, int retries, - const struct scsi_exec_args *args) +static struct request *scsi_execute_init(struct scsi_device *sdev, + const unsigned char *cmd, + blk_opf_t opf, + int timeout, int retries, + struct scsi_exec_args *args) { - static const struct scsi_exec_args default_args; struct request *req; struct scsi_cmnd *scmd; int ret; - if (!args) - args = &default_args; - else if (WARN_ON_ONCE(args->sense && - args->sense_len != SCSI_SENSE_BUFFERSIZE)) - return -EINVAL; + if (WARN_ON_ONCE(args->sense && + args->sense_len != SCSI_SENSE_BUFFERSIZE)) + return ERR_PTR(-EINVAL); req = scsi_alloc_request(sdev->request_queue, opf, args->req_flags); if (IS_ERR(req)) - return PTR_ERR(req); + return req; - if (bufflen) { - ret = blk_rq_map_kern(sdev->request_queue, req, - buffer, bufflen, GFP_NOIO); + if (args->bufflen) { + ret = blk_rq_map_kern(sdev->request_queue, req, args->buffer, + args->bufflen, GFP_NOIO); if (ret) goto out; } @@ -232,19 +227,27 @@ int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd, req->timeout = timeout; req->rq_flags |= RQF_QUIET; - /* - * head injection *required* here otherwise quiesce won't work - */ - blk_execute_rq(req, true); + return req; +out: + blk_mq_free_request(req); + return ERR_PTR(ret); +} + +static int scsi_execute_uninit(struct request *req, + struct scsi_exec_args *args) +{ + struct scsi_cmnd *scmd; + scmd = blk_mq_rq_to_pdu(req); /* * Some devices (USB mass-storage in particular) may transfer * garbage data together with a residue indicating that the data * is invalid. Prevent the garbage from being misinterpreted * and prevent security leaks by zeroing out the excess data. */ - if (unlikely(scmd->resid_len > 0 && scmd->resid_len <= bufflen)) - memset(buffer + bufflen - scmd->resid_len, 0, scmd->resid_len); + if (unlikely(scmd->resid_len > 0 && scmd->resid_len <= args->bufflen)) + memset(args->buffer + args->bufflen - scmd->resid_len, 0, + scmd->resid_len); if (args->resid) *args->resid = scmd->resid_len; @@ -254,14 +257,93 @@ int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd, scsi_normalize_sense(scmd->sense_buffer, scmd->sense_len, args->sshdr); - ret = scmd->result; - out: + args->result = scmd->result; + + if (args->callback) + args->callback(scmd, args); + + return scmd->result; +} + +/** + * scsi_execute_cmd - insert request and wait for the result + * @sdev: scsi_device + * @cmd: scsi command + * @opf: block layer request cmd_flags + * @buffer: data buffer + * @bufflen: len of buffer + * @timeout: request timeout in HZ + * @retries: number of times to retry request + * @args: Optional args. See struct definition for field descriptions + * + * Returns the scsi_cmnd result field if a command was executed, or a negative + * Linux error code if we didn't get that far. + */ +int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd, + blk_opf_t opf, void *buffer, unsigned int bufflen, + int timeout, int retries, + const struct scsi_exec_args *const_args) +{ + struct scsi_exec_args args; + int ret; + struct request *req; + + if (!const_args) + memset(&args, 0, sizeof(struct scsi_exec_args)); + else + args = *const_args; + + args.buffer = buffer; + args.bufflen = bufflen; + + req = scsi_execute_init(sdev, cmd, opf, timeout, retries, &args); + + if (IS_ERR(req)) + return PTR_ERR(req); + + /* + * head injection *required* here otherwise quiesce won't work + */ + blk_execute_rq(req, true); + + ret = scsi_execute_uninit(req, &args); + blk_mq_free_request(req); return ret; } EXPORT_SYMBOL(scsi_execute_cmd); + +static enum rq_end_io_ret scsi_execute_cmd_complete(struct request *req, + blk_status_t ret) +{ + struct scsi_exec_args *args = req->end_io_data; + + scsi_execute_uninit(req, args); + return RQ_END_IO_FREE; +} + +int scsi_execute_cmd_nowait(struct scsi_device *sdev, const unsigned char *cmd, + blk_opf_t opf, int timeout, int retries, + struct scsi_exec_args *args) +{ + struct request *req; + + req = scsi_execute_init(sdev, cmd, opf, timeout, retries, args); + + if (IS_ERR(req)) + return PTR_ERR(req); + + req->end_io = scsi_execute_cmd_complete; + req->end_io_data = args; + + blk_execute_rq_nowait(req, true); + + return 0; +} +EXPORT_SYMBOL(scsi_execute_cmd_nowait); + /* * Wake up the error handler if necessary. Avoid as follows that the error * handler is not woken up if host in-flight requests number == diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 5ec1e71a09de..c80c98b48bc1 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -497,6 +497,10 @@ struct scsi_exec_args { blk_mq_req_flags_t req_flags; /* BLK_MQ_REQ flags */ int scmd_flags; /* SCMD flags */ int *resid; /* residual length */ + void *buffer; /* data buffer */ + unsigned int bufflen; /* buffer length */ + int result; /* scsi layer result */ + void (*callback)(struct scsi_cmnd *scmd, struct scsi_exec_args *args); }; int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd, @@ -504,6 +508,10 @@ int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd, int timeout, int retries, const struct scsi_exec_args *args); +int scsi_execute_cmd_nowait(struct scsi_device *sdev, const unsigned char *cmd, + blk_opf_t opf, int timeout, int retries, + struct scsi_exec_args *args); + extern void sdev_disable_disk_events(struct scsi_device *sdev); extern void sdev_enable_disk_events(struct scsi_device *sdev); extern int scsi_vpd_lun_id(struct scsi_device *, char *, size_t); From patchwork Wed Feb 7 18:41:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Jeffery X-Patchwork-Id: 198039 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:168b:b0:106:860b:bbdd with SMTP id ma11csp2433233dyb; Wed, 7 Feb 2024 10:45:03 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUlrv69OpDdcf5YF/EIsW/b79qwTRD7VPHZTxnHfE1DYihDSfhtAjY/UmieHVqA0LCJDp2htIAqSdbGuuwqTnvncGrzcQ== X-Google-Smtp-Source: AGHT+IELFHX5k58lfzLiq3CHU9hopX2MRGyUG3cS6wzeT20+Dw4PUWdGYVSrw1QbUvDlvMOi7pQc X-Received: by 2002:a17:902:654d:b0:1d9:ec15:e4e6 with SMTP id d13-20020a170902654d00b001d9ec15e4e6mr2906110pln.55.1707331503203; Wed, 07 Feb 2024 10:45:03 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707331503; cv=pass; d=google.com; s=arc-20160816; b=tnJ8EGIvWzQiz1LOw4Pqdm9KaMyHs/J5GYTSW4LYj2BL+43cgpoMDdneJvlLxcrdA2 kKvryTOvmAHSeCZIRxwgw3vKLBjo1NR3XQFPdrmh3aiJoPMGlkI4XwuZG85+KLbYO/Xi YjAdZmn56u7XMAWAlnhG4q1Bt7T1GobfQXCqZfnjUSwzDIyeFUr+sMqdp2OnwIJCudoI RN+qKcFZdHqU54IxU/eGchCVEH+W4OvOwHBPsxt7L9GeslOIYSAkXNm7oEIP/e1xkhxH RQiZLtRz007Pv1H3CgCgqzGEDp23f8RfW6ZQ5Mg5Idvk83zfn3lB2eEGULxlpq2SO0J3 WCcQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=VwU//eJ9yadzq/fsfDhiEtvVbtfHI98m1htYpt9Ipdk=; fh=XNwfcAWlltiq79GkeZUYpHcYiepLESU6CQ4QmtnI7zo=; b=G1WzoEpFDT1karAic5A5yhi7p4rYnaSh2tYiyeadPOSZfbG4C8ThEDcH+8Q/MDdf2Y c4sgUQpRfWihnRxCdZPoMJBn5+rvl85XufYM5xoguPI9mwIP042Y6V1zyHEs0oIplMYa BfUWY1oXMBcdiJCyQ0o/bYOwGYpWG+jMzHtrgGYEs+ViQfbnDVyJtp9QEhjE+RSaIiUV myY8WEVuSgRMhU93Usi3kmoDhza8lowcUs5vMKtKH3s1hqNvPBGkb/Cx9HyhSh900Io4 KUoKBqZK+bRJBT4YpOp5l3fYqcipGXAsjcMtrKyTtpPconSOUo8eFBdfQEA8TXSfXScc xPWw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="ee+/qVnN"; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56922-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56922-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com X-Forwarded-Encrypted: i=2; AJvYcCWi6u/hZmygc3tB+Vtr4E/XywDTmoG6I3lVjfTFAGCaENYtl719xMlmTFuR1Tm5bD2y4v65nbTPiZ/0vubOZsNBuJMfxQ== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id n5-20020a170902e54500b001d96381a4b9si2382011plf.482.2024.02.07.10.45.03 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Feb 2024 10:45:03 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-56922-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="ee+/qVnN"; arc=pass (i=1 spf=pass spfdomain=redhat.com dkim=pass dkdomain=redhat.com dmarc=pass fromdomain=redhat.com); spf=pass (google.com: domain of linux-kernel+bounces-56922-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56922-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 3B729289D50 for ; Wed, 7 Feb 2024 18:44:28 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 257E01272A9; Wed, 7 Feb 2024 18:42:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ee+/qVnN" Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 77F3C86AC3 for ; Wed, 7 Feb 2024 18:42:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331356; cv=none; b=Qi4ljkF/vrHX4nGpBDUrtvAH5KfZ/+ZvBs+3ObruDqt5/imlLDriE18fjdk5rWWXEvSnYBMpwgOZFOYZiUa60Oe2wcjoh5Wx2ZtwcG9uYFb+viRrNupSGKcK9pDyXbzieD/Z5awcRp3PrlWbwpPKFB6zRsGZYbaS5SNVqBxcdT4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707331356; c=relaxed/simple; bh=WxvH6FDX/eWNGMCI+SWHVfMnLqP3askGdu0ASe254/Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dti5G61IYM7E/xP0blr6rXq8jHow9ioL3O1qFm/+sKT+dUgZIlL1MSqzUbIBGphb/gbBbAC3k1jn6magHNPt9VouvC+tKqh+ctQdJpzqY4TntEi1AySekKQrDZkxTwq2gbvX3EkWaaBde7iAVMeqkWP5Y3smT61/sXmoGAUTrt0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=ee+/qVnN; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1707331353; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VwU//eJ9yadzq/fsfDhiEtvVbtfHI98m1htYpt9Ipdk=; b=ee+/qVnNk8KVahdZouW+oiRq+/6BcPlD/19dTMp7FKf/ffDaQlzVIwY7lzY3yRKfdSKLwQ mSlf9lkl5x/41VPySBTQ8mJWuoicJinakPK3hXwGTmmtp9q0wlhFExOy2snv9o5hLpSCkq KwzjtSM8HjhAeHd1WaXxvKefl70x0Iw= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-686-m-6gGQ7ROWmYlHUy-tFPLQ-1; Wed, 07 Feb 2024 13:42:28 -0500 X-MC-Unique: m-6gGQ7ROWmYlHUy-tFPLQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 28C2C84AF81; Wed, 7 Feb 2024 18:42:28 +0000 (UTC) Received: from fedora-work.redhat.com (unknown [10.22.32.236]) by smtp.corp.redhat.com (Postfix) with ESMTP id AC90B4011FF1; Wed, 7 Feb 2024 18:42:27 +0000 (UTC) From: David Jeffery To: linux-kernel@vger.kernel.org Cc: linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org, Greg Kroah-Hartman , "Rafael J . Wysocki" , David Jeffery , Laurence Oberman Subject: [RFC PATCH 6/6] sd: async cache flush on shutdown Date: Wed, 7 Feb 2024 13:41:00 -0500 Message-ID: <20240207184100.18066-7-djeffery@redhat.com> In-Reply-To: <20240207184100.18066-1-djeffery@redhat.com> References: <20240207184100.18066-1-djeffery@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790266838701545978 X-GMAIL-MSGID: 1790266838701545978 Add async shutdown for the cache flush to the sd device by sending a SYNCHRONIZE_CACHE command asynchronously. If there is any sort of error, falls back to the synchronous sd_sync_cache() to try again and resolve any errors. Signed-off-by: David Jeffery Tested-by: Laurence Oberman --- drivers/scsi/sd.c | 66 ++++++++++++++++++++++++++++++++++++++++++----- drivers/scsi/sd.h | 2 ++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 0833b3e6aa6e..f972310df76a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3838,23 +3838,64 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) return 0; } -/* - * Send a SYNCHRONIZE CACHE instruction down to the device through - * the normal SCSI command structure. Wait for the command to - * complete. - */ -static void sd_shutdown(struct device *dev) +static void sd_sync_cache_callback(struct scsi_cmnd *scmd, + struct scsi_exec_args *args) { + struct scsi_disk *sdkp; + + sdkp = container_of(args, struct scsi_disk, shutdown_params); + complete(&sdkp->shutdown_done); +} + +static void sd_async_shutdown_start(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); + const int timeout = sdkp->device->request_queue->rq_timeout + * SD_FLUSH_TIMEOUT_MULTIPLIER; + int ret; if (!sdkp) return; /* this can happen */ + init_completion(&sdkp->shutdown_done); + sdkp->shutdown_params.callback = sd_sync_cache_callback; + if (pm_runtime_suspended(dev)) return; if (sdkp->WCE && sdkp->media_present) { + unsigned char cmd[16] = { 0 }; + sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); + if (sdkp->device->use_16_for_sync) + cmd[0] = SYNCHRONIZE_CACHE_16; + else + cmd[0] = SYNCHRONIZE_CACHE; + + ret = scsi_execute_cmd_nowait(sdkp->device, cmd, REQ_OP_DRV_IN, + timeout, sdkp->max_retries, + &sdkp->shutdown_params); + if (!ret) + return; + sdkp->shutdown_params.result = ret; + } + /* no async I/O to do, go ahead and mark it complete */ + complete(&sdkp->shutdown_done); +} + +static void sd_async_shutdown_end(struct device *dev) +{ + struct scsi_disk *sdkp = dev_get_drvdata(dev); + + if (!sdkp) + return; + + if (pm_runtime_suspended(dev)) + return; + + wait_for_completion(&sdkp->shutdown_done); + + if (sdkp->WCE && sdkp->media_present && sdkp->shutdown_params.result) { + /* for any error with the async flush, retry as sync */ sd_sync_cache(sdkp); } @@ -3867,6 +3908,17 @@ static void sd_shutdown(struct device *dev) } } +/* + * Send a SYNCHRONIZE CACHE instruction down to the device through + * the normal SCSI command structure. Wait for the command to + * complete. + */ +static void sd_shutdown(struct device *dev) +{ + sd_async_shutdown_start(dev); + sd_async_shutdown_end(dev); +} + static inline bool sd_do_start_stop(struct scsi_device *sdev, bool runtime) { return (sdev->manage_system_start_stop && !runtime) || @@ -4003,6 +4055,8 @@ static struct scsi_driver sd_template = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .remove = sd_remove, .shutdown = sd_shutdown, + .async_shutdown_start = sd_async_shutdown_start, + .async_shutdown_end = sd_async_shutdown_end, .pm = &sd_pm_ops, }, .rescan = sd_rescan, diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 409dda5350d1..7b5098211cec 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -91,6 +91,8 @@ struct scsi_disk { struct device disk_dev; struct gendisk *disk; struct opal_dev *opal_dev; + struct scsi_exec_args shutdown_params; + struct completion shutdown_done; #ifdef CONFIG_BLK_DEV_ZONED /* Updated during revalidation before the gendisk capacity is known. */ struct zoned_disk_info early_zone_info;