aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorYu Zhao <yu.zhao@intel.com>2009-06-13 03:52:13 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-06-16 17:30:15 -0400
commit8c1c699fec9e9021bf6ff0285dee086bb27aec90 (patch)
tree4af7bd96c1b651633ff7b6721959aeacd120e4ee /drivers/pci/pci.c
parentc465def6bfe834b62623caa9b98f2d4f4739875a (diff)
PCI: cleanup Function Level Reset
This patch enhances the FLR functions: 1) remove disable_irq() so the shared IRQ won't be disabled. 2) replace the 1s wait with 100, 200 and 400ms wait intervals for the Pending Transaction. 3) replace mdelay() with msleep(). 4) add might_sleep(). 5) lock the device to prevent PM suspend from accessing the CSRs during the reset. 6) coding style fixes. Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Yu Zhao <yu.zhao@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c166
1 files changed, 84 insertions, 82 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8ea911e55722..6a052ada3fe8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2055,111 +2055,112 @@ int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
2055EXPORT_SYMBOL(pci_set_dma_seg_boundary); 2055EXPORT_SYMBOL(pci_set_dma_seg_boundary);
2056#endif 2056#endif
2057 2057
2058static int __pcie_flr(struct pci_dev *dev, int probe) 2058static int pcie_flr(struct pci_dev *dev, int probe)
2059{ 2059{
2060 u16 status; 2060 int i;
2061 int pos;
2061 u32 cap; 2062 u32 cap;
2062 int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP); 2063 u16 status;
2063 2064
2064 if (!exppos) 2065 pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
2066 if (!pos)
2065 return -ENOTTY; 2067 return -ENOTTY;
2066 pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap); 2068
2069 pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap);
2067 if (!(cap & PCI_EXP_DEVCAP_FLR)) 2070 if (!(cap & PCI_EXP_DEVCAP_FLR))
2068 return -ENOTTY; 2071 return -ENOTTY;
2069 2072
2070 if (probe) 2073 if (probe)
2071 return 0; 2074 return 0;
2072 2075
2073 pci_block_user_cfg_access(dev);
2074
2075 /* Wait for Transaction Pending bit clean */ 2076 /* Wait for Transaction Pending bit clean */
2076 pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); 2077 for (i = 0; i < 4; i++) {
2077 if (!(status & PCI_EXP_DEVSTA_TRPND)) 2078 if (i)
2078 goto transaction_done; 2079 msleep((1 << (i - 1)) * 100);
2079 2080
2080 msleep(100); 2081 pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
2081 pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); 2082 if (!(status & PCI_EXP_DEVSTA_TRPND))
2082 if (!(status & PCI_EXP_DEVSTA_TRPND)) 2083 goto clear;
2083 goto transaction_done; 2084 }
2084 2085
2085 dev_info(&dev->dev, "Busy after 100ms while trying to reset; " 2086 dev_err(&dev->dev, "transaction is not cleared; "
2086 "sleeping for 1 second\n"); 2087 "proceeding with reset anyway\n");
2087 ssleep(1); 2088
2088 pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); 2089clear:
2089 if (status & PCI_EXP_DEVSTA_TRPND) 2090 pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
2090 dev_info(&dev->dev, "Still busy after 1s; "
2091 "proceeding with reset anyway\n");
2092
2093transaction_done:
2094 pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL,
2095 PCI_EXP_DEVCTL_BCR_FLR); 2091 PCI_EXP_DEVCTL_BCR_FLR);
2096 mdelay(100); 2092 msleep(100);
2097 2093
2098 pci_unblock_user_cfg_access(dev);
2099 return 0; 2094 return 0;
2100} 2095}
2101 2096
2102static int __pci_af_flr(struct pci_dev *dev, int probe) 2097static int pci_af_flr(struct pci_dev *dev, int probe)
2103{ 2098{
2104 int cappos = pci_find_capability(dev, PCI_CAP_ID_AF); 2099 int i;
2105 u8 status; 2100 int pos;
2106 u8 cap; 2101 u8 cap;
2102 u8 status;
2107 2103
2108 if (!cappos) 2104 pos = pci_find_capability(dev, PCI_CAP_ID_AF);
2105 if (!pos)
2109 return -ENOTTY; 2106 return -ENOTTY;
2110 pci_read_config_byte(dev, cappos + PCI_AF_CAP, &cap); 2107
2108 pci_read_config_byte(dev, pos + PCI_AF_CAP, &cap);
2111 if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR)) 2109 if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR))
2112 return -ENOTTY; 2110 return -ENOTTY;
2113 2111
2114 if (probe) 2112 if (probe)
2115 return 0; 2113 return 0;
2116 2114
2117 pci_block_user_cfg_access(dev);
2118
2119 /* Wait for Transaction Pending bit clean */ 2115 /* Wait for Transaction Pending bit clean */
2120 pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); 2116 for (i = 0; i < 4; i++) {
2121 if (!(status & PCI_AF_STATUS_TP)) 2117 if (i)
2122 goto transaction_done; 2118 msleep((1 << (i - 1)) * 100);
2119
2120 pci_read_config_byte(dev, pos + PCI_AF_STATUS, &status);
2121 if (!(status & PCI_AF_STATUS_TP))
2122 goto clear;
2123 }
2124
2125 dev_err(&dev->dev, "transaction is not cleared; "
2126 "proceeding with reset anyway\n");
2123 2127
2128clear:
2129 pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
2124 msleep(100); 2130 msleep(100);
2125 pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); 2131
2126 if (!(status & PCI_AF_STATUS_TP))
2127 goto transaction_done;
2128
2129 dev_info(&dev->dev, "Busy after 100ms while trying to"
2130 " reset; sleeping for 1 second\n");
2131 ssleep(1);
2132 pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
2133 if (status & PCI_AF_STATUS_TP)
2134 dev_info(&dev->dev, "Still busy after 1s; "
2135 "proceeding with reset anyway\n");
2136
2137transaction_done:
2138 pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
2139 mdelay(100);
2140
2141 pci_unblock_user_cfg_access(dev);
2142 return 0; 2132 return 0;
2143} 2133}
2144 2134
2145static int __pci_reset_function(struct pci_dev *pdev, int probe) 2135static int pci_dev_reset(struct pci_dev *dev, int probe)
2146{ 2136{
2147 int res; 2137 int rc;
2138
2139 might_sleep();
2140
2141 if (!probe) {
2142 pci_block_user_cfg_access(dev);
2143 /* block PM suspend, driver probe, etc. */
2144 down(&dev->dev.sem);
2145 }
2148 2146
2149 res = __pcie_flr(pdev, probe); 2147 rc = pcie_flr(dev, probe);
2150 if (res != -ENOTTY) 2148 if (rc != -ENOTTY)
2151 return res; 2149 goto done;
2152 2150
2153 res = __pci_af_flr(pdev, probe); 2151 rc = pci_af_flr(dev, probe);
2154 if (res != -ENOTTY) 2152done:
2155 return res; 2153 if (!probe) {
2154 up(&dev->dev.sem);
2155 pci_unblock_user_cfg_access(dev);
2156 }
2156 2157
2157 return res; 2158 return rc;
2158} 2159}
2159 2160
2160/** 2161/**
2161 * pci_execute_reset_function() - Reset a PCI device function 2162 * __pci_reset_function - reset a PCI device function
2162 * @dev: Device function to reset 2163 * @dev: PCI device to reset
2163 * 2164 *
2164 * Some devices allow an individual function to be reset without affecting 2165 * Some devices allow an individual function to be reset without affecting
2165 * other functions in the same device. The PCI device must be responsive 2166 * other functions in the same device. The PCI device must be responsive
@@ -2171,18 +2172,18 @@ static int __pci_reset_function(struct pci_dev *pdev, int probe)
2171 * device including MSI, bus mastering, BARs, decoding IO and memory spaces, 2172 * device including MSI, bus mastering, BARs, decoding IO and memory spaces,
2172 * etc. 2173 * etc.
2173 * 2174 *
2174 * Returns 0 if the device function was successfully reset or -ENOTTY if the 2175 * Returns 0 if the device function was successfully reset or negative if the
2175 * device doesn't support resetting a single function. 2176 * device doesn't support resetting a single function.
2176 */ 2177 */
2177int pci_execute_reset_function(struct pci_dev *dev) 2178int __pci_reset_function(struct pci_dev *dev)
2178{ 2179{
2179 return __pci_reset_function(dev, 0); 2180 return pci_dev_reset(dev, 0);
2180} 2181}
2181EXPORT_SYMBOL_GPL(pci_execute_reset_function); 2182EXPORT_SYMBOL_GPL(__pci_reset_function);
2182 2183
2183/** 2184/**
2184 * pci_reset_function() - quiesce and reset a PCI device function 2185 * pci_reset_function - quiesce and reset a PCI device function
2185 * @dev: Device function to reset 2186 * @dev: PCI device to reset
2186 * 2187 *
2187 * Some devices allow an individual function to be reset without affecting 2188 * Some devices allow an individual function to be reset without affecting
2188 * other functions in the same device. The PCI device must be responsive 2189 * other functions in the same device. The PCI device must be responsive
@@ -2190,32 +2191,33 @@ EXPORT_SYMBOL_GPL(pci_execute_reset_function);
2190 * 2191 *
2191 * This function does not just reset the PCI portion of a device, but 2192 * This function does not just reset the PCI portion of a device, but
2192 * clears all the state associated with the device. This function differs 2193 * clears all the state associated with the device. This function differs
2193 * from pci_execute_reset_function in that it saves and restores device state 2194 * from __pci_reset_function in that it saves and restores device state
2194 * over the reset. 2195 * over the reset.
2195 * 2196 *
2196 * Returns 0 if the device function was successfully reset or -ENOTTY if the 2197 * Returns 0 if the device function was successfully reset or negative if the
2197 * device doesn't support resetting a single function. 2198 * device doesn't support resetting a single function.
2198 */ 2199 */
2199int pci_reset_function(struct pci_dev *dev) 2200int pci_reset_function(struct pci_dev *dev)
2200{ 2201{
2201 int r = __pci_reset_function(dev, 1); 2202 int rc;
2202 2203
2203 if (r < 0) 2204 rc = pci_dev_reset(dev, 1);
2204 return r; 2205 if (rc)
2206 return rc;
2205 2207
2206 if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0)
2207 disable_irq(dev->irq);
2208 pci_save_state(dev); 2208 pci_save_state(dev);
2209 2209
2210 /*
2211 * both INTx and MSI are disabled after the Interrupt Disable bit
2212 * is set and the Bus Master bit is cleared.
2213 */
2210 pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); 2214 pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
2211 2215
2212 r = pci_execute_reset_function(dev); 2216 rc = pci_dev_reset(dev, 0);
2213 2217
2214 pci_restore_state(dev); 2218 pci_restore_state(dev);
2215 if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0)
2216 enable_irq(dev->irq);
2217 2219
2218 return r; 2220 return rc;
2219} 2221}
2220EXPORT_SYMBOL_GPL(pci_reset_function); 2222EXPORT_SYMBOL_GPL(pci_reset_function);
2221 2223