Skip to content

Commit

Permalink
nvme: sanitize KATO setting
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hannes Reinecke authored and Christoph Hellwig committed Apr 21, 2021
1 parent 8f864c5 commit a70b81b
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 7 deletions.
17 changes: 14 additions & 3 deletions drivers/nvme/host/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}

Expand All @@ -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)
Expand Down
4 changes: 1 addition & 3 deletions drivers/nvme/host/fabrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion drivers/nvme/host/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a70b81b

Please sign in to comment.