From 682dfedcee2fa9a50cb53e3b30ff1ebe1f7dd659 Mon Sep 17 00:00:00 2001 From: Krzysztof Kazimierczak Date: Mon, 13 Jul 2020 13:53:13 -0700 Subject: [PATCH] ice: need_wakeup flag might not be set for Tx This is a port of i40e commit 705639572e8c ("i40e: need_wakeup flag might not be set for Tx"). Quoting the original commit message: "The need_wakeup flag for Tx might not be set for AF_XDP sockets that are only used to send packets. This happens if there is at least one outstanding packet that has not been completed by the hardware and we get that corresponding completion (which will not generate an interrupt since interrupts are disabled in the napi poll loop) between the time we stopped processing the Tx completions and interrupts are enabled again. In this case, the need_wakeup flag will have been cleared at the end of the Tx completion processing as we believe we will get an interrupt from the outstanding completion at a later point in time. But if this completion interrupt occurs before interrupts are enable, we lose it and should at that point really have set the need_wakeup flag since there are no more outstanding completions that can generate an interrupt to continue the processing. When this happens, user space will see a Tx queue need_wakeup of 0 and skip issuing a syscall, which means will never get into the Tx processing again and we have a deadlock." As a result, packet processing stops. This patch introduces a fix for this issue, by always setting the need_wakeup flag at the end of an interrupt processing. This ensures that the deadlock will not happen. Signed-off-by: Krzysztof Kazimierczak Tested-by: Andrew Bowers Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_xsk.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index 6badfd62dc63..87862918bc7a 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -706,8 +706,6 @@ static bool ice_xmit_zc(struct ice_ring *xdp_ring, int budget) if (tx_desc) { ice_xdp_ring_update_tail(xdp_ring); xsk_umem_consume_tx_done(xdp_ring->xsk_umem); - if (xsk_umem_uses_need_wakeup(xdp_ring->xsk_umem)) - xsk_clear_tx_need_wakeup(xdp_ring->xsk_umem); } return budget > 0 && work_done; @@ -783,12 +781,8 @@ bool ice_clean_tx_irq_zc(struct ice_ring *xdp_ring, int budget) if (xsk_frames) xsk_umem_complete_tx(xdp_ring->xsk_umem, xsk_frames); - if (xsk_umem_uses_need_wakeup(xdp_ring->xsk_umem)) { - if (xdp_ring->next_to_clean == xdp_ring->next_to_use) - xsk_set_tx_need_wakeup(xdp_ring->xsk_umem); - else - xsk_clear_tx_need_wakeup(xdp_ring->xsk_umem); - } + if (xsk_umem_uses_need_wakeup(xdp_ring->xsk_umem)) + xsk_set_tx_need_wakeup(xdp_ring->xsk_umem); ice_update_tx_ring_stats(xdp_ring, total_packets, total_bytes); xmit_done = ice_xmit_zc(xdp_ring, ICE_DFLT_IRQ_WORK);