]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
nvme: add sysfs attribute to change admin timeout per nvme controller
authorMaurizio Lombardi <mlombard@redhat.com>
Thu, 14 May 2026 08:32:51 +0000 (10:32 +0200)
committerKeith Busch <kbusch@kernel.org>
Wed, 20 May 2026 18:45:44 +0000 (11:45 -0700)
Currently, there is no method to adjust the timeout values on a
per-controller basis with nvme admin queues.
Add an admin_timeout attribute to nvme so that different nvme controllers
which may have different timeout requirements can have custom admin
timeouts set.

The admin timeout is also applied to the fabrics queue (fabrics_q).
The fabrics queue is utilized for fabric-specific administrative and
control operations, such as Connect and Property Get/Set commands.

Reviewed-by: Daniel Wagner <dwagner@suse.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Reviewed-by: Mohamed Khalfella <mkhalfella@purestorage.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/sysfs.c

index f9fe7bb65ec6ed4f1b86f76c91d094a9d51b14e1..20df7c12c718042e1c0af76e2e2ed13487343b3d 100644 (file)
@@ -5140,6 +5140,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
        memset(&ctrl->ka_cmd, 0, sizeof(ctrl->ka_cmd));
        ctrl->ka_cmd.common.opcode = nvme_admin_keep_alive;
        ctrl->ka_last_check_time = jiffies;
+       ctrl->admin_timeout = NVME_ADMIN_TIMEOUT;
 
        BUILD_BUG_ON(NVME_DSM_MAX_RANGES * sizeof(struct nvme_dsm_range) >
                        PAGE_SIZE);
index 6f9ecb4948f4b948ce47cd1e921a1794b5562b60..7923533cce00a78efbb849e6a64cb010a983f25a 100644 (file)
@@ -370,6 +370,7 @@ struct nvme_ctrl {
        u16 mtfa;
        u32 ctrl_config;
        u32 queue_count;
+       u32 admin_timeout;
 
        u64 cap;
        u32 max_hw_sectors;
index 2dc1074f99844d68a58895bf85df8d3201a93ab5..35affda088f4cfd23b8ebf8d005681b44bbbd8bb 100644 (file)
@@ -3094,7 +3094,7 @@ static bool __nvme_delete_io_queues(struct nvme_dev *dev, u8 opcode)
        unsigned long timeout;
 
  retry:
-       timeout = NVME_ADMIN_TIMEOUT;
+       timeout = dev->ctrl.admin_timeout;
        while (nr_queues > 0) {
                if (nvme_delete_queue(&dev->queues[nr_queues], opcode))
                        break;
index e59758616f277e709804c72a27c2227ce6fba2d7..3b39b64cd9daf60b9cdad391ccaa237ae5366edd 100644 (file)
@@ -623,6 +623,46 @@ static ssize_t quirks_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RO(quirks);
 
+static ssize_t nvme_admin_timeout_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+
+       return sysfs_emit(buf, "%u\n",
+                               jiffies_to_msecs(ctrl->admin_timeout));
+}
+
+static ssize_t nvme_admin_timeout_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+       u32 timeout;
+       int err;
+
+       /*
+        * Wait until the controller reaches the LIVE state to be sure that
+        * admin_q and fabrics_q are properly initialized.
+        */
+       if (!test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags))
+               return -EBUSY;
+
+       err = kstrtou32(buf, 10, &timeout);
+       if (err || !timeout)
+               return -EINVAL;
+
+       ctrl->admin_timeout = msecs_to_jiffies(timeout);
+
+       blk_queue_rq_timeout(ctrl->admin_q, ctrl->admin_timeout);
+       if (ctrl->fabrics_q)
+               blk_queue_rq_timeout(ctrl->fabrics_q, ctrl->admin_timeout);
+
+       return count;
+}
+
+static DEVICE_ATTR(admin_timeout, S_IRUGO | S_IWUSR,
+       nvme_admin_timeout_show, nvme_admin_timeout_store);
+
 #ifdef CONFIG_NVME_HOST_AUTH
 static ssize_t nvme_ctrl_dhchap_secret_show(struct device *dev,
                struct device_attribute *attr, char *buf)
@@ -765,6 +805,7 @@ static struct attribute *nvme_dev_attrs[] = {
        &dev_attr_cntrltype.attr,
        &dev_attr_dctype.attr,
        &dev_attr_quirks.attr,
+       &dev_attr_admin_timeout.attr,
 #ifdef CONFIG_NVME_HOST_AUTH
        &dev_attr_dhchap_secret.attr,
        &dev_attr_dhchap_ctrl_secret.attr,