nvme - Do a better job backing out of probe errors
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 11 Jul 2018 18:45:38 +0000 (11:45 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 11 Jul 2018 18:45:38 +0000 (11:45 -0700)
* AWS provides nvme interfaces which might not have attached volumes.
  Improve stability on AWS nvme (still needs more work).  Play nice
  when queue creation fails.  Do a better job tracking MSI-X
  interrupt installation and removal.

sys/dev/disk/nvme/nvme.c
sys/dev/disk/nvme/nvme_admin.c

index f909372..c4e4693 100644 (file)
@@ -844,6 +844,19 @@ nvme_create_comqueue(nvme_softc_t *sc, uint16_t qid)
        status = nvme_wait_request(req);
        nvme_put_request(req);
 
+       /*
+        * Ooops, create failed, undo the irq setup
+        */
+       if (sc->nirqs > 1 && status) {
+               ivect = 1 + (qid - 1) % (sc->nirqs - 1);
+               if (qid && ivect == qid) {
+                       bus_teardown_intr(sc->dev,
+                                         sc->irq[ivect],
+                                         sc->irq_handle[ivect]);
+                       sc->irq_handle[ivect] = NULL;
+               }
+       }
+
        return status;
 }
 
@@ -875,10 +888,13 @@ int
 nvme_delete_comqueue(nvme_softc_t *sc, uint16_t qid)
 {
        nvme_request_t *req;
-       /*nvme_comqueue_t *comq = &sc->comqueues[qid];*/
+       nvme_comqueue_t *comq = &sc->comqueues[qid];
        int status;
        uint16_t ivect;
 
+       if (comq->sc == NULL)
+               return 0;
+
        req = nvme_get_admin_request(sc, NVME_OP_DELETE_COMQ);
        req->cmd.head.prp1 = 0;
        req->cmd.delete.qid = qid;
@@ -889,10 +905,11 @@ nvme_delete_comqueue(nvme_softc_t *sc, uint16_t qid)
 
        if (qid && sc->nirqs > 1) {
                ivect = 1 + (qid - 1) % (sc->nirqs - 1);
-               if (ivect == qid) {
+               if (ivect == qid && sc->irq_handle[ivect]) {
                        bus_teardown_intr(sc->dev,
                                          sc->irq[ivect],
                                          sc->irq_handle[ivect]);
+                       sc->irq_handle[ivect] = NULL;
                }
        }
 
index 35870d4..6ddae04 100644 (file)
@@ -457,6 +457,11 @@ nvme_admin_state_make_queues(nvme_softc_t *sc)
                        break;
                }
                error += nvme_create_comqueue(sc, i);
+               if (error) {
+                       nvme_delete_comqueue(sc, i);
+                       nvme_free_comqueue(sc, i);
+                       break;
+               }
        }
        for (i = 1; i <= sc->niosubqs; ++i) {
                error += nvme_alloc_subqueue(sc, i);
@@ -465,6 +470,11 @@ nvme_admin_state_make_queues(nvme_softc_t *sc)
                        break;
                }
                error += nvme_create_subqueue(sc, i);
+               if (error) {
+                       nvme_delete_subqueue(sc, i);
+                       nvme_free_subqueue(sc, i);
+                       break;
+               }
        }
 
        if (error) {