PCI: Device driver reset notification
Subsystems (3)
PATCH v2 1/2 PCI: Device driver reset notification
Notifies a pci device driver when its device's access is about to be disabled for an impending reset attempt, then after the attempt completes and device access is restored.
---
v1 -> v2:
Call the reset notification in all cases before device access is disabled and after device access is restored.
drivers/pci/pci.c | 21 +++++++++++++++++++++ include/linux/pci.h | 3 +++ 2 files changed, 24 insertions(+)
drivers/pci/pci.c +21 -0
@@ -3305,8 +3305,27 @@ static void pci_dev_unlock(struct pci_dev *dev)pci_cfg_access_unlock (dev); } +/** +* pci_reset_notify - notify device driver of reset +* @dev: device to be notified of reset +* @prepare: 'true' if device is about to be reset; 'false' if reset attempt +* completed +* +* Must be called prior to device access being disabled and after device +* access is restored. +*/ +static void pci_reset_notify (struct pci_dev *dev,bool prepare) +{ +const struct pci_error_handlers *err_handler = + dev->driver ? dev->driver->err_handler :NULL ; +if (err_handler && err_handler->reset_notify) + err_handler->reset_notify (dev, prepare); +} +static void pci_dev_save_and_disable (struct pci_dev *dev) { +pci_reset_notify (dev, true); +/* * Wake-up device prior to save. PM registers default to D0 after * reset and a simple register restore doesn't reliably return
@@ -3328,6 +3347,7 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)static void pci_dev_restore (struct pci_dev *dev) {pci_restore_state (dev); +pci_reset_notify (dev, false); }static int pci_dev_reset (struct pci_dev *dev,int probe)
@@ -3344,6 +3364,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)return rc; } +/** * __pci_reset_function - reset a PCI device function * @dev: PCI device to reset
include/linux/pci.h +3 -0
@@ -603,6 +603,9 @@ struct pci_error_handlers {/* PCI slot has been reset */ pci_ers_result_t (*slot_reset)(struct pci_dev *dev); +/* PCI function reset prepare or completed */ +void (*reset_notify)(struct pci_dev *dev,bool prepare); +/* Device driver may resume normal operations */ void (*resume)(struct pci_dev *dev); };
Signature · 1 line
1.7.10.4
PATCH v2 2/2 NVMe: Implement PCI-e reset notification callback
Quiesce and shutdown the device prior to reset, then restart the device and resume IO after.
---
v1 -> v2:
fixed compile warning for wrong data type in function (int -> bool).
drivers/block/nvme-core.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/block/nvme-core.c +11 -0
@@ -2775,6 +2775,16 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)return result; } +static void nvme_reset_notify (struct pci_dev *pdev,bool prepare) +{ +struct nvme_dev *dev =pci_get_drvdata (pdev); + +if (prepare) +nvme_dev_shutdown (dev); +else +nvme_dev_resume (dev); +} +static void nvme_shutdown (struct pci_dev *pdev) {struct nvme_dev *dev =pci_get_drvdata (pdev);
@@ -2839,6 +2849,7 @@ static const struct pci_error_handlers nvme_err_handler = { .link_reset = nvme_link_reset, .slot_reset = nvme_slot_reset, .resume = nvme_error_resume, + .reset_notify = nvme_reset_notify, };/* Move to pci_ids.h later */
Signature · 1 line
1.7.10.4
Bjorn Helgaas
maintainerPATCH v2 1/2 PCI: Device driver reset notification
In reply to Keith BuschQuoted 5 lines · Keith Busch
Notifies a pci device driver when its device's access is about to be disabled for an impending reset attempt, then after the attempt completes and device access is restored.
Signed-off-by Keith Busch <keith.busch at intel.com>
I applied both of these to my pci/hotplug branch for v3.16. Let me know if you want me to drop the NVMe patch and have it go via another tree.
Bjorn
Quoted 75 lines
---
v1 -> v2:Call the reset notification in all cases before device access is disabled and after device access is restored.
drivers/pci/pci.c | 21 +++++++++++++++++++++ include/linux/pci.h | 3 +++ 2 files changed, 24 insertions(+)drivers/pci/pci.c +21
-0@@ -3305,8 +3305,27 @@ static void pci_dev_unlock(struct pci_dev *dev)pci_cfg_access_unlock (dev); } +/** +* pci_reset_notify - notify device driver of reset +* @dev: device to be notified of reset +* @prepare: 'true' if device is about to be reset; 'false' if reset attempt +* completed +* +* Must be called prior to device access being disabled and after device +* access is restored. +*/ +static void pci_reset_notify (struct pci_dev *dev,bool prepare) +{ +const struct pci_error_handlers *err_handler = + dev->driver ? dev->driver->err_handler :NULL ; +if (err_handler && err_handler->reset_notify) + err_handler->reset_notify (dev, prepare); +} +static void pci_dev_save_and_disable (struct pci_dev *dev) { +pci_reset_notify (dev, true); +/* * Wake-up device prior to save. PM registers default to D0 after * reset and a simple register restore doesn't reliably return @@ -3328,6 +3347,7 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)static void pci_dev_restore (struct pci_dev *dev) {pci_restore_state (dev); +pci_reset_notify (dev, false); }static int pci_dev_reset (struct pci_dev *dev,int probe)@@ -3344,6 +3364,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)return rc; } +/** * __pci_reset_function - reset a PCI device function * @dev: PCI device to reset include/linux/pci.h +3
-0@@ -603,6 +603,9 @@ struct pci_error_handlers {/* PCI slot has been reset */ pci_ers_result_t (*slot_reset)(struct pci_dev *dev); +/* PCI function reset prepare or completed */ +void (*reset_notify)(struct pci_dev *dev,bool prepare); +/* Device driver may resume normal operations */ void (*resume)(struct pci_dev *dev); };Signature · 1 line
1.7.10.4