|
@@ -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)
|