aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2008-11-11 04:17:48 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-01-07 14:12:25 -0500
commit1ca887970a3971a22e4875b7c6ad5ae3ce49f61a (patch)
tree8368a3f90da7ee894818658ff925478ef0b43947 /drivers
parentf7b7baae6b30ff04124259ff8d7c0c0d281320e6 (diff)
PCI: Extend pci_reset_function() to support PCI Advanced Features
Some PCI devices implement PCI Advanced Features, which means they support Function Level Reset(FLR). Implement support for that in pci_reset_function. Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/pci.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 62978f644a92..3c2fa2fdc9cd 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1789,6 +1789,43 @@ static int __pcie_flr(struct pci_dev *dev, int probe)
1789 return 0; 1789 return 0;
1790} 1790}
1791 1791
1792static int __pci_af_flr(struct pci_dev *dev, int probe)
1793{
1794 int cappos = pci_find_capability(dev, PCI_CAP_ID_AF);
1795 u8 status;
1796 u8 cap;
1797
1798 if (!cappos)
1799 return -ENOTTY;
1800 pci_read_config_byte(dev, cappos + PCI_AF_CAP, &cap);
1801 if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR))
1802 return -ENOTTY;
1803
1804 if (probe)
1805 return 0;
1806
1807 pci_block_user_cfg_access(dev);
1808
1809 /* Wait for Transaction Pending bit clean */
1810 msleep(100);
1811 pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
1812 if (status & PCI_AF_STATUS_TP) {
1813 dev_info(&dev->dev, "Busy after 100ms while trying to"
1814 " reset; sleeping for 1 second\n");
1815 ssleep(1);
1816 pci_read_config_byte(dev,
1817 cappos + PCI_AF_STATUS, &status);
1818 if (status & PCI_AF_STATUS_TP)
1819 dev_info(&dev->dev, "Still busy after 1s; "
1820 "proceeding with reset anyway\n");
1821 }
1822 pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
1823 mdelay(100);
1824
1825 pci_unblock_user_cfg_access(dev);
1826 return 0;
1827}
1828
1792static int __pci_reset_function(struct pci_dev *pdev, int probe) 1829static int __pci_reset_function(struct pci_dev *pdev, int probe)
1793{ 1830{
1794 int res; 1831 int res;
@@ -1797,6 +1834,10 @@ static int __pci_reset_function(struct pci_dev *pdev, int probe)
1797 if (res != -ENOTTY) 1834 if (res != -ENOTTY)
1798 return res; 1835 return res;
1799 1836
1837 res = __pci_af_flr(pdev, probe);
1838 if (res != -ENOTTY)
1839 return res;
1840
1800 return res; 1841 return res;
1801} 1842}
1802 1843