|
@@ -199,8 +199,11 @@ static void xsk_destruct_skb(struct sk_buff *skb)
|
|
|
{
|
|
|
u64 addr = (u64)(long)skb_shinfo(skb)->destructor_arg;
|
|
|
struct xdp_sock *xs = xdp_sk(skb->sk);
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
+ spin_lock_irqsave(&xs->tx_completion_lock, flags);
|
|
|
WARN_ON_ONCE(xskq_produce_addr(xs->umem->cq, addr));
|
|
|
+ spin_unlock_irqrestore(&xs->tx_completion_lock, flags);
|
|
|
|
|
|
sock_wfree(skb);
|
|
|
}
|
|
@@ -268,15 +271,15 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
|
|
|
skb->destructor = xsk_destruct_skb;
|
|
|
|
|
|
err = dev_direct_xmit(skb, xs->queue_id);
|
|
|
+ xskq_discard_desc(xs->tx);
|
|
|
/* Ignore NET_XMIT_CN as packet might have been sent */
|
|
|
if (err == NET_XMIT_DROP || err == NETDEV_TX_BUSY) {
|
|
|
- err = -EAGAIN;
|
|
|
- /* SKB consumed by dev_direct_xmit() */
|
|
|
+ /* SKB completed but not sent */
|
|
|
+ err = -EBUSY;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
sent_frame = true;
|
|
|
- xskq_discard_desc(xs->tx);
|
|
|
}
|
|
|
|
|
|
out:
|
|
@@ -755,6 +758,7 @@ static int xsk_create(struct net *net, struct socket *sock, int protocol,
|
|
|
|
|
|
xs = xdp_sk(sk);
|
|
|
mutex_init(&xs->mutex);
|
|
|
+ spin_lock_init(&xs->tx_completion_lock);
|
|
|
|
|
|
local_bh_disable();
|
|
|
sock_prot_inuse_add(net, &xsk_proto, 1);
|