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>
This commit is contained in:
Yi Zou 2009-11-06 12:56:00 +00:00 committed by David S. Miller
parent b352e40da8
commit 26f23d82dd
1 changed files with 51 additions and 1 deletions

View File

@ -226,6 +226,56 @@ static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
/* tx_buffer_info must be completely set up in the transmit path */
}
/**
* ixgbe_tx_is_paused - check if the tx ring is paused
* @adapter: the ixgbe adapter
* @tx_ring: the corresponding tx_ring
*
* If not in DCB mode, checks TFCS.TXOFF, otherwise, find out the
* corresponding TC of this tx_ring when checking TFCS.
*
* Returns : true if paused
*/
static inline bool ixgbe_tx_is_paused(struct ixgbe_adapter *adapter,
struct ixgbe_ring *tx_ring)
{
int tc;
u32 txoff = IXGBE_TFCS_TXOFF;
#ifdef CONFIG_IXGBE_DCB
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
int reg_idx = tx_ring->reg_idx;
int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
tc = reg_idx >> 2;
txoff = IXGBE_TFCS_TXOFF0;
} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
tc = 0;
txoff = IXGBE_TFCS_TXOFF;
if (dcb_i == 8) {
/* TC0, TC1 */
tc = reg_idx >> 5;
if (tc == 2) /* TC2, TC3 */
tc += (reg_idx - 64) >> 4;
else if (tc == 3) /* TC4, TC5, TC6, TC7 */
tc += 1 + ((reg_idx - 96) >> 3);
} else if (dcb_i == 4) {
/* TC0, TC1 */
tc = reg_idx >> 6;
if (tc == 1) {
tc += (reg_idx - 64) >> 5;
if (tc == 2) /* TC2, TC3 */
tc += (reg_idx - 96) >> 4;
}
}
}
txoff <<= tc;
}
#endif
return IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & txoff;
}
static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter,
struct ixgbe_ring *tx_ring,
unsigned int eop)
@ -237,7 +287,7 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter,
adapter->detect_tx_hung = false;
if (tx_ring->tx_buffer_info[eop].time_stamp &&
time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ) &&
!(IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF)) {
!ixgbe_tx_is_paused(adapter, tx_ring)) {
/* detected Tx unit hang */
union ixgbe_adv_tx_desc *tx_desc;
tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);