Commit 775755ed authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Bjorn Helgaas

PCI: Split ->reset_notify() method into ->reset_prepare() and ->reset_done()

The pci_error_handlers->reset_notify() method had a flag to indicate
whether to prepare for or clean up after a reset.  The prepare and done
cases have no shared functionality whatsoever, so split them into separate
methods.

[bhelgaas: changelog, update locking comments]
Link: http://lkml.kernel.org/r/20170601111039.8913-3-hch@lst.deSigned-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent b014e96d
...@@ -2348,30 +2348,19 @@ static void fm10k_io_resume(struct pci_dev *pdev) ...@@ -2348,30 +2348,19 @@ static void fm10k_io_resume(struct pci_dev *pdev)
netif_device_attach(netdev); netif_device_attach(netdev);
} }
/** static void fm10k_io_reset_prepare(struct pci_dev *pdev)
* fm10k_io_reset_notify - called when PCI function is reset
* @pdev: Pointer to PCI device
*
* This callback is called when the PCI function is reset such as from
* /sys/class/net/<enpX>/device/reset or similar. When prepare is true, it
* means we should prepare for a function reset. If prepare is false, it means
* the function reset just occurred.
*/
static void fm10k_io_reset_notify(struct pci_dev *pdev, bool prepare)
{ {
struct fm10k_intfc *interface = pci_get_drvdata(pdev); /* warn incase we have any active VF devices */
int err = 0; if (pci_num_vf(pdev))
dev_warn(&pdev->dev,
if (prepare) { "PCIe FLR may cause issues for any active VF devices\n");
/* warn incase we have any active VF devices */ fm10k_prepare_suspend(pci_get_drvdata(pdev));
if (pci_num_vf(pdev)) }
dev_warn(&pdev->dev,
"PCIe FLR may cause issues for any active VF devices\n");
fm10k_prepare_suspend(interface); static void fm10k_io_reset_done(struct pci_dev *pdev)
} else { {
err = fm10k_handle_resume(interface); struct fm10k_intfc *interface = pci_get_drvdata(pdev);
} int err = fm10k_handle_resume(interface);
if (err) { if (err) {
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
...@@ -2384,7 +2373,8 @@ static const struct pci_error_handlers fm10k_err_handler = { ...@@ -2384,7 +2373,8 @@ static const struct pci_error_handlers fm10k_err_handler = {
.error_detected = fm10k_io_error_detected, .error_detected = fm10k_io_error_detected,
.slot_reset = fm10k_io_slot_reset, .slot_reset = fm10k_io_slot_reset,
.resume = fm10k_io_resume, .resume = fm10k_io_resume,
.reset_notify = fm10k_io_reset_notify, .reset_prepare = fm10k_io_reset_prepare,
.reset_done = fm10k_io_reset_done,
}; };
static struct pci_driver fm10k_driver = { static struct pci_driver fm10k_driver = {
......
...@@ -346,11 +346,13 @@ static const struct pci_device_id mwifiex_ids[] = { ...@@ -346,11 +346,13 @@ static const struct pci_device_id mwifiex_ids[] = {
MODULE_DEVICE_TABLE(pci, mwifiex_ids); MODULE_DEVICE_TABLE(pci, mwifiex_ids);
static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare) /*
* Cleanup all software without cleaning anything related to PCIe and HW.
*/
static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev)
{ {
struct pcie_service_card *card = pci_get_drvdata(pdev); struct pcie_service_card *card = pci_get_drvdata(pdev);
struct mwifiex_adapter *adapter = card->adapter; struct mwifiex_adapter *adapter = card->adapter;
int ret;
if (!adapter) { if (!adapter) {
dev_err(&pdev->dev, "%s: adapter structure is not valid\n", dev_err(&pdev->dev, "%s: adapter structure is not valid\n",
...@@ -359,37 +361,48 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare) ...@@ -359,37 +361,48 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
} }
mwifiex_dbg(adapter, INFO, mwifiex_dbg(adapter, INFO,
"%s: vendor=0x%4.04x device=0x%4.04x rev=%d %s\n", "%s: vendor=0x%4.04x device=0x%4.04x rev=%d Pre-FLR\n",
__func__, pdev->vendor, pdev->device, __func__, pdev->vendor, pdev->device, pdev->revision);
pdev->revision,
prepare ? "Pre-FLR" : "Post-FLR"); mwifiex_shutdown_sw(adapter);
adapter->surprise_removed = true;
if (prepare) { clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
/* Kernel would be performing FLR after this notification. clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
* Cleanup all software without cleaning anything related to
* PCIe and HW.
*/
mwifiex_shutdown_sw(adapter);
adapter->surprise_removed = true;
clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
} else {
/* Kernel stores and restores PCIe function context before and
* after performing FLR respectively. Reconfigure the software
* and firmware including firmware redownload
*/
adapter->surprise_removed = false;
ret = mwifiex_reinit_sw(adapter);
if (ret) {
dev_err(&pdev->dev, "reinit failed: %d\n", ret);
return;
}
}
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__); mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
} }
static const struct pci_error_handlers mwifiex_pcie_err_handler[] = { /*
{ .reset_notify = mwifiex_pcie_reset_notify, }, * Kernel stores and restores PCIe function context before and after performing
* FLR respectively. Reconfigure the software and firmware including firmware
* redownload.
*/
static void mwifiex_pcie_reset_done(struct pci_dev *pdev)
{
struct pcie_service_card *card = pci_get_drvdata(pdev);
struct mwifiex_adapter *adapter = card->adapter;
int ret;
if (!adapter) {
dev_err(&pdev->dev, "%s: adapter structure is not valid\n",
__func__);
return;
}
mwifiex_dbg(adapter, INFO,
"%s: vendor=0x%4.04x device=0x%4.04x rev=%d Post-FLR\n",
__func__, pdev->vendor, pdev->device, pdev->revision);
adapter->surprise_removed = false;
ret = mwifiex_reinit_sw(adapter);
if (ret)
dev_err(&pdev->dev, "reinit failed: %d\n", ret);
else
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
}
static const struct pci_error_handlers mwifiex_pcie_err_handler = {
.reset_prepare = mwifiex_pcie_reset_prepare,
.reset_done = mwifiex_pcie_reset_done,
}; };
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
...@@ -410,7 +423,7 @@ static struct pci_driver __refdata mwifiex_pcie = { ...@@ -410,7 +423,7 @@ static struct pci_driver __refdata mwifiex_pcie = {
}, },
#endif #endif
.shutdown = mwifiex_pcie_shutdown, .shutdown = mwifiex_pcie_shutdown,
.err_handler = mwifiex_pcie_err_handler, .err_handler = &mwifiex_pcie_err_handler,
}; };
/* /*
......
...@@ -2145,14 +2145,14 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2145,14 +2145,14 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return result; return result;
} }
static void nvme_reset_notify(struct pci_dev *pdev, bool prepare) static void nvme_reset_prepare(struct pci_dev *pdev)
{ {
struct nvme_dev *dev = pci_get_drvdata(pdev); nvme_dev_disable(pci_get_drvdata(pdev), false);
}
if (prepare) static void nvme_reset_done(struct pci_dev *pdev)
nvme_dev_disable(dev, false); {
else nvme_reset(pci_get_drvdata(pdev));
nvme_reset(dev);
} }
static void nvme_shutdown(struct pci_dev *pdev) static void nvme_shutdown(struct pci_dev *pdev)
...@@ -2275,7 +2275,8 @@ static const struct pci_error_handlers nvme_err_handler = { ...@@ -2275,7 +2275,8 @@ static const struct pci_error_handlers nvme_err_handler = {
.error_detected = nvme_error_detected, .error_detected = nvme_error_detected,
.slot_reset = nvme_slot_reset, .slot_reset = nvme_slot_reset,
.resume = nvme_error_resume, .resume = nvme_error_resume,
.reset_notify = nvme_reset_notify, .reset_prepare = nvme_reset_prepare,
.reset_done = nvme_reset_done,
}; };
static const struct pci_device_id nvme_id_table[] = { static const struct pci_device_id nvme_id_table[] = {
......
...@@ -4130,32 +4130,18 @@ static void pci_dev_unlock(struct pci_dev *dev) ...@@ -4130,32 +4130,18 @@ static void pci_dev_unlock(struct pci_dev *dev)
pci_cfg_access_unlock(dev); pci_cfg_access_unlock(dev);
} }
/** static void pci_dev_save_and_disable(struct pci_dev *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 = const struct pci_error_handlers *err_handler =
dev->driver ? dev->driver->err_handler : NULL; dev->driver ? dev->driver->err_handler : NULL;
/* /*
* dev->driver->err_handler->reset_notify() is protected against * dev->driver->err_handler->reset_prepare() is protected against
* races with ->remove() by the device lock, which must be held by * races with ->remove() by the device lock, which must be held by
* the caller. * the caller.
*/ */
if (err_handler && err_handler->reset_notify) if (err_handler && err_handler->reset_prepare)
err_handler->reset_notify(dev, prepare); err_handler->reset_prepare(dev);
}
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 * Wake-up device prior to save. PM registers default to D0 after
...@@ -4177,8 +4163,18 @@ static void pci_dev_save_and_disable(struct pci_dev *dev) ...@@ -4177,8 +4163,18 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)
static void pci_dev_restore(struct pci_dev *dev) static void pci_dev_restore(struct pci_dev *dev)
{ {
const struct pci_error_handlers *err_handler =
dev->driver ? dev->driver->err_handler : NULL;
pci_restore_state(dev); pci_restore_state(dev);
pci_reset_notify(dev, false);
/*
* dev->driver->err_handler->reset_done() is protected against
* races with ->remove() by the device lock, which must be held by
* the caller.
*/
if (err_handler && err_handler->reset_done)
err_handler->reset_done(dev);
} }
static int pci_dev_reset(struct pci_dev *dev, int probe) static int pci_dev_reset(struct pci_dev *dev, int probe)
......
...@@ -698,7 +698,8 @@ struct pci_error_handlers { ...@@ -698,7 +698,8 @@ struct pci_error_handlers {
pci_ers_result_t (*slot_reset)(struct pci_dev *dev); pci_ers_result_t (*slot_reset)(struct pci_dev *dev);
/* PCI function reset prepare or completed */ /* PCI function reset prepare or completed */
void (*reset_notify)(struct pci_dev *dev, bool prepare); void (*reset_prepare)(struct pci_dev *dev);
void (*reset_done)(struct pci_dev *dev);
/* Device driver may resume normal operations */ /* Device driver may resume normal operations */
void (*resume)(struct pci_dev *dev); void (*resume)(struct pci_dev *dev);
......
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