FAILED: patch "[PATCH] nvme-pci: disable controller on admin queue IRQ setup failure" failed to apply to 6.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 08660a5c8d497f43191635d97efd31cd35051f15
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090346-clang-google-039d@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 08660a5c8d497f43191635d97efd31cd35051f15 Mon Sep 17 00:00:00 2001
From: Myeonghun Pak <[email protected]>
Date: Wed, 15 Jul 2026 16:44:59 +0900
Subject: [PATCH] nvme-pci: disable controller on admin queue IRQ setup failure
nvme_pci_configure_admin_queue() enables the controller and then requests the admin queue interrupt. If queue_request_irq() fails it returns without disabling the controller, and no caller compensates: nvme_pci_enable() only frees the IRQ vectors and calls pci_disable_device(), after which nvme_dev_disable() treats the controller as dead and skips nvme_disable_ctrl(). The controller is left enabled (CC.EN set) on this error path.
Disable it in the failure path, while the PCI device is still enabled so the CC.EN clear handshake completes.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
drivers/nvme/host/pci.c +1 -0
@@ -2414,6 +2414,7 @@ static int nvme_pci_configure_admin_queue(struct nvme_dev *dev) result =queue_request_irq (nvmeq);if (result) { dev->online_queues--; +nvme_disable_ctrl (&dev->ctrl, false);return result; }
Sasha Levin
maintainerPATCH 1/5 nvme-pci: call nvme_pci_configure_admin_queue from nvme_pci_enable
From: Christoph Hellwig <[email protected]>
[ Upstream commit a6ee7f19ebfd158ffb3a6ebacf20ae43549bed05 ]
nvme_pci_configure_admin_queue is called right after nvme_pci_enable, and it's work is undone by nvme_dev_disable.
Tested-by Gerd Bayer <[email protected]>
Stable-dep-of: 08660a5c8d49 ("nvme-pci: disable controller on admin queue IRQ setup failure")
--- drivers/nvme/host/pci.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/nvme/host/pci.c +2 -5
@@ -2701,7 +2701,8 @@ static int nvme_pci_enable(struct nvme_dev *dev)pci_enable_pcie_error_reporting (pdev);pci_save_state (pdev); -return 0 ; + +return nvme_pci_configure_admin_queue (dev); disable:pci_disable_device (pdev);
@@ -2894,10 +2895,6 @@ static void nvme_reset_work(struct work_struct *work)if (result) goto out_unlock; - result =nvme_pci_configure_admin_queue (dev); -if (result) - goto out_unlock; -if (!dev->ctrl.admin_q) { result =nvme_pci_alloc_admin_tag_set (dev);if (result)
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/5 nvme-apple: fix controller shutdown in apple_nvme_disable
From: Christoph Hellwig <[email protected]>
[ Upstream commit c76b8308e4c9148e44e0c7e086ab6d8b4bb10162 ]
nvme_shutdown_ctrl already shuts the controller down, there is no need to also call nvme_disable_ctrl for the shutdown case.
Stable-dep-of: 08660a5c8d49 ("nvme-pci: disable controller on admin queue IRQ setup failure")
--- drivers/nvme/host/apple.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/nvme/host/apple.c +2 -1
@@ -831,7 +831,8 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown)if (shutdown)nvme_shutdown_ctrl (&anv->ctrl); -nvme_disable_ctrl (&anv->ctrl); +else +nvme_disable_ctrl (&anv->ctrl); }WRITE_ONCE (anv->ioq.enabled, false);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/5 nvme: use nvme_wait_ready in nvme_shutdown_ctrl
In reply to Sasha LevinFrom: Christoph Hellwig <[email protected]>
[ Upstream commit e6d275de2e4aaebdc97aa022c031a0dcc475efa4 ]
Refactor the code to wait for CSTS state changes so that it can be reused by nvme_shutdown_ctrl. This reduces the delay between each iteration that checks CSTS from 100ms in the shutdown code to the 1 to 2ms range done during enable, matching the changes from commit 3e98c2443f5c that were only applied to the enable/disable path.
Stable-dep-of: 08660a5c8d49 ("nvme-pci: disable controller on admin queue IRQ setup failure")
--- drivers/nvme/host/core.c | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-)
drivers/nvme/host/core.c +12 -26
@@ -2324,16 +2324,17 @@ static const struct block_device_operations nvme_bdev_ops = { .pr_ops = &nvme_pr_ops, }; -static int nvme_wait_ready (struct nvme_ctrl *ctrl,u32 timeout,bool enabled) +static int nvme_wait_ready (struct nvme_ctrl *ctrl,u32 mask,u32 val, +u32 timeout,const char *op) { -unsigned long timeout_jiffies = ((timeout +1 ) *HZ /2 ) + jiffies; -u32 csts, bit = enabled ?NVME_CSTS_RDY :0 ; +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 )return -ENODEV ; -if ((csts &NVME_CSTS_RDY ) == bit) +if ((csts & mask) == val)break ;usleep_range (1000 ,2000 );
@@ -2342,7 +2343,7 @@ static int nvme_wait_ready(struct nvme_ctrl *ctrl, u32 timeout, bool enabled)if (time_after (jiffies, timeout_jiffies)) {dev_err (ctrl->device,"Device not ready; aborting %s, CSTS=0x%x\n" , - enabled ?"initialisation" :"reset" , csts); + op, csts);return -ENODEV ; } }
@@ -2369,8 +2370,8 @@ int nvme_disable_ctrl(struct nvme_ctrl *ctrl)if (ctrl->quirks &NVME_QUIRK_DELAY_BEFORE_CHK_RDY )msleep (NVME_QUIRK_DELAY_AMOUNT ); - -return nvme_wait_ready (ctrl,NVME_CAP_TIMEOUT (ctrl->cap), false); +return nvme_wait_ready (ctrl,NVME_CSTS_RDY ,0 , + (NVME_CAP_TIMEOUT (ctrl->cap) +1 ) /2 ,"reset" ); }EXPORT_SYMBOL_GPL (nvme_disable_ctrl);
@@ -2453,14 +2454,13 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl) ret = ctrl->ops->reg_write32 (ctrl,NVME_REG_CC , ctrl->ctrl_config);if (ret)return ret; -return nvme_wait_ready (ctrl, timeout, true); +return nvme_wait_ready (ctrl,NVME_CSTS_RDY ,NVME_CSTS_RDY , + (timeout +1 ) /2 ,"initialisation" ); }EXPORT_SYMBOL_GPL (nvme_enable_ctrl);int nvme_shutdown_ctrl (struct nvme_ctrl *ctrl) { -unsigned long timeout = jiffies + (ctrl->shutdown_timeout *HZ ); -u32 csts;int ret; ctrl->ctrl_config &= ~NVME_CC_SHN_MASK ;
@@ -2469,22 +2469,8 @@ int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl) ret = ctrl->ops->reg_write32 (ctrl,NVME_REG_CC , ctrl->ctrl_config);if (ret)return ret; - -while ((ret = ctrl->ops->reg_read32 (ctrl,NVME_REG_CSTS , &csts)) ==0 ) { -if ((csts &NVME_CSTS_SHST_MASK ) ==NVME_CSTS_SHST_CMPLT ) -break ; - -msleep (100 ); -if (fatal_signal_pending (current)) -return -EINTR ; -if (time_after (jiffies, timeout)) { -dev_err (ctrl->device, -"Device shutdown incomplete; abort shutdown\n" ); -return -ENODEV ; - } - } - -return ret; +return nvme_wait_ready (ctrl,NVME_CSTS_SHST_MASK ,NVME_CSTS_SHST_CMPLT , + ctrl->shutdown_timeout,"shutdown" ); }EXPORT_SYMBOL_GPL (nvme_shutdown_ctrl);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 4/5 nvme: merge nvme_shutdown_ctrl into nvme_disable_ctrl
In reply to Sasha LevinFrom: Christoph Hellwig <[email protected]>
[ Upstream commit 285b6e9b571714270fa503d0e32f244d15b9f85f ]
Many of the callers decide which one to use based on a bool argument and there is at least some code to be shared, so merge these two. Also move a comment specific to a single callsite to that callsite.
For this stable backport, retain nvme_stop_admin_queue() in the RDMA and TCP teardown paths: this tree does not have the upstream nvme_quiesce_admin_queue() API rename. Convert the shutdown/disable calls in place, preserving the stable tree's admin queue quiescing and teardown order. No new functions are introduced.
The merged nvme_disable_ctrl(ctrl, shutdown) interface is required by 08660a5c8d497f43191635d97efd31cd35051f15 ("nvme-pci: disable controller on admin queue IRQ setup failure"), whose failure-path call passes false.
Stable-dep-of: 08660a5c8d49 ("nvme-pci: disable controller on admin queue IRQ setup failure")
--- drivers/nvme/host/apple.c | 5 +---- drivers/nvme/host/core.c | 33 ++++++++++----------------------- drivers/nvme/host/fc.c | 2 +- drivers/nvme/host/nvme.h | 3 +-- drivers/nvme/host/pci.c | 15 +++++++++------ drivers/nvme/host/rdma.c | 5 +---- drivers/nvme/host/tcp.c | 5 +---- drivers/nvme/target/loop.c | 2 +- 8 files changed, 25 insertions(+), 45 deletions(-)
drivers/nvme/host/apple.c +1 -4
@@ -829,10 +829,7 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown)apple_nvme_remove_cq (anv); } -if (shutdown) -nvme_shutdown_ctrl (&anv->ctrl); -else -nvme_disable_ctrl (&anv->ctrl); +nvme_disable_ctrl (&anv->ctrl, shutdown); }WRITE_ONCE (anv->ioq.enabled, false);
drivers/nvme/host/core.c +10 -23
@@ -2351,23 +2351,25 @@ static int nvme_wait_ready(struct nvme_ctrl *ctrl, u32 mask, u32 val,return ret; } -/* -* If the device has been passed off to us in an enabled state, just clear -* the enabled bit. The spec says we should set the 'shutdown notification -* bits', but doing so may cause the device to complete commands to the -* admin queue ... and we don't know what memory that might be pointing at! -*/ -int nvme_disable_ctrl (struct nvme_ctrl *ctrl) +int nvme_disable_ctrl (struct nvme_ctrl *ctrl,bool shutdown) {int ret; ctrl->ctrl_config &= ~NVME_CC_SHN_MASK ; - ctrl->ctrl_config &= ~NVME_CC_ENABLE ; +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; +if (shutdown) { +return nvme_wait_ready (ctrl,NVME_CSTS_SHST_MASK , +NVME_CSTS_SHST_CMPLT , + ctrl->shutdown_timeout,"shutdown" ); + }if (ctrl->quirks &NVME_QUIRK_DELAY_BEFORE_CHK_RDY )msleep (NVME_QUIRK_DELAY_AMOUNT ); return nvme_wait_ready(ctrl, NVME_CSTS_RDY, 0,
@@ -2459,21 +2461,6 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl) }EXPORT_SYMBOL_GPL (nvme_enable_ctrl); -int nvme_shutdown_ctrl (struct nvme_ctrl *ctrl) -{ -int ret; - - ctrl->ctrl_config &= ~NVME_CC_SHN_MASK ; - ctrl->ctrl_config |=NVME_CC_SHN_NORMAL ; - - ret = ctrl->ops->reg_write32 (ctrl,NVME_REG_CC , ctrl->ctrl_config); -if (ret) -return ret; -return nvme_wait_ready (ctrl,NVME_CSTS_SHST_MASK ,NVME_CSTS_SHST_CMPLT , - ctrl->shutdown_timeout,"shutdown" ); -} -EXPORT_SYMBOL_GPL (nvme_shutdown_ctrl); -static int nvme_configure_timestamp (struct nvme_ctrl *ctrl) {__le64 ts;
drivers/nvme/host/fc.c +1 -1
@@ -2500,7 +2500,7 @@ __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues)* Other transports, which don't have link-level contexts bound * to sqe's, would try to gracefully shutdown the controller by * writing the registers for shutdown and polling (call -* nvme_shutdown_ctrl()). Given a bunch of i/o was potentially +* nvme_disable_ctrl()). Given a bunch of i/o was potentially * just aborted and we will wait on those contexts, and given * there was no indication of how live the controlelr is on the * link, don't send more io to create more contexts for the
drivers/nvme/host/nvme.h +1 -2
@@ -745,9 +745,8 @@ void nvme_cancel_tagset(struct nvme_ctrl *ctrl);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); +int nvme_disable_ctrl (struct nvme_ctrl *ctrl,bool shutdown);int nvme_enable_ctrl (struct nvme_ctrl *ctrl); -int nvme_shutdown_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);void nvme_uninit_ctrl (struct nvme_ctrl *ctrl);
drivers/nvme/host/pci.c +9 -6
@@ -1539,11 +1539,7 @@ static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown) {struct nvme_queue *nvmeq = &dev->queues[0 ]; -if (shutdown) -nvme_shutdown_ctrl (&dev->ctrl); -else -nvme_disable_ctrl (&dev->ctrl); - +nvme_disable_ctrl (&dev->ctrl, shutdown);nvme_poll_irqdisable (nvmeq); }
@@ -1865,7 +1861,14 @@ static int nvme_pci_configure_admin_queue(struct nvme_dev *dev) (readl(dev->bar + NVME_REG_CSTS) & NVME_CSTS_NSSRO))writel (NVME_CSTS_NSSRO , dev->bar +NVME_REG_CSTS ); - result =nvme_disable_ctrl (&dev->ctrl); +/* +* If the device has been passed off to us in an enabled state, just +* clear the enabled bit. The spec says we should set the 'shutdown +* notification bits', but doing so may cause the device to complete +* commands to the admin queue ... and we don't know what memory that +* might be pointing at! +*/ + result =nvme_disable_ctrl (&dev->ctrl, false);if (result <0 )return result;
drivers/nvme/host/rdma.c +1 -4
@@ -2213,10 +2213,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown) {nvme_rdma_teardown_io_queues (ctrl, shutdown);nvme_stop_admin_queue (&ctrl->ctrl); -if (shutdown) -nvme_shutdown_ctrl (&ctrl->ctrl); -else -nvme_disable_ctrl (&ctrl->ctrl); +nvme_disable_ctrl (&ctrl->ctrl, shutdown);nvme_rdma_teardown_admin_queue (ctrl, shutdown); }
drivers/nvme/host/tcp.c +1 -4
@@ -2228,10 +2228,7 @@ static void nvme_tcp_teardown_ctrl(struct nvme_ctrl *ctrl, bool shutdown) {nvme_tcp_teardown_io_queues (ctrl, shutdown);nvme_stop_admin_queue (ctrl); -if (shutdown) -nvme_shutdown_ctrl (ctrl); -else -nvme_disable_ctrl (ctrl); +nvme_disable_ctrl (ctrl, shutdown);nvme_tcp_teardown_admin_queue (ctrl, shutdown); }
drivers/nvme/target/loop.c +1 -1
@@ -401,7 +401,7 @@ static void nvme_loop_shutdown_ctrl(struct nvme_loop_ctrl *ctrl)nvme_stop_admin_queue (&ctrl->ctrl);if (ctrl->ctrl.state ==NVME_CTRL_LIVE ) -nvme_shutdown_ctrl (&ctrl->ctrl); +nvme_disable_ctrl (&ctrl->ctrl, true);nvme_cancel_admin_tagset (&ctrl->ctrl);nvme_loop_destroy_admin_queue (ctrl);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 5/5 nvme-pci: disable controller on admin queue IRQ setup failure
In reply to Sasha LevinFrom: Myeonghun Pak <[email protected]>
[ Upstream commit 08660a5c8d497f43191635d97efd31cd35051f15 ]
nvme_pci_configure_admin_queue() enables the controller and then requests the admin queue interrupt. If queue_request_irq() fails it returns without disabling the controller, and no caller compensates: nvme_pci_enable() only frees the IRQ vectors and calls pci_disable_device(), after which nvme_dev_disable() treats the controller as dead and skips nvme_disable_ctrl(). The controller is left enabled (CC.EN set) on this error path.
Disable it in the failure path, while the PCI device is still enabled so the CC.EN clear handshake completes.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
--- drivers/nvme/host/pci.c | 1 + 1 file changed, 1 insertion(+)
drivers/nvme/host/pci.c +1 -0
@@ -1895,6 +1895,7 @@ static int nvme_pci_configure_admin_queue(struct nvme_dev *dev) result =queue_request_irq (nvmeq);if (result) { dev->online_queues--; +nvme_disable_ctrl (&dev->ctrl, false);return result; }
Signature · 1 line
2.53.0