svn commit: r248761 - head/sys/dev/nvme
Jim Harris
jimharris at FreeBSD.org
Tue Mar 26 21:14:52 UTC 2013
Author: jimharris
Date: Tue Mar 26 21:14:51 2013
New Revision: 248761
URL: http://svnweb.freebsd.org/changeset/base/248761
Log:
Cap the number of retry attempts to a configurable number. This ensures
that if a specific I/O repeatedly times out, we don't retry it indefinitely.
The default number of retries will be 4, but is adjusted using hw.nvme.retry_count.
Sponsored by: Intel
Reviewed by: carl
Modified:
head/sys/dev/nvme/nvme.c
head/sys/dev/nvme/nvme_ctrlr.c
head/sys/dev/nvme/nvme_private.h
head/sys/dev/nvme/nvme_qpair.c
Modified: head/sys/dev/nvme/nvme.c
==============================================================================
--- head/sys/dev/nvme/nvme.c Tue Mar 26 21:08:32 2013 (r248760)
+++ head/sys/dev/nvme/nvme.c Tue Mar 26 21:14:51 2013 (r248761)
@@ -49,7 +49,8 @@ struct nvme_consumer {
struct nvme_consumer nvme_consumer[NVME_MAX_CONSUMERS];
#define INVALID_CONSUMER_ID 0xFFFF
-uma_zone_t nvme_request_zone;
+uma_zone_t nvme_request_zone;
+int32_t nvme_retry_count;
MALLOC_DEFINE(M_NVME, "nvme", "nvme(4) memory allocations");
Modified: head/sys/dev/nvme/nvme_ctrlr.c
==============================================================================
--- head/sys/dev/nvme/nvme_ctrlr.c Tue Mar 26 21:08:32 2013 (r248760)
+++ head/sys/dev/nvme/nvme_ctrlr.c Tue Mar 26 21:14:51 2013 (r248761)
@@ -731,6 +731,10 @@ nvme_ctrlr_start(void *ctrlr_arg)
struct nvme_controller *ctrlr = ctrlr_arg;
int i;
+ nvme_qpair_reset(&ctrlr->adminq);
+ for (i = 0; i < ctrlr->num_io_queues; i++)
+ nvme_qpair_reset(&ctrlr->ioq[i]);
+
nvme_admin_qpair_enable(&ctrlr->adminq);
if (nvme_ctrlr_identify(ctrlr) != 0)
@@ -929,6 +933,9 @@ nvme_ctrlr_construct(struct nvme_control
timeout_period = max(timeout_period, NVME_MIN_TIMEOUT_PERIOD);
ctrlr->timeout_period = timeout_period;
+ nvme_retry_count = NVME_DEFAULT_RETRY_COUNT;
+ TUNABLE_INT_FETCH("hw.nvme.retry_count", &nvme_retry_count);
+
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;
Modified: head/sys/dev/nvme/nvme_private.h
==============================================================================
--- head/sys/dev/nvme/nvme_private.h Tue Mar 26 21:08:32 2013 (r248760)
+++ head/sys/dev/nvme/nvme_private.h Tue Mar 26 21:14:51 2013 (r248761)
@@ -104,6 +104,8 @@ MALLOC_DECLARE(M_NVME);
#define NVME_MIN_TIMEOUT_PERIOD (5)
#define NVME_MAX_TIMEOUT_PERIOD (120)
+#define NVME_DEFAULT_RETRY_COUNT (4)
+
/* Maximum log page size to fetch for AERs. */
#define NVME_MAX_AER_LOG_SIZE (4096)
@@ -111,7 +113,8 @@ MALLOC_DECLARE(M_NVME);
#define CACHE_LINE_SIZE (64)
#endif
-extern uma_zone_t nvme_request_zone;
+extern uma_zone_t nvme_request_zone;
+extern int32_t nvme_retry_count;
struct nvme_request {
@@ -122,6 +125,7 @@ struct nvme_request {
struct uio *uio;
nvme_cb_fn_t cb_fn;
void *cb_arg;
+ int32_t retries;
STAILQ_ENTRY(nvme_request) stailq;
};
@@ -409,6 +413,7 @@ void nvme_qpair_submit_tracker(struct nv
void nvme_qpair_process_completions(struct nvme_qpair *qpair);
void nvme_qpair_submit_request(struct nvme_qpair *qpair,
struct nvme_request *req);
+void nvme_qpair_reset(struct nvme_qpair *qpair);
void nvme_admin_qpair_enable(struct nvme_qpair *qpair);
void nvme_admin_qpair_disable(struct nvme_qpair *qpair);
Modified: head/sys/dev/nvme/nvme_qpair.c
==============================================================================
--- head/sys/dev/nvme/nvme_qpair.c Tue Mar 26 21:08:32 2013 (r248760)
+++ head/sys/dev/nvme/nvme_qpair.c Tue Mar 26 21:14:51 2013 (r248761)
@@ -105,7 +105,8 @@ nvme_qpair_complete_tracker(struct nvme_
req = tr->req;
error = nvme_completion_is_error(cpl);
- retry = error && nvme_completion_is_retry(cpl);
+ retry = error && nvme_completion_is_retry(cpl) &&
+ req->retries < nvme_retry_count;
if (error && print_on_error) {
nvme_dump_completion(cpl);
@@ -122,9 +123,10 @@ nvme_qpair_complete_tracker(struct nvme_
mtx_lock(&qpair->lock);
callout_stop(&tr->timer);
- if (retry)
+ if (retry) {
+ req->retries++;
nvme_qpair_submit_tracker(qpair, tr);
- else {
+ } else {
if (req->payload_size > 0 || req->uio != NULL)
bus_dmamap_unload(qpair->dma_tag,
tr->payload_dma_map);
@@ -568,6 +570,12 @@ nvme_qpair_enable(struct nvme_qpair *qpa
{
qpair->is_enabled = TRUE;
+}
+
+void
+nvme_qpair_reset(struct nvme_qpair *qpair)
+{
+
qpair->sq_head = qpair->sq_tail = qpair->cq_head = 0;
/*
@@ -597,19 +605,25 @@ nvme_io_qpair_enable(struct nvme_qpair *
{
STAILQ_HEAD(, nvme_request) temp;
struct nvme_tracker *tr;
+ struct nvme_tracker *tr_temp;
struct nvme_request *req;
+ /*
+ * Manually abort each outstanding I/O. This normally results in a
+ * retry, unless the retry count on the associated request has
+ * reached its limit.
+ */
+ TAILQ_FOREACH_SAFE(tr, &qpair->outstanding_tr, tailq, tr_temp) {
+ device_printf(qpair->ctrlr->dev,
+ "aborting outstanding i/o\n");
+ nvme_qpair_manual_complete_tracker(qpair, tr, NVME_SCT_GENERIC,
+ NVME_SC_ABORTED_BY_REQUEST, TRUE);
+ }
+
mtx_lock(&qpair->lock);
nvme_qpair_enable(qpair);
- TAILQ_FOREACH(tr, &qpair->outstanding_tr, tailq) {
- device_printf(qpair->ctrlr->dev,
- "resubmitting outstanding i/o\n");
- nvme_dump_command(&tr->req->cmd);
- nvme_qpair_submit_tracker(qpair, tr);
- }
-
STAILQ_INIT(&temp);
STAILQ_SWAP(&qpair->queued_req, &temp, nvme_request);
More information about the svn-src-all
mailing list