|
@@ -4368,17 +4368,41 @@ static void i40e_detect_recover_hung_queue(int q_idx, struct i40e_vsi *vsi)
|
|
else
|
|
else
|
|
val = rd32(&pf->hw, I40E_PFINT_DYN_CTL0);
|
|
val = rd32(&pf->hw, I40E_PFINT_DYN_CTL0);
|
|
|
|
|
|
|
|
+ /* Bail out if interrupts are disabled because napi_poll
|
|
|
|
+ * execution in-progress or will get scheduled soon.
|
|
|
|
+ * napi_poll cleans TX and RX queues and updates 'next_to_clean'.
|
|
|
|
+ */
|
|
|
|
+ if (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK))
|
|
|
|
+ return;
|
|
|
|
+
|
|
head = i40e_get_head(tx_ring);
|
|
head = i40e_get_head(tx_ring);
|
|
|
|
|
|
tx_pending = i40e_get_tx_pending(tx_ring);
|
|
tx_pending = i40e_get_tx_pending(tx_ring);
|
|
|
|
|
|
- /* Interrupts are disabled and TX pending is non-zero,
|
|
|
|
- * trigger the SW interrupt (don't wait). Worst case
|
|
|
|
- * there will be one extra interrupt which may result
|
|
|
|
- * into not cleaning any queues because queues are cleaned.
|
|
|
|
|
|
+ /* HW is done executing descriptors, updated HEAD write back,
|
|
|
|
+ * but SW hasn't processed those descriptors. If interrupt is
|
|
|
|
+ * not generated from this point ON, it could result into
|
|
|
|
+ * dev_watchdog detecting timeout on those netdev_queue,
|
|
|
|
+ * hence proactively trigger SW interrupt.
|
|
*/
|
|
*/
|
|
- if (tx_pending && (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK)))
|
|
|
|
- i40e_force_wb(vsi, tx_ring->q_vector);
|
|
|
|
|
|
+ if (tx_pending) {
|
|
|
|
+ /* NAPI Poll didn't run and clear since it was set */
|
|
|
|
+ if (test_and_clear_bit(I40E_Q_VECTOR_HUNG_DETECT,
|
|
|
|
+ &tx_ring->q_vector->hung_detected)) {
|
|
|
|
+ netdev_info(vsi->netdev, "VSI_seid %d, Hung TX queue %d, tx_pending: %d, NTC:0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x\n",
|
|
|
|
+ vsi->seid, q_idx, tx_pending,
|
|
|
|
+ tx_ring->next_to_clean, head,
|
|
|
|
+ tx_ring->next_to_use,
|
|
|
|
+ readl(tx_ring->tail));
|
|
|
|
+ netdev_info(vsi->netdev, "VSI_seid %d, Issuing force_wb for TX queue %d, Interrupt Reg: 0x%x\n",
|
|
|
|
+ vsi->seid, q_idx, val);
|
|
|
|
+ i40e_force_wb(vsi, tx_ring->q_vector);
|
|
|
|
+ } else {
|
|
|
|
+ /* First Chance - detected possible hung */
|
|
|
|
+ set_bit(I40E_Q_VECTOR_HUNG_DETECT,
|
|
|
|
+ &tx_ring->q_vector->hung_detected);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|