Merge tag 'mips_4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
[linux-2.6-microblaze.git] / net / xdp / xsk.c
index 59fb7d3..4e937cd 100644 (file)
@@ -84,10 +84,8 @@ static int __xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
 {
        int err = xskq_produce_batch_desc(xs->rx, (u64)xdp->handle, len);
 
-       if (err) {
-               xdp_return_buff(xdp);
+       if (err)
                xs->rx_dropped++;
-       }
 
        return err;
 }
@@ -199,8 +197,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);
 }
@@ -215,9 +216,6 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
        struct sk_buff *skb;
        int err = 0;
 
-       if (unlikely(!xs->tx))
-               return -ENOBUFS;
-
        mutex_lock(&xs->mutex);
 
        while (xskq_peek_desc(xs->tx, &desc)) {
@@ -230,22 +228,13 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
                        goto out;
                }
 
-               if (xskq_reserve_addr(xs->umem->cq)) {
-                       err = -EAGAIN;
+               if (xskq_reserve_addr(xs->umem->cq))
                        goto out;
-               }
 
-               len = desc.len;
-               if (unlikely(len > xs->dev->mtu)) {
-                       err = -EMSGSIZE;
+               if (xs->queue_id >= xs->dev->real_num_tx_queues)
                        goto out;
-               }
-
-               if (xs->queue_id >= xs->dev->real_num_tx_queues) {
-                       err = -ENXIO;
-                       goto out;
-               }
 
+               len = desc.len;
                skb = sock_alloc_send_skb(sk, len, 1, &err);
                if (unlikely(!skb)) {
                        err = -EAGAIN;
@@ -268,15 +257,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:
@@ -297,6 +286,8 @@ static int xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
                return -ENXIO;
        if (unlikely(!(xs->dev->flags & IFF_UP)))
                return -ENETDOWN;
+       if (unlikely(!xs->tx))
+               return -ENOBUFS;
        if (need_wait)
                return -EOPNOTSUPP;
 
@@ -755,6 +746,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);