]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
nvme: properly handle partially initialized queues in nvme_create_io_queues
authorChristoph Hellwig <hch@lst.de>
Fri, 2 Oct 2015 16:51:31 +0000 (18:51 +0200)
committerChuck Anderson <chuck.anderson@oracle.com>
Wed, 6 Jul 2016 23:31:59 +0000 (16:31 -0700)
This avoids having to clean up later in a seemingly unrelated place.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
(cherry picked from commit 2659e57b906562bb020fb093b0c1b670b9700314)

Orabug: 22620486
Signed-off-by: Jason Luo <zhangqing.luo@oracle.com>
drivers/block/nvme-core.c

index 5190a7d3dcd0f2f2f41e28b023ae021c04110042..e728c57de2d16fa385087a5f6221f5477fcfaa4f 100644 (file)
@@ -2196,6 +2196,13 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid)
        kfree(ns);
 }
 
+/*
+ * Create I/O queues.  Failing to create an I/O queue is not an issue,
+ * we can continue with less than the desired amount of queues, and
+ * even a controller without I/O queues an still be used to issue
+ * admin commands.  This might be useful to upgrade a buggy firmware
+ * for example.
+ */
 static void nvme_create_io_queues(struct nvme_dev *dev)
 {
        unsigned i;
@@ -2205,8 +2212,10 @@ static void nvme_create_io_queues(struct nvme_dev *dev)
                        break;
 
        for (i = dev->online_queues; i <= dev->queue_count - 1; i++)
-               if (nvme_create_queue(dev->queues[i], i))
+               if (nvme_create_queue(dev->queues[i], i)) {
+                       nvme_free_queues(dev, i);
                        break;
+               }
 }
 
 static int set_queue_count(struct nvme_dev *dev, int count)
@@ -3012,9 +3021,12 @@ static void nvme_probe_work(struct work_struct *work)
 
        dev->event_limit = 1;
 
+       /*
+        * Keep the controller around but remove all namespaces if we don't have
+        * any working I/O queue.
+        */
        if (dev->online_queues < 2) {
                dev_warn(dev->dev, "IO queues not created\n");
-               nvme_free_queues(dev, 1);
                nvme_dev_remove(dev);
        } else {
                nvme_unfreeze_queues(dev);