Skip to content

Commit 8d6c074

Browse files
committed
nvme: Introduce longer timeouts for admin queue
KIOXIA CD8 SSDs routinely take ~25 seconds to delete non-empty namespace. In some cases like hot-plug it takes longer, triggering timeout and controller resets after just 30 seconds. Linux for many years has separate 60 seconds timeout for admin queue. This patch does the same. And it is good to be consistent. Sponsored by: iXsystems, Inc. Reviewed by: imp MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D42454
1 parent 733a668 commit 8d6c074

File tree

4 files changed

+20
-5
lines changed

4 files changed

+20
-5
lines changed

sys/dev/nvme/nvme_ctrlr.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,12 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
14051405
to = NVME_CAP_LO_TO(cap_lo) + 1;
14061406
ctrlr->ready_timeout_in_ms = to * 500;
14071407

1408+
timeout_period = NVME_ADMIN_TIMEOUT_PERIOD;
1409+
TUNABLE_INT_FETCH("hw.nvme.admin_timeout_period", &timeout_period);
1410+
timeout_period = min(timeout_period, NVME_MAX_TIMEOUT_PERIOD);
1411+
timeout_period = max(timeout_period, NVME_MIN_TIMEOUT_PERIOD);
1412+
ctrlr->admin_timeout_period = timeout_period;
1413+
14081414
timeout_period = NVME_DEFAULT_TIMEOUT_PERIOD;
14091415
TUNABLE_INT_FETCH("hw.nvme.timeout_period", &timeout_period);
14101416
timeout_period = min(timeout_period, NVME_MAX_TIMEOUT_PERIOD);

sys/dev/nvme/nvme_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ MALLOC_DECLARE(M_NVME);
8686
#define NVME_MAX_CONSUMERS (2)
8787
#define NVME_MAX_ASYNC_EVENTS (8)
8888

89+
#define NVME_ADMIN_TIMEOUT_PERIOD (60) /* in seconds */
8990
#define NVME_DEFAULT_TIMEOUT_PERIOD (30) /* in seconds */
9091
#define NVME_MIN_TIMEOUT_PERIOD (5)
9192
#define NVME_MAX_TIMEOUT_PERIOD (120)
@@ -279,6 +280,7 @@ struct nvme_controller {
279280
uint32_t int_coal_threshold;
280281

281282
/** timeout period in seconds */
283+
uint32_t admin_timeout_period;
282284
uint32_t timeout_period;
283285

284286
/** doorbell stride */

sys/dev/nvme/nvme_qpair.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,8 @@ nvme_qpair_submit_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr)
11811181
if (req->timeout) {
11821182
if (req->cb_fn == nvme_completion_poll_cb)
11831183
timeout = 1;
1184+
else if (qpair->id == 0)
1185+
timeout = ctrlr->admin_timeout_period;
11841186
else
11851187
timeout = ctrlr->timeout_period;
11861188
tr->deadline = getsbinuptime() + timeout * SBT_1S;

sys/dev/nvme/nvme_sysctl.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ nvme_sysctl_int_coal_threshold(SYSCTL_HANDLER_ARGS)
132132
static int
133133
nvme_sysctl_timeout_period(SYSCTL_HANDLER_ARGS)
134134
{
135-
struct nvme_controller *ctrlr = arg1;
136-
uint32_t newval = ctrlr->timeout_period;
135+
uint32_t *ptr = arg1;
136+
uint32_t newval = *ptr;
137137
int error = sysctl_handle_int(oidp, &newval, 0, req);
138138

139139
if (error || (req->newptr == NULL))
@@ -143,7 +143,7 @@ nvme_sysctl_timeout_period(SYSCTL_HANDLER_ARGS)
143143
newval < NVME_MIN_TIMEOUT_PERIOD) {
144144
return (EINVAL);
145145
} else {
146-
ctrlr->timeout_period = newval;
146+
*ptr = newval;
147147
}
148148

149149
return (0);
@@ -352,10 +352,15 @@ nvme_sysctl_initialize_ctrlr(struct nvme_controller *ctrlr)
352352
nvme_sysctl_int_coal_threshold, "IU",
353353
"Interrupt coalescing threshold");
354354

355+
SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO,
356+
"admin_timeout_period", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
357+
&ctrlr->admin_timeout_period, 0, nvme_sysctl_timeout_period, "IU",
358+
"Timeout period for Admin queue (in seconds)");
359+
355360
SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO,
356361
"timeout_period", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
357-
ctrlr, 0, nvme_sysctl_timeout_period, "IU",
358-
"Timeout period (in seconds)");
362+
&ctrlr->timeout_period, 0, nvme_sysctl_timeout_period, "IU",
363+
"Timeout period for I/O queues (in seconds)");
359364

360365
SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO,
361366
"num_cmds", CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,

0 commit comments

Comments
 (0)