diff options
author | Keith Busch <keith.busch@intel.com> | 2015-01-07 20:55:49 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-01-08 11:00:32 -0500 |
commit | ea191d2f36b0f577ce5377c3e72aedc34282969d (patch) | |
tree | 27ff7ee0f1971cea41c38a7c3d265a3f4a106263 | |
parent | c917dfe52834979610d45022226445d1dc7c67d8 (diff) |
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: Keith Busch <keith.busch@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | drivers/block/nvme-core.c | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 286fa4cfc937..beb8d48f8560 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c | |||
@@ -1369,6 +1369,14 @@ static struct blk_mq_ops nvme_mq_ops = { | |||
1369 | .timeout = nvme_timeout, | 1369 | .timeout = nvme_timeout, |
1370 | }; | 1370 | }; |
1371 | 1371 | ||
1372 | static void nvme_dev_remove_admin(struct nvme_dev *dev) | ||
1373 | { | ||
1374 | if (dev->admin_q && !blk_queue_dying(dev->admin_q)) { | ||
1375 | blk_cleanup_queue(dev->admin_q); | ||
1376 | blk_mq_free_tag_set(&dev->admin_tagset); | ||
1377 | } | ||
1378 | } | ||
1379 | |||
1372 | static int nvme_alloc_admin_tags(struct nvme_dev *dev) | 1380 | static int nvme_alloc_admin_tags(struct nvme_dev *dev) |
1373 | { | 1381 | { |
1374 | if (!dev->admin_q) { | 1382 | if (!dev->admin_q) { |
@@ -1388,17 +1396,15 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev) | |||
1388 | blk_mq_free_tag_set(&dev->admin_tagset); | 1396 | blk_mq_free_tag_set(&dev->admin_tagset); |
1389 | return -ENOMEM; | 1397 | return -ENOMEM; |
1390 | } | 1398 | } |
1399 | if (!blk_get_queue(dev->admin_q)) { | ||
1400 | nvme_dev_remove_admin(dev); | ||
1401 | return -ENODEV; | ||
1402 | } | ||
1391 | } | 1403 | } |
1392 | 1404 | ||
1393 | return 0; | 1405 | return 0; |
1394 | } | 1406 | } |
1395 | 1407 | ||
1396 | static void nvme_free_admin_tags(struct nvme_dev *dev) | ||
1397 | { | ||
1398 | if (dev->admin_q) | ||
1399 | blk_mq_free_tag_set(&dev->admin_tagset); | ||
1400 | } | ||
1401 | |||
1402 | static int nvme_configure_admin_queue(struct nvme_dev *dev) | 1408 | static int nvme_configure_admin_queue(struct nvme_dev *dev) |
1403 | { | 1409 | { |
1404 | int result; | 1410 | int result; |
@@ -1465,7 +1471,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev) | |||
1465 | return result; | 1471 | return result; |
1466 | 1472 | ||
1467 | free_tags: | 1473 | free_tags: |
1468 | nvme_free_admin_tags(dev); | 1474 | nvme_dev_remove_admin(dev); |
1469 | free_nvmeq: | 1475 | free_nvmeq: |
1470 | nvme_free_queues(dev, 0); | 1476 | nvme_free_queues(dev, 0); |
1471 | return result; | 1477 | return result; |
@@ -2415,12 +2421,6 @@ static void nvme_dev_shutdown(struct nvme_dev *dev) | |||
2415 | nvme_dev_unmap(dev); | 2421 | nvme_dev_unmap(dev); |
2416 | } | 2422 | } |
2417 | 2423 | ||
2418 | static void nvme_dev_remove_admin(struct nvme_dev *dev) | ||
2419 | { | ||
2420 | if (dev->admin_q && !blk_queue_dying(dev->admin_q)) | ||
2421 | blk_cleanup_queue(dev->admin_q); | ||
2422 | } | ||
2423 | |||
2424 | static void nvme_dev_remove(struct nvme_dev *dev) | 2424 | static void nvme_dev_remove(struct nvme_dev *dev) |
2425 | { | 2425 | { |
2426 | struct nvme_ns *ns; | 2426 | struct nvme_ns *ns; |
@@ -2510,6 +2510,7 @@ static void nvme_free_dev(struct kref *kref) | |||
2510 | nvme_free_namespaces(dev); | 2510 | nvme_free_namespaces(dev); |
2511 | nvme_release_instance(dev); | 2511 | nvme_release_instance(dev); |
2512 | blk_mq_free_tag_set(&dev->tagset); | 2512 | blk_mq_free_tag_set(&dev->tagset); |
2513 | blk_put_queue(dev->admin_q); | ||
2513 | kfree(dev->queues); | 2514 | kfree(dev->queues); |
2514 | kfree(dev->entry); | 2515 | kfree(dev->entry); |
2515 | kfree(dev); | 2516 | kfree(dev); |
@@ -2795,7 +2796,6 @@ static void nvme_remove(struct pci_dev *pdev) | |||
2795 | nvme_dev_shutdown(dev); | 2796 | nvme_dev_shutdown(dev); |
2796 | nvme_dev_remove_admin(dev); | 2797 | nvme_dev_remove_admin(dev); |
2797 | nvme_free_queues(dev, 0); | 2798 | nvme_free_queues(dev, 0); |
2798 | nvme_free_admin_tags(dev); | ||
2799 | nvme_release_prp_pools(dev); | 2799 | nvme_release_prp_pools(dev); |
2800 | kref_put(&dev->kref, nvme_free_dev); | 2800 | kref_put(&dev->kref, nvme_free_dev); |
2801 | } | 2801 | } |