Commit ee9aebb2 authored by Keith Busch's avatar Keith Busch Committed by Christoph Hellwig

nvme-pci: Suspend queues after deleting them

The driver had been abusing the cq_vector state to know if new submissions
were safe, but that was before we could quiesce blk-mq. If the controller
happens to get an interrupt through while we're suspending those queues,
'no irq handler' warnings may occur.

This patch will disable the interrupts only after the queues are deleted.
Reported-by: default avatarJianchao Wang <jianchao.w.wang@oracle.com>
Tested-by: default avatarJianchao Wang <jianchao.w.wang@oracle.com>
Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 62314e40
...@@ -1324,9 +1324,6 @@ static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown) ...@@ -1324,9 +1324,6 @@ static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown)
{ {
struct nvme_queue *nvmeq = &dev->queues[0]; struct nvme_queue *nvmeq = &dev->queues[0];
if (nvme_suspend_queue(nvmeq))
return;
if (shutdown) if (shutdown)
nvme_shutdown_ctrl(&dev->ctrl); nvme_shutdown_ctrl(&dev->ctrl);
else else
...@@ -2011,9 +2008,9 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode) ...@@ -2011,9 +2008,9 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode)
return 0; return 0;
} }
static void nvme_disable_io_queues(struct nvme_dev *dev, int queues) static void nvme_disable_io_queues(struct nvme_dev *dev)
{ {
int pass; int pass, queues = dev->online_queues - 1;
unsigned long timeout; unsigned long timeout;
u8 opcode = nvme_admin_delete_sq; u8 opcode = nvme_admin_delete_sq;
...@@ -2164,7 +2161,7 @@ static void nvme_pci_disable(struct nvme_dev *dev) ...@@ -2164,7 +2161,7 @@ static void nvme_pci_disable(struct nvme_dev *dev)
static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
{ {
int i, queues; int i;
bool dead = true; bool dead = true;
struct pci_dev *pdev = to_pci_dev(dev->dev); struct pci_dev *pdev = to_pci_dev(dev->dev);
...@@ -2199,21 +2196,13 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) ...@@ -2199,21 +2196,13 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
} }
nvme_stop_queues(&dev->ctrl); nvme_stop_queues(&dev->ctrl);
queues = dev->online_queues - 1; if (!dead) {
for (i = dev->ctrl.queue_count - 1; i > 0; i--) nvme_disable_io_queues(dev);
nvme_suspend_queue(&dev->queues[i]);
if (dead) {
/* A device might become IO incapable very soon during
* probe, before the admin queue is configured. Thus,
* queue_count can be 0 here.
*/
if (dev->ctrl.queue_count)
nvme_suspend_queue(&dev->queues[0]);
} else {
nvme_disable_io_queues(dev, queues);
nvme_disable_admin_queue(dev, shutdown); nvme_disable_admin_queue(dev, shutdown);
} }
for (i = dev->ctrl.queue_count - 1; i >= 0; i--)
nvme_suspend_queue(&dev->queues[i]);
nvme_pci_disable(dev); nvme_pci_disable(dev);
blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_request, &dev->ctrl); blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_request, &dev->ctrl);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment