nvme: support per-request timeouts

Allow different timeouts per command.

Reviewed by:		seuros, chuck
Differential Revision:	https://reviews.freebsd.org/D59828
This commit is contained in:
Warner Losh committed 2026-10-19 00:22:50 -06:00
1 parent 5258b44e84
commit 1c31ef40e1
3 files changed
+17 -10

No files matched your search

+1 -1
View File
@@ -795,7 +795,7 @@ nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr,
* Disable timeout here, since asynchronous event requests should by
* nature never be timed out.
*/
req->timeout = false;
req->timeout_ms = NVME_TIMEOUT_NONE;
req->cmd.opc = NVME_OPC_ASYNC_EVENT_REQUEST;
nvme_ctrlr_submit_admin_request(ctrlr, req);
}
+5 -3
View File
@@ -86,6 +86,9 @@ MALLOC_DECLARE(M_NVME);
#define NVME_MAX_TIMEOUT_PERIOD (120)
#define NVME_MAX_FORMAT_TIMEOUT_PERIOD (60 * 60)
#define NVME_TIMEOUT_DEFAULT 0U
#define NVME_TIMEOUT_NONE UINT32_MAX
#define NVME_DEFAULT_RETRY_COUNT (4)
/* Maximum log page size to fetch for AERs. */
@@ -115,12 +118,11 @@ struct nvme_request {
struct memdesc payload;
nvme_cb_fn_t cb_fn;
void *cb_arg;
uint32_t timeout_ms;
int16_t retries;
uint16_t ioq;
#define NVME_IOQ_DEFAULT 0xffff
bool payload_valid;
bool timeout;
bool spare[2]; /* Future use */
STAILQ_ENTRY(nvme_request) stailq;
};
@@ -544,7 +546,7 @@ _nvme_allocate_request(const int how, nvme_cb_fn_t cb_fn, void *cb_arg)
req->ioq = NVME_IOQ_DEFAULT;
req->cb_fn = cb_fn;
req->cb_arg = cb_arg;
req->timeout = true;
req->timeout_ms = NVME_TIMEOUT_DEFAULT;
}
return (req);
}
+11 -6
View File
@@ -1037,7 +1037,7 @@ nvme_qpair_submit_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr)
{
struct nvme_request *req;
struct nvme_controller *ctrlr;
int timeout;
uint32_t timeout_ms;
mtx_assert(&qpair->lock, MA_OWNED);
@@ -1045,14 +1045,19 @@ nvme_qpair_submit_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr)
qpair->act_tr[tr->cid] = tr;
ctrlr = qpair->ctrlr;
if (req->timeout) {
if (req->timeout_ms != NVME_TIMEOUT_NONE) {
if (req->cb_fn == nvme_completion_poll_cb)
timeout = 1;
timeout_ms = 1000;
else if (req->timeout_ms != NVME_TIMEOUT_DEFAULT)
timeout_ms = req->timeout_ms;
else if (qpair->id == 0 && req->cmd.opc == NVME_OPC_FORMAT_NVM)
timeout_ms = ctrlr->format_timeout_period * 1000;
else if (qpair->id == 0)
timeout = ctrlr->admin_timeout_period;
timeout_ms = ctrlr->admin_timeout_period * 1000;
else
timeout = ctrlr->timeout_period;
tr->deadline = getsbinuptime() + timeout * SBT_1S;
timeout_ms = ctrlr->timeout_period * 1000;
tr->deadline = getsbinuptime() +
(sbintime_t)timeout_ms * SBT_1MS;
if (!qpair->timer_armed) {
qpair->timer_armed = true;
callout_reset_sbt_on(&qpair->timer, SBT_1S / 2, SBT_1S / 2,