PCI: Export pcie_flr()
Currently we opencode the FLR sequence in lots of place; export a core helper instead. We split out the probing for FLR support as all the non-core callers already know their hardware. Note that in the new pci_has_flr() function the quirk check has been moved before the capability check as there is no point in reading the capability in this case. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
committed by
Bjorn Helgaas
parent
0e7df22401
commit
a60a2b73ba
@@ -3773,27 +3773,41 @@ static void pci_flr_wait(struct pci_dev *dev)
|
|||||||
(i - 1) * 100);
|
(i - 1) * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcie_flr(struct pci_dev *dev, int probe)
|
/**
|
||||||
|
* pcie_has_flr - check if a device supports function level resets
|
||||||
|
* @dev: device to check
|
||||||
|
*
|
||||||
|
* Returns true if the device advertises support for PCIe function level
|
||||||
|
* resets.
|
||||||
|
*/
|
||||||
|
static bool pcie_has_flr(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
u32 cap;
|
u32 cap;
|
||||||
|
|
||||||
pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
|
|
||||||
if (!(cap & PCI_EXP_DEVCAP_FLR))
|
|
||||||
return -ENOTTY;
|
|
||||||
|
|
||||||
if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
|
if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
|
||||||
return -ENOTTY;
|
return false;
|
||||||
|
|
||||||
if (probe)
|
pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
|
||||||
return 0;
|
return cap & PCI_EXP_DEVCAP_FLR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pcie_flr - initiate a PCIe function level reset
|
||||||
|
* @dev: device to reset
|
||||||
|
*
|
||||||
|
* Initiate a function level reset on @dev. The caller should ensure the
|
||||||
|
* device supports FLR before calling this function, e.g. by using the
|
||||||
|
* pcie_has_flr() helper.
|
||||||
|
*/
|
||||||
|
void pcie_flr(struct pci_dev *dev)
|
||||||
|
{
|
||||||
if (!pci_wait_for_pending_transaction(dev))
|
if (!pci_wait_for_pending_transaction(dev))
|
||||||
dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
|
dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
|
||||||
|
|
||||||
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
|
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
|
||||||
pci_flr_wait(dev);
|
pci_flr_wait(dev);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pcie_flr);
|
||||||
|
|
||||||
static int pci_af_flr(struct pci_dev *dev, int probe)
|
static int pci_af_flr(struct pci_dev *dev, int probe)
|
||||||
{
|
{
|
||||||
@@ -3977,9 +3991,12 @@ static int __pci_dev_reset(struct pci_dev *dev, int probe)
|
|||||||
if (rc != -ENOTTY)
|
if (rc != -ENOTTY)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
rc = pcie_flr(dev, probe);
|
if (pcie_has_flr(dev)) {
|
||||||
if (rc != -ENOTTY)
|
if (!probe)
|
||||||
|
pcie_flr(dev);
|
||||||
|
rc = 0;
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
rc = pci_af_flr(dev, probe);
|
rc = pci_af_flr(dev, probe);
|
||||||
if (rc != -ENOTTY)
|
if (rc != -ENOTTY)
|
||||||
|
|||||||
@@ -1054,6 +1054,7 @@ int pcie_get_mps(struct pci_dev *dev);
|
|||||||
int pcie_set_mps(struct pci_dev *dev, int mps);
|
int pcie_set_mps(struct pci_dev *dev, int mps);
|
||||||
int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
|
int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
|
||||||
enum pcie_link_width *width);
|
enum pcie_link_width *width);
|
||||||
|
void pcie_flr(struct pci_dev *dev);
|
||||||
int __pci_reset_function(struct pci_dev *dev);
|
int __pci_reset_function(struct pci_dev *dev);
|
||||||
int __pci_reset_function_locked(struct pci_dev *dev);
|
int __pci_reset_function_locked(struct pci_dev *dev);
|
||||||
int pci_reset_function(struct pci_dev *dev);
|
int pci_reset_function(struct pci_dev *dev);
|
||||||
|
|||||||
Reference in New Issue
Block a user