diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_common.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_common.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 345c32eab4a5..6d87c7491d10 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c | |||
@@ -454,8 +454,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) | |||
454 | * Prevent the PCI-E bus from from hanging by disabling PCI-E master | 454 | * Prevent the PCI-E bus from from hanging by disabling PCI-E master |
455 | * access and verify no pending requests | 455 | * access and verify no pending requests |
456 | */ | 456 | */ |
457 | if (ixgbe_disable_pcie_master(hw) != 0) | 457 | ixgbe_disable_pcie_master(hw); |
458 | hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); | ||
459 | 458 | ||
460 | return 0; | 459 | return 0; |
461 | } | 460 | } |
@@ -2161,10 +2160,16 @@ out: | |||
2161 | **/ | 2160 | **/ |
2162 | s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) | 2161 | s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) |
2163 | { | 2162 | { |
2163 | struct ixgbe_adapter *adapter = hw->back; | ||
2164 | u32 i; | 2164 | u32 i; |
2165 | u32 reg_val; | 2165 | u32 reg_val; |
2166 | u32 number_of_queues; | 2166 | u32 number_of_queues; |
2167 | s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; | 2167 | s32 status = 0; |
2168 | u16 dev_status = 0; | ||
2169 | |||
2170 | /* Just jump out if bus mastering is already disabled */ | ||
2171 | if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) | ||
2172 | goto out; | ||
2168 | 2173 | ||
2169 | /* Disable the receive unit by stopping each queue */ | 2174 | /* Disable the receive unit by stopping each queue */ |
2170 | number_of_queues = hw->mac.max_rx_queues; | 2175 | number_of_queues = hw->mac.max_rx_queues; |
@@ -2181,13 +2186,43 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) | |||
2181 | IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val); | 2186 | IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val); |
2182 | 2187 | ||
2183 | for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { | 2188 | for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { |
2184 | if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) { | 2189 | if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) |
2185 | status = 0; | 2190 | goto check_device_status; |
2191 | udelay(100); | ||
2192 | } | ||
2193 | |||
2194 | hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n"); | ||
2195 | status = IXGBE_ERR_MASTER_REQUESTS_PENDING; | ||
2196 | |||
2197 | /* | ||
2198 | * Before proceeding, make sure that the PCIe block does not have | ||
2199 | * transactions pending. | ||
2200 | */ | ||
2201 | check_device_status: | ||
2202 | for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { | ||
2203 | pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS, | ||
2204 | &dev_status); | ||
2205 | if (!(dev_status & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) | ||
2186 | break; | 2206 | break; |
2187 | } | ||
2188 | udelay(100); | 2207 | udelay(100); |
2189 | } | 2208 | } |
2190 | 2209 | ||
2210 | if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT) | ||
2211 | hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n"); | ||
2212 | else | ||
2213 | goto out; | ||
2214 | |||
2215 | /* | ||
2216 | * Two consecutive resets are required via CTRL.RST per datasheet | ||
2217 | * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine | ||
2218 | * of this need. The first reset prevents new master requests from | ||
2219 | * being issued by our device. We then must wait 1usec for any | ||
2220 | * remaining completions from the PCIe bus to trickle in, and then reset | ||
2221 | * again to clear out any effects they may have had on our device. | ||
2222 | */ | ||
2223 | hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; | ||
2224 | |||
2225 | out: | ||
2191 | return status; | 2226 | return status; |
2192 | } | 2227 | } |
2193 | 2228 | ||