aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2008-10-21 05:38:25 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-10-22 19:42:35 -0400
commit8dd7f8036c123296fc4214f9d8810eb485570422 (patch)
tree0c6cab9083be724d2c72ba4aabef9e3b0dffd7fc /drivers/pci/pci.c
parentc4ed02fae78bf6cea0b22edd34a67df972f29832 (diff)
PCI: add support for function level reset
Sometimes, it's necessary to enable software's ability to quiesce and reset endpoint hardware with function-level granularity, so provide support for it. The patch implement Function Level Reset(FLR) feature following PCI-e spec. And this is the first step. We would add more generic method, like D0/D3, to allow more devices support this function. The patch contains two functions. pcie_reset_function() is the new driver API, and, contains some action to quiesce a device. The other function is a helper: pcie_execute_reset_function() just executes the reset for a particular device function. Current the usage model is in KVM. Function reset is necessary for assigning device to a guest, or moving it between partitions. For Function Level Reset(FLR), please refer to PCI Express spec chapter 6.6.2. Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index aee73cf251b6..533aeb5fcbe4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -18,6 +18,7 @@
18#include <linux/log2.h> 18#include <linux/log2.h>
19#include <linux/pci-aspm.h> 19#include <linux/pci-aspm.h>
20#include <linux/pm_wakeup.h> 20#include <linux/pm_wakeup.h>
21#include <linux/interrupt.h>
21#include <asm/dma.h> /* isa_dma_bridge_buggy */ 22#include <asm/dma.h> /* isa_dma_bridge_buggy */
22#include "pci.h" 23#include "pci.h"
23 24
@@ -1746,6 +1747,103 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary);
1746#endif 1747#endif
1747 1748
1748/** 1749/**
1750 * pci_execute_reset_function() - Reset a PCI device function
1751 * @dev: Device function to reset
1752 *
1753 * Some devices allow an individual function to be reset without affecting
1754 * other functions in the same device. The PCI device must be responsive
1755 * to PCI config space in order to use this function.
1756 *
1757 * The device function is presumed to be unused when this function is called.
1758 * Resetting the device will make the contents of PCI configuration space
1759 * random, so any caller of this must be prepared to reinitialise the
1760 * device including MSI, bus mastering, BARs, decoding IO and memory spaces,
1761 * etc.
1762 *
1763 * Returns 0 if the device function was successfully reset or -ENOTTY if the
1764 * device doesn't support resetting a single function.
1765 */
1766int pci_execute_reset_function(struct pci_dev *dev)
1767{
1768 u16 status;
1769 u32 cap;
1770 int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP);
1771
1772 if (!exppos)
1773 return -ENOTTY;
1774 pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap);
1775 if (!(cap & PCI_EXP_DEVCAP_FLR))
1776 return -ENOTTY;
1777
1778 pci_block_user_cfg_access(dev);
1779
1780 /* Wait for Transaction Pending bit clean */
1781 msleep(100);
1782 pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
1783 if (status & PCI_EXP_DEVSTA_TRPND) {
1784 dev_info(&dev->dev, "Busy after 100ms while trying to reset; "
1785 "sleeping for 1 second\n");
1786 ssleep(1);
1787 pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
1788 if (status & PCI_EXP_DEVSTA_TRPND)
1789 dev_info(&dev->dev, "Still busy after 1s; "
1790 "proceeding with reset anyway\n");
1791 }
1792
1793 pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL,
1794 PCI_EXP_DEVCTL_BCR_FLR);
1795 mdelay(100);
1796
1797 pci_unblock_user_cfg_access(dev);
1798 return 0;
1799}
1800EXPORT_SYMBOL_GPL(pci_execute_reset_function);
1801
1802/**
1803 * pci_reset_function() - quiesce and reset a PCI device function
1804 * @dev: Device function to reset
1805 *
1806 * Some devices allow an individual function to be reset without affecting
1807 * other functions in the same device. The PCI device must be responsive
1808 * to PCI config space in order to use this function.
1809 *
1810 * This function does not just reset the PCI portion of a device, but
1811 * clears all the state associated with the device. This function differs
1812 * from pci_execute_reset_function in that it saves and restores device state
1813 * over the reset.
1814 *
1815 * Returns 0 if the device function was successfully reset or -ENOTTY if the
1816 * device doesn't support resetting a single function.
1817 */
1818int pci_reset_function(struct pci_dev *dev)
1819{
1820 u32 cap;
1821 int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP);
1822 int r;
1823
1824 if (!exppos)
1825 return -ENOTTY;
1826 pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap);
1827 if (!(cap & PCI_EXP_DEVCAP_FLR))
1828 return -ENOTTY;
1829
1830 if (!dev->msi_enabled && !dev->msix_enabled)
1831 disable_irq(dev->irq);
1832 pci_save_state(dev);
1833
1834 pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
1835
1836 r = pci_execute_reset_function(dev);
1837
1838 pci_restore_state(dev);
1839 if (!dev->msi_enabled && !dev->msix_enabled)
1840 enable_irq(dev->irq);
1841
1842 return r;
1843}
1844EXPORT_SYMBOL_GPL(pci_reset_function);
1845
1846/**
1749 * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count 1847 * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
1750 * @dev: PCI device to query 1848 * @dev: PCI device to query
1751 * 1849 *