diff options
-rw-r--r-- | drivers/pci/pci.c | 98 | ||||
-rw-r--r-- | include/linux/pci.h | 2 | ||||
-rw-r--r-- | include/linux/pci_regs.h | 2 |
3 files changed, 102 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 | */ | ||
1766 | int 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 | } | ||
1800 | EXPORT_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 | */ | ||
1818 | int 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 | } | ||
1844 | EXPORT_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 | * |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 085187be29c7..f6f6810296e6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -626,6 +626,8 @@ int pcix_get_mmrbc(struct pci_dev *dev); | |||
626 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc); | 626 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc); |
627 | int pcie_get_readrq(struct pci_dev *dev); | 627 | int pcie_get_readrq(struct pci_dev *dev); |
628 | int pcie_set_readrq(struct pci_dev *dev, int rq); | 628 | int pcie_set_readrq(struct pci_dev *dev, int rq); |
629 | int pci_reset_function(struct pci_dev *dev); | ||
630 | int pci_execute_reset_function(struct pci_dev *dev); | ||
629 | void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); | 631 | void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); |
630 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); | 632 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); |
631 | int pci_select_bars(struct pci_dev *dev, unsigned long flags); | 633 | int pci_select_bars(struct pci_dev *dev, unsigned long flags); |
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index eb6686b88f9a..e5effd47ed74 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h | |||
@@ -377,6 +377,7 @@ | |||
377 | #define PCI_EXP_DEVCAP_RBER 0x8000 /* Role-Based Error Reporting */ | 377 | #define PCI_EXP_DEVCAP_RBER 0x8000 /* Role-Based Error Reporting */ |
378 | #define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ | 378 | #define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ |
379 | #define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ | 379 | #define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ |
380 | #define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ | ||
380 | #define PCI_EXP_DEVCTL 8 /* Device Control */ | 381 | #define PCI_EXP_DEVCTL 8 /* Device Control */ |
381 | #define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ | 382 | #define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ |
382 | #define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ | 383 | #define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ |
@@ -389,6 +390,7 @@ | |||
389 | #define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ | 390 | #define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ |
390 | #define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ | 391 | #define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ |
391 | #define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ | 392 | #define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ |
393 | #define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */ | ||
392 | #define PCI_EXP_DEVSTA 10 /* Device Status */ | 394 | #define PCI_EXP_DEVSTA 10 /* Device Status */ |
393 | #define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */ | 395 | #define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */ |
394 | #define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */ | 396 | #define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */ |