Skip to content

Commit 04d4105

Browse files
atbrady-intelJeff Kirsher
authored andcommitted
i40e/i40evf: use SW variables for hang detection
The i40e_detect_recover_hung function uses the i40e_get_tx_pending function to determine if there are packets stalled on the ring. i40e_get_tx_pending calculates the pending packets using the head writeback value and HW tail. If the queue is stopped and we lose the interrupt to update our next_to_clean then we a) won't get another interrupt to clean because queue is stopped b) we won't catch the problem with i40e_detect_recover_hung because the HW values look like there's no packets waiting to be transmitted. Using the SW values we can catch the issue because next_to_clean will be out of sync with head writeback. This has the added benefit being less CPU intensive because we don't need to reach into the hardware to get the values. Signed-off-by: Alan Brady <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 8cd5fe6 commit 04d4105

File tree

3 files changed

+13
-7
lines changed

3 files changed

+13
-7
lines changed

drivers/net/ethernet/intel/i40e/i40e_txrx.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -708,16 +708,22 @@ void i40e_free_tx_resources(struct i40e_ring *tx_ring)
708708
/**
709709
* i40e_get_tx_pending - how many tx descriptors not processed
710710
* @tx_ring: the ring of descriptors
711+
* @in_sw: use SW variables
711712
*
712713
* Since there is no access to the ring head register
713714
* in XL710, we need to use our local copies
714715
**/
715-
u32 i40e_get_tx_pending(struct i40e_ring *ring)
716+
u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw)
716717
{
717718
u32 head, tail;
718719

719-
head = i40e_get_head(ring);
720-
tail = readl(ring->tail);
720+
if (!in_sw) {
721+
head = i40e_get_head(ring);
722+
tail = readl(ring->tail);
723+
} else {
724+
head = ring->next_to_clean;
725+
tail = ring->next_to_use;
726+
}
721727

722728
if (head != tail)
723729
return (head < tail) ?
@@ -774,7 +780,7 @@ void i40e_detect_recover_hung(struct i40e_vsi *vsi)
774780
*/
775781
smp_rmb();
776782
tx_ring->tx_stats.prev_pkt_ctr =
777-
i40e_get_tx_pending(tx_ring) ? packets : -1;
783+
i40e_get_tx_pending(tx_ring, true) ? packets : -1;
778784
}
779785
}
780786
}
@@ -898,7 +904,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
898904
* them to be written back in case we stay in NAPI.
899905
* In this mode on X722 we do not enable Interrupt.
900906
*/
901-
unsigned int j = i40e_get_tx_pending(tx_ring);
907+
unsigned int j = i40e_get_tx_pending(tx_ring, false);
902908

903909
if (budget &&
904910
((j / WB_STRIDE) == 0) && (j > 0) &&

drivers/net/ethernet/intel/i40e/i40e_txrx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ void i40e_free_tx_resources(struct i40e_ring *tx_ring);
505505
void i40e_free_rx_resources(struct i40e_ring *rx_ring);
506506
int i40e_napi_poll(struct napi_struct *napi, int budget);
507507
void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector);
508-
u32 i40e_get_tx_pending(struct i40e_ring *ring);
508+
u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw);
509509
void i40e_detect_recover_hung(struct i40e_vsi *vsi);
510510
int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
511511
bool __i40e_chk_linearize(struct sk_buff *skb);

drivers/net/ethernet/intel/i40evf/i40e_txrx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ void i40evf_detect_recover_hung(struct i40e_vsi *vsi)
196196
*/
197197
smp_rmb();
198198
tx_ring->tx_stats.prev_pkt_ctr =
199-
i40evf_get_tx_pending(tx_ring, false) ? packets : -1;
199+
i40evf_get_tx_pending(tx_ring, true) ? packets : -1;
200200
}
201201
}
202202
}

0 commit comments

Comments
 (0)