Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ixgbe: Fix checking TFCS register for TXOFF status when DCB is enabled

When DCB is enabled, the ixgbe_check_tx_hang() should check the corresponding
TC's TXOFF in TFCS based on the TC that the tx ring belongs to. Adds a
function to map from the tx_ring hw reg_idx to the correspodning TC and read
TFCS accordingly.

Signed-off-by: Yi Zou <yi.zou@intel.com>
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yi Zou and committed by
David S. Miller
26f23d82 b352e40d

+51 -1
+51 -1
drivers/net/ixgbe/ixgbe_main.c
··· 226 226 /* tx_buffer_info must be completely set up in the transmit path */ 227 227 } 228 228 229 + /** 230 + * ixgbe_tx_is_paused - check if the tx ring is paused 231 + * @adapter: the ixgbe adapter 232 + * @tx_ring: the corresponding tx_ring 233 + * 234 + * If not in DCB mode, checks TFCS.TXOFF, otherwise, find out the 235 + * corresponding TC of this tx_ring when checking TFCS. 236 + * 237 + * Returns : true if paused 238 + */ 239 + static inline bool ixgbe_tx_is_paused(struct ixgbe_adapter *adapter, 240 + struct ixgbe_ring *tx_ring) 241 + { 242 + int tc; 243 + u32 txoff = IXGBE_TFCS_TXOFF; 244 + 245 + #ifdef CONFIG_IXGBE_DCB 246 + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { 247 + int reg_idx = tx_ring->reg_idx; 248 + int dcb_i = adapter->ring_feature[RING_F_DCB].indices; 249 + 250 + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { 251 + tc = reg_idx >> 2; 252 + txoff = IXGBE_TFCS_TXOFF0; 253 + } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { 254 + tc = 0; 255 + txoff = IXGBE_TFCS_TXOFF; 256 + if (dcb_i == 8) { 257 + /* TC0, TC1 */ 258 + tc = reg_idx >> 5; 259 + if (tc == 2) /* TC2, TC3 */ 260 + tc += (reg_idx - 64) >> 4; 261 + else if (tc == 3) /* TC4, TC5, TC6, TC7 */ 262 + tc += 1 + ((reg_idx - 96) >> 3); 263 + } else if (dcb_i == 4) { 264 + /* TC0, TC1 */ 265 + tc = reg_idx >> 6; 266 + if (tc == 1) { 267 + tc += (reg_idx - 64) >> 5; 268 + if (tc == 2) /* TC2, TC3 */ 269 + tc += (reg_idx - 96) >> 4; 270 + } 271 + } 272 + } 273 + txoff <<= tc; 274 + } 275 + #endif 276 + return IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & txoff; 277 + } 278 + 229 279 static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, 230 280 struct ixgbe_ring *tx_ring, 231 281 unsigned int eop) ··· 287 237 adapter->detect_tx_hung = false; 288 238 if (tx_ring->tx_buffer_info[eop].time_stamp && 289 239 time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ) && 290 - !(IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF)) { 240 + !ixgbe_tx_is_paused(adapter, tx_ring)) { 291 241 /* detected Tx unit hang */ 292 242 union ixgbe_adv_tx_desc *tx_desc; 293 243 tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);