aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Karlsson <magnus.karlsson@intel.com>2020-12-18 14:45:25 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-01-17 14:17:05 +0100
commitbe665727363f71f6417693719f975bdbc0e9aaf0 (patch)
tree2b9f3d03b5b0ddef2bf6897a3f3260a6b8beca62
parent9ad0375ed292b20e6737794a680fad8f842a6672 (diff)
downloadkernel_replicant_linux-be665727363f71f6417693719f975bdbc0e9aaf0.tar.gz
kernel_replicant_linux-be665727363f71f6417693719f975bdbc0e9aaf0.tar.bz2
kernel_replicant_linux-be665727363f71f6417693719f975bdbc0e9aaf0.zip
xsk: Rollback reservation at NETDEV_TX_BUSY
commit b1b95cb5c0a9694d47d5f845ba97e226cfda957d upstream. Rollback the reservation in the completion ring when we get a NETDEV_TX_BUSY. When this error is received from the driver, we are supposed to let the user application retry the transmit again. And in order to do this, we need to roll back the failed send so it can be retried. Unfortunately, we did not cancel the reservation we had made in the completion ring. By not doing this, we actually make the completion ring one entry smaller per NETDEV_TX_BUSY error we get, and after enough of these errors the completion ring will be of size zero and transmit will stop working. Fix this by cancelling the reservation when we get a NETDEV_TX_BUSY error. Fixes: 642e450b6b59 ("xsk: Do not discard packet when NETDEV_TX_BUSY") Reported-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Björn Töpel <bjorn.topel@intel.com> Link: https://lore.kernel.org/bpf/20201218134525.13119-3-magnus.karlsson@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/xdp/xsk.c3
-rw-r--r--net/xdp/xsk_queue.h5
2 files changed, 8 insertions, 0 deletions
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
index f20eba841460..d5f42c62fd79 100644
--- a/net/xdp/xsk.c
+++ b/net/xdp/xsk.c
@@ -428,6 +428,9 @@ static int xsk_generic_xmit(struct sock *sk)
if (err == NETDEV_TX_BUSY) {
/* Tell user-space to retry the send */
skb->destructor = sock_wfree;
+ spin_lock_irqsave(&xs->pool->cq_lock, flags);
+ xskq_prod_cancel(xs->pool->cq);
+ spin_unlock_irqrestore(&xs->pool->cq_lock, flags);
/* Free skb without triggering the perf drop trace */
consume_skb(skb);
err = -EAGAIN;
diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h
index 9e71b9f27679..ef6de0fb4e31 100644
--- a/net/xdp/xsk_queue.h
+++ b/net/xdp/xsk_queue.h
@@ -286,6 +286,11 @@ static inline bool xskq_prod_is_full(struct xsk_queue *q)
return !free_entries;
}
+static inline void xskq_prod_cancel(struct xsk_queue *q)
+{
+ q->cached_prod--;
+}
+
static inline int xskq_prod_reserve(struct xsk_queue *q)
{
if (xskq_prod_is_full(q))