Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea191d2f authored by Keith Busch's avatar Keith Busch Committed by Jens Axboe
Browse files

NVMe: Reference count admin queue usage



Since there is no gendisk associated with the admin queue, the driver
needs to hold a reference to it until all open references to the
controller are closed.

This also combines queue cleanup with freeing the tag set since these
should not be separate.

Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent c917dfe5
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -1369,6 +1369,14 @@ static struct blk_mq_ops nvme_mq_ops = {
	.timeout	= nvme_timeout,
};

static void nvme_dev_remove_admin(struct nvme_dev *dev)
{
	if (dev->admin_q && !blk_queue_dying(dev->admin_q)) {
		blk_cleanup_queue(dev->admin_q);
		blk_mq_free_tag_set(&dev->admin_tagset);
	}
}

static int nvme_alloc_admin_tags(struct nvme_dev *dev)
{
	if (!dev->admin_q) {
@@ -1388,15 +1396,13 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev)
			blk_mq_free_tag_set(&dev->admin_tagset);
			return -ENOMEM;
		}
		if (!blk_get_queue(dev->admin_q)) {
			nvme_dev_remove_admin(dev);
			return -ENODEV;
		}

	return 0;
	}

static void nvme_free_admin_tags(struct nvme_dev *dev)
{
	if (dev->admin_q)
		blk_mq_free_tag_set(&dev->admin_tagset);
	return 0;
}

static int nvme_configure_admin_queue(struct nvme_dev *dev)
@@ -1465,7 +1471,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
	return result;

 free_tags:
	nvme_free_admin_tags(dev);
	nvme_dev_remove_admin(dev);
 free_nvmeq:
	nvme_free_queues(dev, 0);
	return result;
@@ -2415,12 +2421,6 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
	nvme_dev_unmap(dev);
}

static void nvme_dev_remove_admin(struct nvme_dev *dev)
{
	if (dev->admin_q && !blk_queue_dying(dev->admin_q))
		blk_cleanup_queue(dev->admin_q);
}

static void nvme_dev_remove(struct nvme_dev *dev)
{
	struct nvme_ns *ns;
@@ -2510,6 +2510,7 @@ static void nvme_free_dev(struct kref *kref)
	nvme_free_namespaces(dev);
	nvme_release_instance(dev);
	blk_mq_free_tag_set(&dev->tagset);
	blk_put_queue(dev->admin_q);
	kfree(dev->queues);
	kfree(dev->entry);
	kfree(dev);
@@ -2795,7 +2796,6 @@ static void nvme_remove(struct pci_dev *pdev)
	nvme_dev_shutdown(dev);
	nvme_dev_remove_admin(dev);
	nvme_free_queues(dev, 0);
	nvme_free_admin_tags(dev);
	nvme_release_prp_pools(dev);
	kref_put(&dev->kref, nvme_free_dev);
}