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

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
...@@ -1369,6 +1369,14 @@ static struct blk_mq_ops nvme_mq_ops = { ...@@ -1369,6 +1369,14 @@ static struct blk_mq_ops nvme_mq_ops = {
.timeout = nvme_timeout, .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) static int nvme_alloc_admin_tags(struct nvme_dev *dev)
{ {
if (!dev->admin_q) { if (!dev->admin_q) {
...@@ -1388,17 +1396,15 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev) ...@@ -1388,17 +1396,15 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev)
blk_mq_free_tag_set(&dev->admin_tagset); blk_mq_free_tag_set(&dev->admin_tagset);
return -ENOMEM; return -ENOMEM;
} }
if (!blk_get_queue(dev->admin_q)) {
nvme_dev_remove_admin(dev);
return -ENODEV;
}
} }
return 0; return 0;
} }
static void nvme_free_admin_tags(struct nvme_dev *dev)
{
if (dev->admin_q)
blk_mq_free_tag_set(&dev->admin_tagset);
}
static int nvme_configure_admin_queue(struct nvme_dev *dev) static int nvme_configure_admin_queue(struct nvme_dev *dev)
{ {
int result; int result;
...@@ -1465,7 +1471,7 @@ 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; return result;
free_tags: free_tags:
nvme_free_admin_tags(dev); nvme_dev_remove_admin(dev);
free_nvmeq: free_nvmeq:
nvme_free_queues(dev, 0); nvme_free_queues(dev, 0);
return result; return result;
...@@ -2415,12 +2421,6 @@ static void nvme_dev_shutdown(struct nvme_dev *dev) ...@@ -2415,12 +2421,6 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
nvme_dev_unmap(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) static void nvme_dev_remove(struct nvme_dev *dev)
{ {
struct nvme_ns *ns; struct nvme_ns *ns;
...@@ -2510,6 +2510,7 @@ static void nvme_free_dev(struct kref *kref) ...@@ -2510,6 +2510,7 @@ static void nvme_free_dev(struct kref *kref)
nvme_free_namespaces(dev); nvme_free_namespaces(dev);
nvme_release_instance(dev); nvme_release_instance(dev);
blk_mq_free_tag_set(&dev->tagset); blk_mq_free_tag_set(&dev->tagset);
blk_put_queue(dev->admin_q);
kfree(dev->queues); kfree(dev->queues);
kfree(dev->entry); kfree(dev->entry);
kfree(dev); kfree(dev);
...@@ -2795,7 +2796,6 @@ static void nvme_remove(struct pci_dev *pdev) ...@@ -2795,7 +2796,6 @@ static void nvme_remove(struct pci_dev *pdev)
nvme_dev_shutdown(dev); nvme_dev_shutdown(dev);
nvme_dev_remove_admin(dev); nvme_dev_remove_admin(dev);
nvme_free_queues(dev, 0); nvme_free_queues(dev, 0);
nvme_free_admin_tags(dev);
nvme_release_prp_pools(dev); nvme_release_prp_pools(dev);
kref_put(&dev->kref, nvme_free_dev); kref_put(&dev->kref, nvme_free_dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment