summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjimharris <jimharris@FreeBSD.org>2013-03-26 20:02:35 +0000
committerjimharris <jimharris@FreeBSD.org>2013-03-26 20:02:35 +0000
commit83032bc2394df6e15ddb874995f794f0c8c660b1 (patch)
tree5ebc789383fbca5abbead81ca4e0081cc57c742d
parent711dabaf432762eec4942b5f5f7611e7df825260 (diff)
downloadFreeBSD-src-83032bc2394df6e15ddb874995f794f0c8c660b1.zip
FreeBSD-src-83032bc2394df6e15ddb874995f794f0c8c660b1.tar.gz
Add a tunable for the I/O timeout interval. Default is still 30 seconds,
but can be adjusted between a min/max of 5 and 120 seconds. Sponsored by: Intel Reviewed by: carl
-rw-r--r--sys/dev/nvme/nvme_ctrlr.c13
-rw-r--r--sys/dev/nvme/nvme_private.h13
-rw-r--r--sys/dev/nvme/nvme_qpair.c11
-rw-r--r--sys/dev/nvme/nvme_sysctl.c24
4 files changed, 50 insertions, 11 deletions
diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index f759a60..6328134 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -592,10 +592,10 @@ nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr,
aer->req = req;
/*
- * Override default timeout value here, since asynchronous event
- * requests should by nature never be timed out.
+ * Disable timeout here, since asynchronous event requests should by
+ * nature never be timed out.
*/
- req->timeout = 0;
+ req->timeout = FALSE;
req->cmd.opc = NVME_OPC_ASYNC_EVENT_REQUEST;
nvme_ctrlr_submit_admin_request(ctrlr, req);
}
@@ -791,6 +791,7 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
union cap_lo_register cap_lo;
union cap_hi_register cap_hi;
int num_vectors, per_cpu_io_queues, status = 0;
+ int timeout_period;
ctrlr->dev = dev;
ctrlr->is_started = FALSE;
@@ -822,6 +823,12 @@ nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev)
cap_lo.raw = nvme_mmio_read_4(ctrlr, cap_lo);
ctrlr->ready_timeout_in_ms = cap_lo.bits.to * 500;
+ timeout_period = NVME_DEFAULT_TIMEOUT_PERIOD;
+ TUNABLE_INT_FETCH("hw.nvme.timeout_period", &timeout_period);
+ timeout_period = min(timeout_period, NVME_MAX_TIMEOUT_PERIOD);
+ timeout_period = max(timeout_period, NVME_MIN_TIMEOUT_PERIOD);
+ ctrlr->timeout_period = timeout_period;
+
per_cpu_io_queues = 1;
TUNABLE_INT_FETCH("hw.nvme.per_cpu_io_queues", &per_cpu_io_queues);
ctrlr->per_cpu_io_queues = per_cpu_io_queues ? TRUE : FALSE;
diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h
index 2fde631..8921710 100644
--- a/sys/dev/nvme/nvme_private.h
+++ b/sys/dev/nvme/nvme_private.h
@@ -100,7 +100,9 @@ MALLOC_DECLARE(M_NVME);
#define NVME_MAX_CONSUMERS (2)
#define NVME_MAX_ASYNC_EVENTS (8)
-#define NVME_TIMEOUT_IN_SEC (30)
+#define NVME_DEFAULT_TIMEOUT_PERIOD (30) /* in seconds */
+#define NVME_MIN_TIMEOUT_PERIOD (5)
+#define NVME_MAX_TIMEOUT_PERIOD (120)
#ifndef CACHE_LINE_SIZE
#define CACHE_LINE_SIZE (64)
@@ -113,7 +115,7 @@ struct nvme_request {
struct nvme_command cmd;
void *payload;
uint32_t payload_size;
- uint32_t timeout;
+ boolean_t timeout;
struct uio *uio;
nvme_cb_fn_t cb_fn;
void *cb_arg;
@@ -257,6 +259,9 @@ struct nvme_controller {
/** interrupt coalescing threshold */
uint32_t int_coal_threshold;
+ /** timeout period in seconds */
+ uint32_t timeout_period;
+
struct nvme_qpair adminq;
struct nvme_qpair *ioq;
@@ -427,7 +432,7 @@ nvme_allocate_request(void *payload, uint32_t payload_size, nvme_cb_fn_t cb_fn,
req->payload_size = payload_size;
req->cb_fn = cb_fn;
req->cb_arg = cb_arg;
- req->timeout = NVME_TIMEOUT_IN_SEC;
+ req->timeout = TRUE;
return (req);
}
@@ -444,7 +449,7 @@ nvme_allocate_request_uio(struct uio *uio, nvme_cb_fn_t cb_fn, void *cb_arg)
req->uio = uio;
req->cb_fn = cb_fn;
req->cb_arg = cb_arg;
- req->timeout = NVME_TIMEOUT_IN_SEC;
+ req->timeout = TRUE;
return (req);
}
diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c
index db9abf2..9783db9 100644
--- a/sys/dev/nvme/nvme_qpair.c
+++ b/sys/dev/nvme/nvme_qpair.c
@@ -480,20 +480,23 @@ nvme_timeout(void *arg)
void
nvme_qpair_submit_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr)
{
- struct nvme_request *req;
+ struct nvme_request *req;
+ struct nvme_controller *ctrlr;
mtx_assert(&qpair->lock, MA_OWNED);
req = tr->req;
req->cmd.cid = tr->cid;
qpair->act_tr[tr->cid] = tr;
+ ctrlr = qpair->ctrlr;
- if (req->timeout > 0)
+ if (req->timeout)
#if __FreeBSD_version >= 800030
- callout_reset_curcpu(&tr->timer, req->timeout * hz,
+ callout_reset_curcpu(&tr->timer, ctrlr->timeout_period * hz,
nvme_timeout, tr);
#else
- callout_reset(&tr->timer, req->timeout * hz, nvme_timeout, tr);
+ callout_reset(&tr->timer, ctrlr->timeout_period * hz,
+ nvme_timeout, tr);
#endif
/* Copy the command from the tracker to the submission queue. */
diff --git a/sys/dev/nvme/nvme_sysctl.c b/sys/dev/nvme/nvme_sysctl.c
index 85187af..6e0aa0c 100644
--- a/sys/dev/nvme/nvme_sysctl.c
+++ b/sys/dev/nvme/nvme_sysctl.c
@@ -123,6 +123,25 @@ nvme_sysctl_int_coal_threshold(SYSCTL_HANDLER_ARGS)
return (0);
}
+static int
+nvme_sysctl_timeout_period(SYSCTL_HANDLER_ARGS)
+{
+ struct nvme_controller *ctrlr = arg1;
+ uint32_t oldval = ctrlr->timeout_period;
+ int error = sysctl_handle_int(oidp, &ctrlr->timeout_period, 0, req);
+
+ if (error)
+ return (error);
+
+ if (ctrlr->timeout_period > NVME_MAX_TIMEOUT_PERIOD ||
+ ctrlr->timeout_period < NVME_MIN_TIMEOUT_PERIOD) {
+ ctrlr->timeout_period = oldval;
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
static void
nvme_qpair_reset_stats(struct nvme_qpair *qpair)
{
@@ -244,6 +263,11 @@ nvme_sysctl_initialize_ctrlr(struct nvme_controller *ctrlr)
"Interrupt coalescing threshold");
SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO,
+ "timeout_period", CTLTYPE_UINT | CTLFLAG_RW, ctrlr, 0,
+ nvme_sysctl_timeout_period, "IU",
+ "Timeout period (in seconds)");
+
+ SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO,
"num_cmds", CTLTYPE_S64 | CTLFLAG_RD,
ctrlr, 0, nvme_sysctl_num_cmds, "IU",
"Number of commands submitted");
OpenPOWER on IntegriCloud