summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pci.c36
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c75
-rw-r--r--drivers/nvme/host/pci.c15
-rw-r--r--drivers/pci/ats.c87
-rw-r--r--drivers/pci/iov.c4
-rw-r--r--drivers/pci/pci-sysfs.c5
-rw-r--r--drivers/pci/pci.c161
-rw-r--r--drivers/pci/pci.h1
-rw-r--r--drivers/pci/quirks.c4
-rw-r--r--include/linux/pci-ats.h10
-rw-r--r--include/linux/pci.h11
11 files changed, 245 insertions, 164 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index 3e26d27ad213..63784576ae8b 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -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)
{
- 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");
+ /* 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));
+}
- fm10k_prepare_suspend(interface);
- } else {
- err = fm10k_handle_resume(interface);
- }
+static void fm10k_io_reset_done(struct pci_dev *pdev)
+{
+ struct fm10k_intfc *interface = pci_get_drvdata(pdev);
+ 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 = {
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index ac62bce50e96..279adf124fc9 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -346,11 +346,13 @@ 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;
- int ret;
if (!adapter) {
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)
}
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");
-
- 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;
- }
- }
+ "%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__);
}
-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
@@ -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,
};
/*
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index fed803232edc..9a3d69b8df98 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -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[] = {
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index eeb9fb2b47aa..ad8ddbbbf245 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -153,23 +153,27 @@ int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
u32 max_requests;
int pos;
+ if (WARN_ON(pdev->pri_enabled))
+ return -EBUSY;
+
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
if (!pos)
return -EINVAL;
- pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control);
pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status);
- if ((control & PCI_PRI_CTRL_ENABLE) ||
- !(status & PCI_PRI_STATUS_STOPPED))
+ if (!(status & PCI_PRI_STATUS_STOPPED))
return -EBUSY;
pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ, &max_requests);
reqs = min(max_requests, reqs);
+ pdev->pri_reqs_alloc = reqs;
pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs);
- control |= PCI_PRI_CTRL_ENABLE;
+ control = PCI_PRI_CTRL_ENABLE;
pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
+ pdev->pri_enabled = 1;
+
return 0;
}
EXPORT_SYMBOL_GPL(pci_enable_pri);
@@ -185,6 +189,9 @@ void pci_disable_pri(struct pci_dev *pdev)
u16 control;
int pos;
+ if (WARN_ON(!pdev->pri_enabled))
+ return;
+
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
if (!pos)
return;
@@ -192,10 +199,34 @@ void pci_disable_pri(struct pci_dev *pdev)
pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control);
control &= ~PCI_PRI_CTRL_ENABLE;
pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
+
+ pdev->pri_enabled = 0;
}
EXPORT_SYMBOL_GPL(pci_disable_pri);
/**
+ * pci_restore_pri_state - Restore PRI
+ * @pdev: PCI device structure
+ */
+void pci_restore_pri_state(struct pci_dev *pdev)
+{
+ u16 control = PCI_PRI_CTRL_ENABLE;
+ u32 reqs = pdev->pri_reqs_alloc;
+ int pos;
+
+ if (!pdev->pri_enabled)
+ return;
+
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
+ if (!pos)
+ return;
+
+ pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs);
+ pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
+}
+EXPORT_SYMBOL_GPL(pci_restore_pri_state);
+
+/**
* pci_reset_pri - Resets device's PRI state
* @pdev: PCI device structure
*
@@ -207,16 +238,14 @@ int pci_reset_pri(struct pci_dev *pdev)
u16 control;
int pos;
+ if (WARN_ON(pdev->pri_enabled))
+ return -EBUSY;
+
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
if (!pos)
return -EINVAL;
- pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control);
- if (control & PCI_PRI_CTRL_ENABLE)
- return -EBUSY;
-
- control |= PCI_PRI_CTRL_RESET;
-
+ control = PCI_PRI_CTRL_RESET;
pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
return 0;
@@ -239,16 +268,14 @@ int pci_enable_pasid(struct pci_dev *pdev, int features)
u16 control, supported;
int pos;
+ if (WARN_ON(pdev->pasid_enabled))
+ return -EBUSY;
+
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
if (!pos)
return -EINVAL;
- pci_read_config_word(pdev, pos + PCI_PASID_CTRL, &control);
pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported);
-
- if (control & PCI_PASID_CTRL_ENABLE)
- return -EINVAL;
-
supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV;
/* User wants to enable anything unsupported? */
@@ -256,9 +283,12 @@ int pci_enable_pasid(struct pci_dev *pdev, int features)
return -EINVAL;
control = PCI_PASID_CTRL_ENABLE | features;
+ pdev->pasid_features = features;
pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control);
+ pdev->pasid_enabled = 1;
+
return 0;
}
EXPORT_SYMBOL_GPL(pci_enable_pasid);
@@ -266,22 +296,47 @@ EXPORT_SYMBOL_GPL(pci_enable_pasid);
/**
* pci_disable_pasid - Disable the PASID capability
* @pdev: PCI device structure
- *
*/
void pci_disable_pasid(struct pci_dev *pdev)
{
u16 control = 0;
int pos;
+ if (WARN_ON(!pdev->pasid_enabled))
+ return;
+
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
if (!pos)
return;
pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control);
+
+ pdev->pasid_enabled = 0;
}
EXPORT_SYMBOL_GPL(pci_disable_pasid);
/**
+ * pci_restore_pasid_state - Restore PASID capabilities
+ * @pdev: PCI device structure
+ */
+void pci_restore_pasid_state(struct pci_dev *pdev)
+{
+ u16 control;
+ int pos;
+
+ if (!pdev->pasid_enabled)
+ return;
+
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
+ if (!pos)
+ return;
+
+ control = PCI_PASID_CTRL_ENABLE | pdev->pasid_features;
+ pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control);
+}
+EXPORT_SYMBOL_GPL(pci_restore_pasid_state);
+
+/**
* pci_pasid_features - Check which PASID features are supported
* @pdev: PCI device structure
*
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index d9dc7363ac77..120485d6f352 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -461,8 +461,6 @@ found:
else
iov->dev = dev;
- mutex_init(&iov->lock);
-
dev->sriov = iov;
dev->is_physfn = 1;
rc = compute_max_vf_buses(dev);
@@ -491,8 +489,6 @@ static void sriov_release(struct pci_dev *dev)
if (dev != dev->sriov->dev)
pci_dev_put(dev->sriov->dev);
- mutex_destroy(&dev->sriov->lock);
-
kfree(dev->sriov);
dev->sriov = NULL;
}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index a3537cf58a20..2f3780b50723 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -595,7 +595,6 @@ static ssize_t sriov_numvfs_store(struct device *dev,
const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
- struct pci_sriov *iov = pdev->sriov;
int ret;
u16 num_vfs;
@@ -606,7 +605,7 @@ static ssize_t sriov_numvfs_store(struct device *dev,
if (num_vfs > pci_sriov_get_totalvfs(pdev))
return -ERANGE;
- mutex_lock(&iov->dev->sriov->lock);
+ device_lock(&pdev->dev);
if (num_vfs == pdev->sriov->num_VFs)
goto exit;
@@ -641,7 +640,7 @@ static ssize_t sriov_numvfs_store(struct device *dev,
num_vfs, ret);
exit:
- mutex_unlock(&iov->dev->sriov->lock);
+ device_unlock(&pdev->dev);
if (ret < 0)
return ret;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 703741242375..34b5fe025dd4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -28,6 +28,7 @@
#include <linux/pm_runtime.h>
#include <linux/pci_hotplug.h>
#include <linux/vmalloc.h>
+#include <linux/pci-ats.h>
#include <asm/setup.h>
#include <asm/dma.h>
#include <linux/aer.h>
@@ -1173,6 +1174,8 @@ void pci_restore_state(struct pci_dev *dev)
/* PCI Express register must be restored first */
pci_restore_pcie_state(dev);
+ pci_restore_pasid_state(dev);
+ pci_restore_pri_state(dev);
pci_restore_ats_state(dev);
pci_restore_vc_state(dev);
@@ -4033,40 +4036,6 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
return pci_reset_hotplug_slot(dev->slot->hotplug, probe);
}
-static int __pci_dev_reset(struct pci_dev *dev, int probe)
-{
- int rc;
-
- might_sleep();
-
- rc = pci_dev_specific_reset(dev, probe);
- if (rc != -ENOTTY)
- goto done;
-
- if (pcie_has_flr(dev)) {
- if (!probe)
- pcie_flr(dev);
- rc = 0;
- goto done;
- }
-
- rc = pci_af_flr(dev, probe);
- if (rc != -ENOTTY)
- goto done;
-
- rc = pci_pm_reset(dev, probe);
- if (rc != -ENOTTY)
- goto done;
-
- rc = pci_dev_reset_slot_function(dev, probe);
- if (rc != -ENOTTY)
- goto done;
-
- rc = pci_parent_bus_reset(dev, probe);
-done:
- return rc;
-}
-
static void pci_dev_lock(struct pci_dev *dev)
{
pci_cfg_access_lock(dev);
@@ -4092,26 +4061,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;
- 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);
+ /*
+ * 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_prepare)
+ err_handler->reset_prepare(dev);
/*
* Wake-up device prior to save. PM registers default to D0 after
@@ -4133,23 +4094,18 @@ 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)
-{
- int rc;
-
- if (!probe)
- pci_dev_lock(dev);
-
- rc = __pci_dev_reset(dev, probe);
+ const struct pci_error_handlers *err_handler =
+ dev->driver ? dev->driver->err_handler : NULL;
- if (!probe)
- pci_dev_unlock(dev);
+ pci_restore_state(dev);
- return rc;
+ /*
+ * 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);
}
/**
@@ -4171,7 +4127,13 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
*/
int __pci_reset_function(struct pci_dev *dev)
{
- return pci_dev_reset(dev, 0);
+ int ret;
+
+ pci_dev_lock(dev);
+ ret = __pci_reset_function_locked(dev);
+ pci_dev_unlock(dev);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(__pci_reset_function);
@@ -4196,7 +4158,27 @@ EXPORT_SYMBOL_GPL(__pci_reset_function);
*/
int __pci_reset_function_locked(struct pci_dev *dev)
{
- return __pci_dev_reset(dev, 0);
+ int rc;
+
+ might_sleep();
+
+ rc = pci_dev_specific_reset(dev, 0);
+ if (rc != -ENOTTY)
+ return rc;
+ if (pcie_has_flr(dev)) {
+ pcie_flr(dev);
+ return 0;
+ }
+ rc = pci_af_flr(dev, 0);
+ if (rc != -ENOTTY)
+ return rc;
+ rc = pci_pm_reset(dev, 0);
+ if (rc != -ENOTTY)
+ return rc;
+ rc = pci_dev_reset_slot_function(dev, 0);
+ if (rc != -ENOTTY)
+ return rc;
+ return pci_parent_bus_reset(dev, 0);
}
EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
@@ -4213,7 +4195,26 @@ EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
*/
int pci_probe_reset_function(struct pci_dev *dev)
{
- return pci_dev_reset(dev, 1);
+ int rc;
+
+ might_sleep();
+
+ rc = pci_dev_specific_reset(dev, 1);
+ if (rc != -ENOTTY)
+ return rc;
+ if (pcie_has_flr(dev))
+ return 0;
+ rc = pci_af_flr(dev, 1);
+ if (rc != -ENOTTY)
+ return rc;
+ rc = pci_pm_reset(dev, 1);
+ if (rc != -ENOTTY)
+ return rc;
+ rc = pci_dev_reset_slot_function(dev, 1);
+ if (rc != -ENOTTY)
+ return rc;
+
+ return pci_parent_bus_reset(dev, 1);
}
/**
@@ -4236,15 +4237,17 @@ int pci_reset_function(struct pci_dev *dev)
{
int rc;
- rc = pci_dev_reset(dev, 1);
+ rc = pci_probe_reset_function(dev);
if (rc)
return rc;
+ pci_dev_lock(dev);
pci_dev_save_and_disable(dev);
- rc = pci_dev_reset(dev, 0);
+ rc = __pci_reset_function_locked(dev);
pci_dev_restore(dev);
+ pci_dev_unlock(dev);
return rc;
}
@@ -4260,20 +4263,18 @@ int pci_try_reset_function(struct pci_dev *dev)
{
int rc;
- rc = pci_dev_reset(dev, 1);
+ rc = pci_probe_reset_function(dev);
if (rc)
return rc;
- pci_dev_save_and_disable(dev);
+ if (!pci_dev_trylock(dev))
+ return -EAGAIN;
- if (pci_dev_trylock(dev)) {
- rc = __pci_dev_reset(dev, 0);
- pci_dev_unlock(dev);
- } else
- rc = -EAGAIN;
+ pci_dev_save_and_disable(dev);
+ rc = __pci_reset_function_locked(dev);
+ pci_dev_unlock(dev);
pci_dev_restore(dev);
-
return rc;
}
EXPORT_SYMBOL_GPL(pci_try_reset_function);
@@ -4423,7 +4424,9 @@ static void pci_bus_save_and_disable(struct pci_bus *bus)
struct pci_dev *dev;
list_for_each_entry(dev, &bus->devices, bus_list) {
+ pci_dev_lock(dev);
pci_dev_save_and_disable(dev);
+ pci_dev_unlock(dev);
if (dev->subordinate)
pci_bus_save_and_disable(dev->subordinate);
}
@@ -4438,7 +4441,9 @@ static void pci_bus_restore(struct pci_bus *bus)
struct pci_dev *dev;
list_for_each_entry(dev, &bus->devices, bus_list) {
+ pci_dev_lock(dev);
pci_dev_restore(dev);
+ pci_dev_unlock(dev);
if (dev->subordinate)
pci_bus_restore(dev->subordinate);
}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index f8113e5b9812..93f4044b8f4b 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -272,7 +272,6 @@ struct pci_sriov {
u16 driver_max_VFs; /* max num VFs driver supports */
struct pci_dev *dev; /* lowest numbered PF */
struct pci_dev *self; /* this PF */
- struct mutex lock; /* lock for setting sriov_numvfs in sysfs */
resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
bool drivers_autoprobe; /* auto probing of VFs by driver */
};
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e1deb796976a..6967c6b4cf6b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3249,6 +3249,10 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1588,
quirk_broken_intx_masking);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1589,
quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x158a,
+ quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x158b,
+ quirk_broken_intx_masking);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x37d0,
quirk_broken_intx_masking);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x37d1,
diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h
index 57e0b8250947..782fb8e0755f 100644
--- a/include/linux/pci-ats.h
+++ b/include/linux/pci-ats.h
@@ -7,6 +7,7 @@
int pci_enable_pri(struct pci_dev *pdev, u32 reqs);
void pci_disable_pri(struct pci_dev *pdev);
+void pci_restore_pri_state(struct pci_dev *pdev);
int pci_reset_pri(struct pci_dev *pdev);
#else /* CONFIG_PCI_PRI */
@@ -20,6 +21,10 @@ static inline void pci_disable_pri(struct pci_dev *pdev)
{
}
+static inline void pci_restore_pri_state(struct pci_dev *pdev)
+{
+}
+
static inline int pci_reset_pri(struct pci_dev *pdev)
{
return -ENODEV;
@@ -31,6 +36,7 @@ static inline int pci_reset_pri(struct pci_dev *pdev)
int pci_enable_pasid(struct pci_dev *pdev, int features);
void pci_disable_pasid(struct pci_dev *pdev);
+void pci_restore_pasid_state(struct pci_dev *pdev);
int pci_pasid_features(struct pci_dev *pdev);
int pci_max_pasids(struct pci_dev *pdev);
@@ -45,6 +51,10 @@ static inline void pci_disable_pasid(struct pci_dev *pdev)
{
}
+static inline void pci_restore_pasid_state(struct pci_dev *pdev)
+{
+}
+
static inline int pci_pasid_features(struct pci_dev *pdev)
{
return -EINVAL;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a8acc5e80e02..9a6b4c458d9a 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -361,6 +361,8 @@ struct pci_dev {
unsigned int msix_enabled:1;
unsigned int ari_enabled:1; /* ARI forwarding */
unsigned int ats_enabled:1; /* Address Translation Service */
+ unsigned int pasid_enabled:1; /* Process Address Space ID */
+ unsigned int pri_enabled:1; /* Page Request Interface */
unsigned int is_managed:1;
unsigned int needs_freset:1; /* Dev requires fundamental reset */
unsigned int state_saved:1;
@@ -404,6 +406,12 @@ struct pci_dev {
u8 ats_stu; /* ATS Smallest Translation Unit */
atomic_t ats_ref_cnt; /* number of VFs with ATS enabled */
#endif
+#ifdef CONFIG_PCI_PRI
+ u32 pri_reqs_alloc; /* Number of PRI requests allocated */
+#endif
+#ifdef CONFIG_PCI_PASID
+ u16 pasid_features;
+#endif
phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */
size_t romlen; /* Length of ROM if it's not from the BAR */
char *driver_override; /* Driver name to force a match */
@@ -695,7 +703,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);