nvme: sanitize KATO setting
authorHannes Reinecke <hare@suse.de>
Fri, 16 Apr 2021 11:46:20 +0000 (13:46 +0200)
committerChristoph Hellwig <hch@lst.de>
Wed, 21 Apr 2021 17:13:15 +0000 (19:13 +0200)
According to the NVMe base spec the KATO commands should be sent
at half of the KATO interval, to properly account for round-trip
times.
As we now will only ever send one KATO command per connection we
can easily use the recommended values.
This also fixes a potential issue where the request timeout for
the KATO command does not match the value in the connect command,
which might be causing spurious connection drops from the target.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/nvme/host/core.c
drivers/nvme/host/fabrics.c
drivers/nvme/host/nvme.h

index 40f08e6..0cb097c 100644 (file)
@@ -1109,6 +1109,17 @@ void nvme_execute_passthru_rq(struct request *rq)
 }
 EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU);
 
+/*
+ * Recommended frequency for KATO commands per NVMe 1.4 section 7.12.1:
+ * 
+ *   The host should send Keep Alive commands at half of the Keep Alive Timeout
+ *   accounting for transport roundtrip times [..].
+ */
+static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
+{
+       queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+}
+
 static void nvme_keep_alive_end_io(struct request *rq, blk_status_t status)
 {
        struct nvme_ctrl *ctrl = rq->end_io_data;
@@ -1131,7 +1142,7 @@ static void nvme_keep_alive_end_io(struct request *rq, blk_status_t status)
                startka = true;
        spin_unlock_irqrestore(&ctrl->lock, flags);
        if (startka)
-               queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ);
+               nvme_queue_keep_alive_work(ctrl);
 }
 
 static int nvme_keep_alive(struct nvme_ctrl *ctrl)
@@ -1161,7 +1172,7 @@ static void nvme_keep_alive_work(struct work_struct *work)
                dev_dbg(ctrl->device,
                        "reschedule traffic based keep-alive timer\n");
                ctrl->comp_seen = false;
-               queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ);
+               nvme_queue_keep_alive_work(ctrl);
                return;
        }
 
@@ -1178,7 +1189,7 @@ static void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
        if (unlikely(ctrl->kato == 0))
                return;
 
-       queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ);
+       nvme_queue_keep_alive_work(ctrl);
 }
 
 void nvme_stop_keep_alive(struct nvme_ctrl *ctrl)
index 604ab0e..13c2747 100644 (file)
@@ -379,10 +379,8 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
 
        /*
         * Set keep-alive timeout in seconds granularity (ms * 1000)
-        * and add a grace period for controller kato enforcement
         */
-       cmd.connect.kato = ctrl->kato ?
-               cpu_to_le32((ctrl->kato + NVME_KATO_GRACE) * 1000) : 0;
+       cmd.connect.kato = cpu_to_le32(ctrl->kato * 1000);
 
        if (ctrl->opts->disable_sqflow)
                cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
index c6102ce..4927618 100644 (file)
@@ -27,7 +27,6 @@ extern unsigned int admin_timeout;
 #define NVME_ADMIN_TIMEOUT     (admin_timeout * HZ)
 
 #define NVME_DEFAULT_KATO      5
-#define NVME_KATO_GRACE                10
 
 #ifdef CONFIG_ARCH_NO_SG_CHAIN
 #define  NVME_INLINE_SG_CNT  0