NVMe: Failed controller initialization fixes
[linux-2.6-block.git] / drivers / block / nvme-core.c
index 01a68250f8682de11c3a853e80f0edfbfb7f7d4f..22761a6c34aa6edeae71a38db5ced7260228664a 100644 (file)
@@ -2931,6 +2931,18 @@ static int nvme_dev_resume(struct nvme_dev *dev)
        return 0;
 }
 
+static void nvme_dead_ctrl(struct nvme_dev *dev)
+{
+       dev_warn(dev->dev, "Device failed to resume\n");
+       kref_get(&dev->kref);
+       if (IS_ERR(kthread_run(nvme_remove_dead_ctrl, dev, "nvme%d",
+                                               dev->instance))) {
+               dev_err(dev->dev,
+                       "Failed to start controller remove task\n");
+               kref_put(&dev->kref, nvme_free_dev);
+       }
+}
+
 static void nvme_dev_reset(struct nvme_dev *dev)
 {
        bool in_probe = work_busy(&dev->probe_work);
@@ -2944,14 +2956,7 @@ static void nvme_dev_reset(struct nvme_dev *dev)
        /* Fail this device if reset occured during probe to avoid
         * infinite initialization loops. */
        if (in_probe) {
-               dev_warn(dev->dev, "Device failed to resume\n");
-               kref_get(&dev->kref);
-               if (IS_ERR(kthread_run(nvme_remove_dead_ctrl, dev, "nvme%d",
-                                                       dev->instance))) {
-                       dev_err(dev->dev,
-                               "Failed to start controller remove task\n");
-                       kref_put(&dev->kref, nvme_free_dev);
-               }
+               nvme_dead_ctrl(dev);
                return;
        }
        /* Schedule device resume asynchronously so the reset work is available
@@ -3086,16 +3091,8 @@ static void nvme_async_probe(struct work_struct *work)
 {
        struct nvme_dev *dev = container_of(work, struct nvme_dev, probe_work);
 
-       if (nvme_dev_resume(dev))
-               goto reset;
-       return;
- reset:
-       spin_lock(&dev_list_lock);
-       if (!work_busy(&dev->reset_work)) {
-               dev->reset_workfn = nvme_reset_failed_dev;
-               queue_work(nvme_workq, &dev->reset_work);
-       }
-       spin_unlock(&dev_list_lock);
+       if (nvme_dev_resume(dev) && !work_busy(&dev->reset_work))
+               nvme_dead_ctrl(dev);
 }
 
 static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)