The _RST is a standard method specified in the ACPI specification. It provides a function level reset when it is described in the acpi_device context associated with PCI-device. Implement a new reset function pci_dev_acpi_reset() for probing RST method and execute if it is defined in the firmware. The ACPI based reset is called after the device-specific reset and before standard PCI hardware resets. Signed-off-by: Shanker Donthineni <sdonthineni@xxxxxxxxxx> --- - Fix typo in the commit text drivers/pci/pci.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 16a17215f633..6dadb19848c2 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5054,6 +5054,35 @@ static void pci_dev_restore(struct pci_dev *dev) err_handler->reset_done(dev); } +/** + * pci_dev_acpi_reset - do a function level reset using _RST method + * @dev: device to reset + * @probe: check if _RST method is included in the acpi_device context. + */ +static int pci_dev_acpi_reset(struct pci_dev *dev, int probe) +{ +#ifdef CONFIG_ACPI + acpi_handle handle = ACPI_HANDLE(&dev->dev); + + /* Return -ENOTTY if _RST method is not included in the dev context */ + if (!handle || !acpi_has_method(handle, "_RST")) + return -ENOTTY; + + /* Return 0 for probe phase indicating that we can reset this device */ + if (probe) + return 0; + + /* Invoke _RST() method to perform a function level reset */ + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_RST", NULL, NULL))) { + pci_warn(dev, "Failed to reset the device\n"); + return -EINVAL; + } + return 0; +#else + return -ENOTTY; +#endif +} + /** * __pci_reset_function_locked - reset a PCI device function while holding * the @dev mutex lock. @@ -5089,6 +5118,9 @@ int __pci_reset_function_locked(struct pci_dev *dev) * reset mechanisms might be broken on the device. */ rc = pci_dev_specific_reset(dev, 0); + if (rc != -ENOTTY) + return rc; + rc = pci_dev_acpi_reset(dev, 0); if (rc != -ENOTTY) return rc; if (pcie_has_flr(dev)) { @@ -5127,6 +5159,9 @@ int pci_probe_reset_function(struct pci_dev *dev) might_sleep(); rc = pci_dev_specific_reset(dev, 1); + if (rc != -ENOTTY) + return rc; + rc = pci_dev_acpi_reset(dev, 1); if (rc != -ENOTTY) return rc; if (pcie_has_flr(dev)) -- 2.17.1