|
@@ -120,6 +120,7 @@ struct nvme_dev {
|
|
|
unsigned long flags;
|
|
|
|
|
|
#define NVME_CTRL_RESETTING 0
|
|
|
+#define NVME_CTRL_REMOVING 1
|
|
|
|
|
|
struct nvme_ctrl ctrl;
|
|
|
struct completion ioq_wait;
|
|
@@ -286,6 +287,17 @@ static int nvme_init_request(void *data, struct request *req,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void nvme_queue_scan(struct nvme_dev *dev)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * Do not queue new scan work when a controller is reset during
|
|
|
+ * removal.
|
|
|
+ */
|
|
|
+ if (test_bit(NVME_CTRL_REMOVING, &dev->flags))
|
|
|
+ return;
|
|
|
+ queue_work(nvme_workq, &dev->scan_work);
|
|
|
+}
|
|
|
+
|
|
|
static void nvme_complete_async_event(struct nvme_dev *dev,
|
|
|
struct nvme_completion *cqe)
|
|
|
{
|
|
@@ -300,7 +312,7 @@ static void nvme_complete_async_event(struct nvme_dev *dev,
|
|
|
switch (result & 0xff07) {
|
|
|
case NVME_AER_NOTICE_NS_CHANGED:
|
|
|
dev_info(dev->dev, "rescanning\n");
|
|
|
- queue_work(nvme_workq, &dev->scan_work);
|
|
|
+ nvme_queue_scan(dev);
|
|
|
default:
|
|
|
dev_warn(dev->dev, "async event result %08x\n", result);
|
|
|
}
|
|
@@ -1690,7 +1702,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
|
|
|
return 0;
|
|
|
dev->ctrl.tagset = &dev->tagset;
|
|
|
}
|
|
|
- queue_work(nvme_workq, &dev->scan_work);
|
|
|
+ nvme_queue_scan(dev);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -2128,6 +2140,7 @@ static void nvme_remove(struct pci_dev *pdev)
|
|
|
{
|
|
|
struct nvme_dev *dev = pci_get_drvdata(pdev);
|
|
|
|
|
|
+ set_bit(NVME_CTRL_REMOVING, &dev->flags);
|
|
|
pci_set_drvdata(pdev, NULL);
|
|
|
flush_work(&dev->scan_work);
|
|
|
nvme_remove_namespaces(&dev->ctrl);
|