i40e: Add a SW workaround for lost interrupts
This patch adds a workaround for cases where we might have interrupts that got lost but WB happened. If that happens without this patch we will see a tx_timeout. To work around it, this patch goes ahead and reschedules NAPI in that situation, if NAPI is not already scheduled. We also add a counter in ethtool to keep track of when we detect a case of tx_lost_interrupt. Note: napi_reschedule() can be safely called from process/service_task context and is done in other drivers as well without an issue. Change-ID: I00f98f1ce3774524d9421227652bef20fcbd0d20 Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:

committed by
Jeff Kirsher

parent
f734dfff2f
commit
dd353109e4
@@ -129,15 +129,19 @@ void i40evf_free_tx_resources(struct i40e_ring *tx_ring)
|
||||
/**
|
||||
* i40evf_get_tx_pending - how many Tx descriptors not processed
|
||||
* @tx_ring: the ring of descriptors
|
||||
* @in_sw: is tx_pending being checked in SW or HW
|
||||
*
|
||||
* Since there is no access to the ring head register
|
||||
* in XL710, we need to use our local copies
|
||||
**/
|
||||
u32 i40evf_get_tx_pending(struct i40e_ring *ring)
|
||||
u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw)
|
||||
{
|
||||
u32 head, tail;
|
||||
|
||||
head = i40e_get_head(ring);
|
||||
if (!in_sw)
|
||||
head = i40e_get_head(ring);
|
||||
else
|
||||
head = ring->next_to_clean;
|
||||
tail = readl(ring->tail);
|
||||
|
||||
if (head != tail)
|
||||
@@ -259,7 +263,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
|
||||
* them to be written back in case we stay in NAPI.
|
||||
* In this mode on X722 we do not enable Interrupt.
|
||||
*/
|
||||
j = i40evf_get_tx_pending(tx_ring);
|
||||
j = i40evf_get_tx_pending(tx_ring, false);
|
||||
|
||||
if (budget &&
|
||||
((j / (WB_STRIDE + 1)) == 0) && (j > 0) &&
|
||||
|
@@ -202,6 +202,7 @@ struct i40e_tx_queue_stats {
|
||||
u64 tx_done_old;
|
||||
u64 tx_linearize;
|
||||
u64 tx_force_wb;
|
||||
u64 tx_lost_interrupt;
|
||||
};
|
||||
|
||||
struct i40e_rx_queue_stats {
|
||||
@@ -326,7 +327,7 @@ void i40evf_free_tx_resources(struct i40e_ring *tx_ring);
|
||||
void i40evf_free_rx_resources(struct i40e_ring *rx_ring);
|
||||
int i40evf_napi_poll(struct napi_struct *napi, int budget);
|
||||
void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector);
|
||||
u32 i40evf_get_tx_pending(struct i40e_ring *ring);
|
||||
u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw);
|
||||
|
||||
/**
|
||||
* i40e_get_head - Retrieve head from head writeback
|
||||
|
Reference in New Issue
Block a user