Hannes Reinecke 28b2dc
From: Keith Busch <kbusch@kernel.org>
Hannes Reinecke 28b2dc
Date: Thu, 5 Sep 2019 07:52:33 -0600
Hannes Reinecke 28b2dc
Subject: [PATCH] nvme-pci: Free tagset if no IO queues
Hannes Reinecke 28b2dc
Git-commit: 770597ecb2075390c01c425b8b1f551347f1bd70
Hannes Reinecke 28b2dc
Patch-mainline: v5.4-rc4
Hannes Reinecke 28b2dc
References: bsc#1169045
Hannes Reinecke 28b2dc
Hannes Reinecke 28b2dc
If a controller becomes degraded after a reset, we will not be able to
Hannes Reinecke 28b2dc
perform any IO. We currently teardown previously created request
Hannes Reinecke 28b2dc
queues and namespaces, but we had kept the unusable tagset. Free
Hannes Reinecke 28b2dc
it after all queues using it have been released.
Hannes Reinecke 28b2dc
Hannes Reinecke 28b2dc
Tested-by: Edmund Nadolski <edmund.nadolski@intel.com>
Hannes Reinecke 28b2dc
Reviewed-by: James Smart <james.smart@broadcom.com>
Hannes Reinecke 28b2dc
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Hannes Reinecke 28b2dc
Reviewed-by: Christoph Hellwig <hch@lst.de>
Hannes Reinecke 28b2dc
Signed-off-by: Keith Busch <kbusch@kernel.org>
Hannes Reinecke 28b2dc
Acked-by: Hannes Reinecke <hare@suse.com>
Hannes Reinecke 28b2dc
---
Hannes Reinecke 28b2dc
 drivers/nvme/host/pci.c | 11 +++++++++--
Hannes Reinecke 28b2dc
 1 file changed, 9 insertions(+), 2 deletions(-)
Hannes Reinecke 28b2dc
Hannes Reinecke 28b2dc
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
Hannes Reinecke 28b2dc
index 78e403823646..5c04581899f4 100644
Hannes Reinecke 28b2dc
--- a/drivers/nvme/host/pci.c
Hannes Reinecke 28b2dc
+++ b/drivers/nvme/host/pci.c
Hannes Reinecke 28b2dc
@@ -2490,14 +2490,20 @@ static void nvme_release_prp_pools(struct nvme_dev *dev)
Hannes Reinecke 28b2dc
 	dma_pool_destroy(dev->prp_small_pool);
Hannes Reinecke 28b2dc
 }
Hannes Reinecke 28b2dc
 
Hannes Reinecke 28b2dc
+static void nvme_free_tagset(struct nvme_dev *dev)
Hannes Reinecke 28b2dc
+{
Hannes Reinecke 28b2dc
+	if (dev->tagset.tags)
Hannes Reinecke 28b2dc
+		blk_mq_free_tag_set(&dev->tagset);
Hannes Reinecke 28b2dc
+	dev->ctrl.tagset = NULL;
Hannes Reinecke 28b2dc
+}
Hannes Reinecke 28b2dc
+
Hannes Reinecke 28b2dc
 static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl)
Hannes Reinecke 28b2dc
 {
Hannes Reinecke 28b2dc
 	struct nvme_dev *dev = to_nvme_dev(ctrl);
Hannes Reinecke 28b2dc
 
Hannes Reinecke 28b2dc
 	nvme_dbbuf_dma_free(dev);
Hannes Reinecke 28b2dc
 	put_device(dev->dev);
Hannes Reinecke 28b2dc
-	if (dev->tagset.tags)
Hannes Reinecke 28b2dc
-		blk_mq_free_tag_set(&dev->tagset);
Hannes Reinecke 28b2dc
+	nvme_free_tagset(dev);
Hannes Reinecke 28b2dc
 	if (dev->ctrl.admin_q)
Hannes Reinecke 28b2dc
 		blk_put_queue(dev->ctrl.admin_q);
Hannes Reinecke 28b2dc
 	kfree(dev->queues);
Hannes Reinecke 28b2dc
@@ -2616,6 +2622,7 @@ static void nvme_reset_work(struct work_struct *work)
Hannes Reinecke 28b2dc
 		nvme_kill_queues(&dev->ctrl);
Hannes Reinecke 28b2dc
 		nvme_remove_namespaces(&dev->ctrl);
Hannes Reinecke 28b2dc
 		new_state = NVME_CTRL_ADMIN_ONLY;
Hannes Reinecke 28b2dc
+		nvme_free_tagset(dev);
Hannes Reinecke 28b2dc
 	} else {
Hannes Reinecke 28b2dc
 		nvme_start_queues(&dev->ctrl);
Hannes Reinecke 28b2dc
 		nvme_wait_freeze(&dev->ctrl);
Hannes Reinecke 28b2dc
-- 
Hannes Reinecke 28b2dc
2.16.4
Hannes Reinecke 28b2dc