From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EB88342669E for ; Tue, 28 Jul 2026 12:18:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785241085; cv=none; b=T8MxkFiyThVloC00xmCK+JaXSwdQi+j5X7FKYksVbSG991FIDmWwdaj+8clIlpjr2Z6k5bAq9PiCIGOZ+TtgFHOYRqjChBKLxMhxHgNUkR7KYwuy2zzM4rk2uAlMeQ7Exj6xNmb1DZuDaIh5CczEjf3qKCKbPjPE6UBhG+xjAzo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785241085; c=relaxed/simple; bh=hTLt+iXpQcgFq/h8cbroNqa1GsuSLfFJ9gMH41YkQ9g=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=eqLNhhmpD9S/NsN9ioj/Vid6IKL9duSUaDgHH4BaIz9E9H1scoKEVNKkxd8+s8FaRQ3OQDFdCSpKrqUs+TCnluGc1Wnz4jdLBRlgfLPBcrD8yQiNPHSg1YsXD9USWFS/ZvfWOOF9jIOWH2tJLZavIQg3XsOx0J5ihDiATXhIaE4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=FNfEuFpx; arc=none smtp.client-ip=209.85.214.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FNfEuFpx" Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-2cea3004256so40371125ad.0 for ; Tue, 28 Jul 2026 05:18:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785241083; x=1785845883; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=08TZYCbqGIQFgxaWi3aeV+W4mfKVq6zhCr96lytPW0c=; b=FNfEuFpx/J2ryOXKixCGmUzxjq4UPpksvkHsM4uWrYAhCwmzFK2+0IOBwSNmDoJ9UF HRUnjC9l0h94p3Cdn8EjsWH/fwqD6YVH+ouCuseSoaN8O8M2BIDAPU3dArcyOuArz4i0 nMZqUCtm/+SPJt6lGQXQ2IZnVCCM/mNnOKkkopFTk2QlkZcYoLBx0LQKvZqDPC51oWKh 4NrsJHJDuUqktJ18MI0wvg29/4+m1/uxHEjppZ2tX1LaEVynihm9Kqkh5T3oUnmNN/Xm uYHLcAmcfU1z2C56UxH0yBkYQFiMBFN4GSwDvMA+13G8/cJKKT2GSCaTsAth3TELtfz2 GwWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785241083; x=1785845883; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=08TZYCbqGIQFgxaWi3aeV+W4mfKVq6zhCr96lytPW0c=; b=TeVnfgcH4ppUpHGAUI5k81d3NHxn9KK+var84HqjvJUnuWTP+vO5OTiHtIDAsGVEew wy1Z0WFxBnI2O+xvQBCuugxRHQwCOZ9govrE0IiklH20hYtJtgD2pAoc9W3f+l3NJH8z j89fwlxvkWMSuYBdbYHSOop5NzbdCppW+osd8GD33QX4bqWe+WQZK5pBhcAM535rntrU DV01YJ7Qd+r3E0C2xF2wiiRS0svmVNl5Us07cuQC/yzKU4RI6YI2FifDdrAJsBmHdhjS 8TX0hcrbHH8WB3a2NlFulzmQfj+KihR08nivToLQk6pIQmWDpxhBaoPW2OGOQQ5yB+3k 32Jw== X-Forwarded-Encrypted: i=1; AHgh+RrryLVoIXglRcGL6hwlyCcaw7qWc4Lw9rjEaad++PBZWefTNAtYUL8DsmjnU37jE2LZM/ciHvZCi4aewBo=@vger.kernel.org X-Gm-Message-State: AOJu0Yx8AjnOn01d59gsK1mXKZEIwJxwPf9jgo6BjbPJ0YZizOAon1F/ W37/8oRwRCIh7HeuJyh0He2vD6ck+htP6oXDwlBHFMnEjfq2GCLjzJQt X-Gm-Gg: AR+sD13avGgBMl/TPuIpoQMDJ1EiOItYhljIUesvKvdevy40cQM51RAcyC881IOQXuu asNIG/jDfyeHf4hIszTS3r7okmqMt8Kx+t0vfknqIwvRWUX0SJzHT1LNgEfoqjD3hMUScb51M/O dwhUrttIrGhfPugkvjkcOTPYsPPSU+pp591D8ZiGi1y/vV7Xwm3XpKH89y5URyWH4xDSnIxJCRS jzACFXBQrkQJFJFlrvmWYI2VD4zSLtMaO/eIRFwnIfhrymw9bZI7thgI7NINS11xZ0AOKDGWr6J HmKm9eqTxVJQx+hhHIYb/NpzLjTZwRArjOrevXsvwlWuT89isHt25YV+8aXMrMbfK5uzoEgDVwD SHmoQU84B99QkzsLU7pDme0Jb9QvZV1XOrttiiQYfKJ4SbFMg7I5JLiVHdXu1HIoBGnB/VEyVj3 14cLDl X-Received: by 2002:a05:6a21:9991:b0:3c3:9c4e:de3a with SMTP id adf61e73a8af0-3c8aaf8d403mr2699113637.6.1785241082932; Tue, 28 Jul 2026 05:18:02 -0700 (PDT) Received: from n232-175-066.byted.org ([240e:83:200::35b]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-cbbb660daf6sm4478822a12.2.2026.07.28.05.18.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Jul 2026 05:18:02 -0700 (PDT) From: guzebing To: kbusch@kernel.org, axboe@kernel.dk, hch@lst.de, sagi@grimberg.me Cc: linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, Guzebing Subject: [PATCH v4] nvme: reduce firmware activation poll interval Date: Tue, 28 Jul 2026 20:17:35 +0800 Message-Id: <20260728121735.1627370-1-guzebing1612@gmail.com> X-Mailer: git-send-email 2.20.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Guzebing nvme_fw_act_work() polls the controller processing-paused status every 100 ms while firmware activation is pending. Some devices can complete online activation in only a few hundred milliseconds, so the fixed 100 ms interval can add up to 100 ms of latency before the driver observes completion. nvme_wait_ready() already uses a 1 to 2 ms delay between CSTS reads. Use the same interval in nvme_fw_act_work() and factor the CSTS read, status check, and sleep loop into a common helper for both paths. For firmware activation, preserve the existing CC.EN check before testing CSTS.PP. Signed-off-by: Guzebing --- Changes in v4: - Move the CSTS read, status check, and sleep loop into a common helper, preserving the firmware activation path's CC.EN check before CSTS.PP. Changes in v3: - Add a common polling delay helper for nvme_fw_act_work() and nvme_wait_ready(). Changes in v2: - Drop the module parameter and use a fixed 1 to 2 ms poll interval. v3: https://lore.kernel.org/linux-nvme/20260715114401.1084214-1-guzebing1612@gmail.com/ v2: https://lore.kernel.org/linux-nvme/20260714092846.3381169-1-guzebing1612@gmail.com/ v1: https://lore.kernel.org/linux-nvme/20260627010610.47768-1-guzebing1612@gmail.com/ Note: The common helper combines the CSTS condition with a firmware-activation-specific software state condition: the cached CC.EN value in ctrl_config. This follows the suggestion to share the complete polling loop, but makes the helper slightly less focused. Would it be clearer and simpler to keep the loops separate, replace msleep(100) in nvme_fw_act_work() with usleep_range(1000, 2000), and add a comment that the interval matches nvme_wait_ready()? drivers/nvme/host/core.c | 78 +++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 453c1f0b2dd09..d6a7e1cbd0e6f 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2688,33 +2688,52 @@ const struct block_device_operations nvme_bdev_ops = { .pr_ops = &nvme_pr_ops, }; -static int nvme_wait_ready(struct nvme_ctrl *ctrl, u32 mask, u32 val, - u32 timeout, const char *op) +/* + * Poll CSTS until the requested status is reached. + * If exit_if_ctrl_disabled is set, check the cached CC.EN value first and + * stop polling when it is cleared. + */ +static int nvme_wait_csts(struct nvme_ctrl *ctrl, u32 mask, u32 val, + unsigned long timeout, bool exit_if_ctrl_disabled, + u32 *csts) { - unsigned long timeout_jiffies = jiffies + timeout * HZ; - u32 csts; int ret; - while ((ret = ctrl->ops->reg_read32(ctrl, NVME_REG_CSTS, &csts)) == 0) { - if (csts == ~0) + while ((ret = ctrl->ops->reg_read32(ctrl, NVME_REG_CSTS, csts)) == 0) { + if (*csts == ~0) return -ENODEV; - if ((csts & mask) == val) - break; + if (exit_if_ctrl_disabled && + !(ctrl->ctrl_config & NVME_CC_ENABLE)) + return 0; + if ((*csts & mask) == val) + return 0; usleep_range(1000, 2000); if (fatal_signal_pending(current)) return -EINTR; - if (time_after(jiffies, timeout_jiffies)) { - dev_err(ctrl->device, - "Device not ready; aborting %s, CSTS=0x%x\n", - op, csts); - return -ENODEV; - } + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; } return ret; } +static int nvme_wait_ready(struct nvme_ctrl *ctrl, u32 mask, u32 val, + u32 timeout, const char *op) +{ + unsigned long timeout_jiffies = jiffies + timeout * HZ; + u32 csts; + int ret; + + ret = nvme_wait_csts(ctrl, mask, val, timeout_jiffies, false, &csts); + if (ret != -ETIMEDOUT) + return ret; + + dev_err(ctrl->device, + "Device not ready; aborting %s, CSTS=0x%x\n", op, csts); + return -ENODEV; +} + int nvme_disable_ctrl(struct nvme_ctrl *ctrl, bool shutdown) { int ret; @@ -4748,20 +4767,6 @@ static void nvme_async_event_work(struct work_struct *work) ctrl->ops->submit_async_event(ctrl); } -static bool nvme_ctrl_pp_status(struct nvme_ctrl *ctrl) -{ - - u32 csts; - - if (ctrl->ops->reg_read32(ctrl, NVME_REG_CSTS, &csts)) - return false; - - if (csts == ~0) - return false; - - return ((ctrl->ctrl_config & NVME_CC_ENABLE) && (csts & NVME_CSTS_PP)); -} - static void nvme_get_fw_slot_info(struct nvme_ctrl *ctrl) { struct nvme_fw_slot_info_log *log; @@ -4797,6 +4802,8 @@ static void nvme_fw_act_work(struct work_struct *work) struct nvme_ctrl *ctrl = container_of(work, struct nvme_ctrl, fw_act_work); unsigned long fw_act_timeout; + u32 csts; + int ret; nvme_auth_stop(ctrl); @@ -4806,14 +4813,13 @@ static void nvme_fw_act_work(struct work_struct *work) fw_act_timeout = jiffies + secs_to_jiffies(admin_timeout); nvme_quiesce_io_queues(ctrl); - while (nvme_ctrl_pp_status(ctrl)) { - if (time_after(jiffies, fw_act_timeout)) { - dev_warn(ctrl->device, - "Fw activation timeout, reset controller\n"); - nvme_try_sched_reset(ctrl); - return; - } - msleep(100); + ret = nvme_wait_csts(ctrl, NVME_CSTS_PP, 0, fw_act_timeout, true, + &csts); + if (ret == -ETIMEDOUT) { + dev_warn(ctrl->device, + "Fw activation timeout, reset controller\n"); + nvme_try_sched_reset(ctrl); + return; } if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_CONNECTING) || -- 2.20.1