[PATCH RFC v4 08/21] nvme-pci: Handle movable BARs
Sergey Miroshnichenko
s.miroshnichenko at yadro.com
Tue Mar 12 00:31:09 AEDT 2019
Hotplugged devices can affect the existing ones by moving their BARs.
PCI subsystem will inform the NVME driver about this by invoking
reset_prepare()+reset_done(), then iounmap()+ioremap() must be called.
Signed-off-by: Sergey Miroshnichenko <s.miroshnichenko at yadro.com>
---
drivers/nvme/host/pci.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 92bad1c810ac..ccea3033a67a 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -106,6 +106,7 @@ struct nvme_dev {
unsigned int num_vecs;
int q_depth;
u32 db_stride;
+ resource_size_t current_phys_bar;
void __iomem *bar;
unsigned long bar_mapped_size;
struct work_struct remove_work;
@@ -1672,13 +1673,16 @@ static int nvme_remap_bar(struct nvme_dev *dev, unsigned long size)
{
struct pci_dev *pdev = to_pci_dev(dev->dev);
- if (size <= dev->bar_mapped_size)
+ if (dev->bar &&
+ dev->current_phys_bar == pci_resource_start(pdev, 0) &&
+ size <= dev->bar_mapped_size)
return 0;
if (size > pci_resource_len(pdev, 0))
return -ENOMEM;
if (dev->bar)
iounmap(dev->bar);
- dev->bar = ioremap(pci_resource_start(pdev, 0), size);
+ dev->current_phys_bar = pci_resource_start(pdev, 0);
+ dev->bar = ioremap(dev->current_phys_bar, size);
if (!dev->bar) {
dev->bar_mapped_size = 0;
return -ENOMEM;
@@ -2504,6 +2508,8 @@ static void nvme_reset_work(struct work_struct *work)
if (WARN_ON(dev->ctrl.state != NVME_CTRL_RESETTING))
goto out;
+ nvme_remap_bar(dev, db_bar_size(dev, 0));
+
/*
* If we're called to reset a live controller first shut it down before
* moving on.
@@ -2910,6 +2916,23 @@ static void nvme_error_resume(struct pci_dev *pdev)
flush_work(&dev->ctrl.reset_work);
}
+void nvme_rescan_prepare(struct pci_dev *pdev)
+{
+ struct nvme_dev *dev = pci_get_drvdata(pdev);
+
+ nvme_dev_disable(dev, false);
+ nvme_dev_unmap(dev);
+ dev->bar = NULL;
+}
+
+void nvme_rescan_done(struct pci_dev *pdev)
+{
+ struct nvme_dev *dev = pci_get_drvdata(pdev);
+
+ nvme_dev_map(dev);
+ nvme_reset_ctrl_sync(&dev->ctrl);
+}
+
static const struct pci_error_handlers nvme_err_handler = {
.error_detected = nvme_error_detected,
.slot_reset = nvme_slot_reset,
@@ -2974,6 +2997,8 @@ static struct pci_driver nvme_driver = {
},
.sriov_configure = pci_sriov_configure_simple,
.err_handler = &nvme_err_handler,
+ .rescan_prepare = nvme_rescan_prepare,
+ .rescan_done = nvme_rescan_done,
};
static int __init nvme_init(void)
--
2.20.1
More information about the Linuxppc-dev
mailing list