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);
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to