Commit 09113abf authored by Tong Zhang's avatar Tong Zhang Committed by Christoph Hellwig

nvme-pci: fix error handling in nvme_pci_enable()

There are two issues in nvme_pci_enable():

 1) If pci_alloc_irq_vectors() fails, device is left enabled. Fix this by
    adding a goto disable statement.
 2) nvme_pci_configure_admin_queue could return -ENODEV, in this case,
    we will need to free IRQ properly.  Otherwise the following warning
    could be triggered:

[    5.286752] WARNING: CPU: 0 PID: 33 at kernel/irq/irqdomain.c:253 irq_domain_remove+0x12d/0x140
[    5.290547] Call Trace:
[    5.290626]  <TASK>
[    5.290695]  msi_remove_device_irq_domain+0xc9/0xf0
[    5.290843]  msi_device_data_release+0x15/0x80
[    5.290978]  release_nodes+0x58/0x90
[    5.293788] WARNING: CPU: 0 PID: 33 at kernel/irq/msi.c:276 msi_device_data_release+0x76/0x80
[    5.297573] Call Trace:
[    5.297651]  <TASK>
[    5.297719]  release_nodes+0x58/0x90
[    5.297831]  devres_release_all+0xef/0x140
[    5.298339]  device_unbind_cleanup+0x11/0xc0
[    5.298479]  really_probe+0x296/0x320

Fixes: a6ee7f19 ("nvme-pci: call nvme_pci_configure_admin_queue from nvme_pci_enable")
Co-developed-by: default avatarKeith Busch <kbusch@kernel.org>
Signed-off-by: default avatarTong Zhang <ztong0001@gmail.com>
Reviewed-by: default avatarKeith Busch <kbusch@kernel.org>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 453116a4
...@@ -2533,7 +2533,7 @@ static int nvme_pci_enable(struct nvme_dev *dev) ...@@ -2533,7 +2533,7 @@ static int nvme_pci_enable(struct nvme_dev *dev)
*/ */
result = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); result = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
if (result < 0) if (result < 0)
return result; goto disable;
dev->ctrl.cap = lo_hi_readq(dev->bar + NVME_REG_CAP); dev->ctrl.cap = lo_hi_readq(dev->bar + NVME_REG_CAP);
...@@ -2586,8 +2586,13 @@ static int nvme_pci_enable(struct nvme_dev *dev) ...@@ -2586,8 +2586,13 @@ static int nvme_pci_enable(struct nvme_dev *dev)
pci_enable_pcie_error_reporting(pdev); pci_enable_pcie_error_reporting(pdev);
pci_save_state(pdev); pci_save_state(pdev);
return nvme_pci_configure_admin_queue(dev); result = nvme_pci_configure_admin_queue(dev);
if (result)
goto free_irq;
return result;
free_irq:
pci_free_irq_vectors(pdev);
disable: disable:
pci_disable_device(pdev); pci_disable_device(pdev);
return result; return result;
......
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