mirror of https://gitee.com/openkylin/linux.git
NVMe: Surprise removal handling
This adds checks to see if the nvme pci device was removed. The check reads the status register for the value of -1, which it should never be unless the device is no longer present. If a user performs a surprise removal on an nvme device, the driver will be notified either by the pci driver remove callback if the platform's slot is capable of this event, or via reading the device BAR status register, which will indicate controller failure and trigger a reset. Either way, the device is not present so all outstanding commands would timeout. This will not send queue deletion commands to a drive that isn't present and fail after ioremap, significantly speeding up surprise removal; previously this took over 2 minutes per IO queue pair created, but this will complete removing the device within a few seconds. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
This commit is contained in:
parent
c30341dc3c
commit
0e53d18051
|
@ -1140,8 +1140,9 @@ static void nvme_disable_queue(struct nvme_dev *dev, int qid)
|
||||||
irq_set_affinity_hint(vector, NULL);
|
irq_set_affinity_hint(vector, NULL);
|
||||||
free_irq(vector, nvmeq);
|
free_irq(vector, nvmeq);
|
||||||
|
|
||||||
/* Don't tell the adapter to delete the admin queue */
|
/* Don't tell the adapter to delete the admin queue.
|
||||||
if (qid) {
|
* Don't tell a removed adapter to delete IO queues. */
|
||||||
|
if (qid && readl(&dev->bar->csts) != -1) {
|
||||||
adapter_delete_sq(dev, qid);
|
adapter_delete_sq(dev, qid);
|
||||||
adapter_delete_cq(dev, qid);
|
adapter_delete_cq(dev, qid);
|
||||||
}
|
}
|
||||||
|
@ -2052,12 +2053,18 @@ static int nvme_dev_map(struct nvme_dev *dev)
|
||||||
dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
|
dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
|
||||||
if (!dev->bar)
|
if (!dev->bar)
|
||||||
goto disable;
|
goto disable;
|
||||||
|
if (readl(&dev->bar->csts) == -1) {
|
||||||
|
result = -ENODEV;
|
||||||
|
goto unmap;
|
||||||
|
}
|
||||||
dev->db_stride = 1 << NVME_CAP_STRIDE(readq(&dev->bar->cap));
|
dev->db_stride = 1 << NVME_CAP_STRIDE(readq(&dev->bar->cap));
|
||||||
dev->dbs = ((void __iomem *)dev->bar) + 4096;
|
dev->dbs = ((void __iomem *)dev->bar) + 4096;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
unmap:
|
||||||
|
iounmap(dev->bar);
|
||||||
|
dev->bar = NULL;
|
||||||
disable:
|
disable:
|
||||||
pci_release_regions(pdev);
|
pci_release_regions(pdev);
|
||||||
disable_pci:
|
disable_pci:
|
||||||
|
|
Loading…
Reference in New Issue