From a80b4577b6a3119e737d758c421095e8d719c61d Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Wed, 22 Feb 2017 11:13:09 -0800 Subject: [PATCH] NVMe: Simplify device reset failure A reset failure schedules the device to unbind from the driver through the pci driver's remove. This cleans up all intialization, so there is no need to duplicate the potentially racy cleanup. To help understand why a reset failed, the status is logged with the existing warning message. Signed-off-by: Keith Busch Reviewed-by: Johannes Thumshirn Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe (cherry picked from commit f58944e265d4ebe47216a5d7488aee3928823d30) Orabug: 25130845 Signed-off-by: Ashok Vairavan Reviewed-by: Martin K. Petersen --- drivers/nvme/host/pci.c | 40 +++++++++++----------------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 748a1c24d214..9010f55c2757 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -82,7 +82,6 @@ struct nvme_queue; static int nvme_reset(struct nvme_dev *dev); static int nvme_process_cq(struct nvme_queue *nvmeq); static void nvme_unmap_data(struct nvme_dev *dev, struct nvme_iod *iod); -static void nvme_dead_ctrl(struct nvme_dev *dev); static void nvme_remove_dead_ctrl(struct nvme_dev *dev); static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown); @@ -1883,7 +1882,7 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl) static void nvme_reset_work(struct work_struct *work) { struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work); - int result; + int result = -ENODEV; if (WARN_ON(test_bit(NVME_CTRL_RESETTING, &dev->flags))) goto out; @@ -1903,26 +1902,25 @@ static void nvme_reset_work(struct work_struct *work) result = nvme_configure_admin_queue(dev); if (result) - goto unmap; + goto out; nvme_init_queue(dev->queues[0], 0); result = nvme_alloc_admin_tags(dev); if (result) - goto disable; + goto out; result = nvme_init_identify(&dev->ctrl); if (result) - goto free_tags; + goto out; result = nvme_setup_io_queues(dev); if (result) - goto free_tags; + goto out; dev->ctrl.event_limit = NVME_NR_AEN_COMMANDS; queue_work(nvme_workq, &dev->async_work); mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + HZ)); - /* * Keep the controller around but remove all namespaces if we don't have * any working I/O queue. @@ -1938,17 +1936,8 @@ static void nvme_reset_work(struct work_struct *work) clear_bit(NVME_CTRL_RESETTING, &dev->flags); return; - free_tags: - nvme_dev_remove_admin(dev); - blk_put_queue(dev->ctrl.admin_q); - dev->ctrl.admin_q = NULL; - disable: - nvme_disable_admin_queue(dev, false); - unmap: - nvme_dev_unmap(dev); out: - if (!work_pending(&dev->reset_work)) - nvme_dead_ctrl(dev); + nvme_remove_dead_ctrl(dev, result); } static int nvme_remove_dead_ctrl(void *arg) @@ -1962,18 +1951,6 @@ static int nvme_remove_dead_ctrl(void *arg) return 0; } -static void nvme_dead_ctrl(struct nvme_dev *dev) -{ - dev_warn(dev->ctrl.device, "Removing after probe failure\n"); - kref_get(&dev->ctrl.kref); - if (IS_ERR(kthread_run(nvme_remove_dead_ctrl, dev, "nvme%d", - dev->ctrl.instance))) { - dev_err(dev->dev, - "Failed to start controller remove task\n"); - nvme_put_ctrl(&dev->ctrl); - } -} - static int nvme_reset(struct nvme_dev *dev) { if (!dev->ctrl.admin_q || blk_queue_dying(dev->ctrl.admin_q)) @@ -2103,6 +2080,11 @@ static void nvme_shutdown(struct pci_dev *pdev) nvme_dev_disable(dev, true); } +/* + * The driver's remove may be called on a device in a partially initialized + * state. This function must not have any dependencies on the device state in + * order to proceed. + */ static void nvme_remove(struct pci_dev *pdev) { struct nvme_dev *dev = pci_get_drvdata(pdev); -- 2.50.1