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.de
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
Christoph Hellwig 2017-06-01 13:10:38 +02:00 committed by Bjorn Helgaas
parent b014e96d1a
commit 775755ed3c
5 changed files with 81 additions and 80 deletions

View File

@ -2348,30 +2348,19 @@ static void fm10k_io_resume(struct pci_dev *pdev)
netif_device_attach(netdev);
}
/**
* 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)
static void fm10k_io_reset_prepare(struct pci_dev *pdev)
{
/* warn incase we have any active VF devices */
if (pci_num_vf(pdev))
dev_warn(&pdev->dev,
"PCIe FLR may cause issues for any active VF devices\n");
fm10k_prepare_suspend(pci_get_drvdata(pdev));
}
static void fm10k_io_reset_done(struct pci_dev *pdev)
{
struct fm10k_intfc *interface = pci_get_drvdata(pdev);
int err = 0;
if (prepare) {
/* warn incase we have any active VF devices */
if (pci_num_vf(pdev))
dev_warn(&pdev->dev,
"PCIe FLR may cause issues for any active VF devices\n");
fm10k_prepare_suspend(interface);
} else {
err = fm10k_handle_resume(interface);
}
int err = fm10k_handle_resume(interface);
if (err) {
dev_warn(&pdev->dev,
@ -2384,7 +2373,8 @@ static const struct pci_error_handlers fm10k_err_handler = {
.error_detected = fm10k_io_error_detected,
.slot_reset = fm10k_io_slot_reset,
.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 = {

View File

@ -346,7 +346,37 @@ static const struct pci_device_id 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 mwifiex_adapter *adapter = card->adapter;
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 Pre-FLR\n",
__func__, pdev->vendor, pdev->device, pdev->revision);
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);
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
}
/*
* 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;
@ -359,37 +389,20 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
}
mwifiex_dbg(adapter, INFO,
"%s: vendor=0x%4.04x device=0x%4.04x rev=%d %s\n",
__func__, pdev->vendor, pdev->device,
pdev->revision,
prepare ? "Pre-FLR" : "Post-FLR");
"%s: vendor=0x%4.04x device=0x%4.04x rev=%d Post-FLR\n",
__func__, pdev->vendor, pdev->device, pdev->revision);
if (prepare) {
/* Kernel would be performing FLR after this notification.
* 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__);
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_notify = mwifiex_pcie_reset_notify, },
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
@ -410,7 +423,7 @@ static struct pci_driver __refdata mwifiex_pcie = {
},
#endif
.shutdown = mwifiex_pcie_shutdown,
.err_handler = mwifiex_pcie_err_handler,
.err_handler = &mwifiex_pcie_err_handler,
};
/*

View File

@ -2145,14 +2145,14 @@ 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)
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)
nvme_dev_disable(dev, false);
else
nvme_reset(dev);
static void nvme_reset_done(struct pci_dev *pdev)
{
nvme_reset(pci_get_drvdata(pdev));
}
static void nvme_shutdown(struct pci_dev *pdev)
@ -2275,7 +2275,8 @@ static const struct pci_error_handlers nvme_err_handler = {
.error_detected = nvme_error_detected,
.slot_reset = nvme_slot_reset,
.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[] = {

View File

@ -4130,32 +4130,18 @@ 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)
static void pci_dev_save_and_disable(struct pci_dev *dev)
{
const struct pci_error_handlers *err_handler =
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
* the caller.
*/
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);
if (err_handler && err_handler->reset_prepare)
err_handler->reset_prepare(dev);
/*
* 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)
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_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)

View File

@ -698,7 +698,8 @@ struct pci_error_handlers {
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);
void (*reset_prepare)(struct pci_dev *dev);
void (*reset_done)(struct pci_dev *dev);
/* Device driver may resume normal operations */
void (*resume)(struct pci_dev *dev);