Merge tag 'devicetree-fixes-for-5.12-1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / net / xdp / xsk.c
index 4a83117..4faabd1 100644 (file)
@@ -184,12 +184,13 @@ static void xsk_copy_xdp(struct xdp_buff *to, struct xdp_buff *from, u32 len)
        memcpy(to_buf, from_buf, len + metalen);
 }
 
-static int __xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len,
-                    bool explicit_free)
+static int __xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
 {
        struct xdp_buff *xsk_xdp;
        int err;
+       u32 len;
 
+       len = xdp->data_end - xdp->data;
        if (len > xsk_pool_get_rx_frame_size(xs->pool)) {
                xs->rx_dropped++;
                return -ENOSPC;
@@ -207,8 +208,6 @@ static int __xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len,
                xsk_buff_free(xsk_xdp);
                return err;
        }
-       if (explicit_free)
-               xdp_return_buff(xdp);
        return 0;
 }
 
@@ -230,11 +229,8 @@ static bool xsk_is_bound(struct xdp_sock *xs)
        return false;
 }
 
-static int xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp,
-                  bool explicit_free)
+static int xsk_rcv_check(struct xdp_sock *xs, struct xdp_buff *xdp)
 {
-       u32 len;
-
        if (!xsk_is_bound(xs))
                return -EINVAL;
 
@@ -242,11 +238,7 @@ static int xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp,
                return -EINVAL;
 
        sk_mark_napi_id_once_xdp(&xs->sk, xdp);
-       len = xdp->data_end - xdp->data;
-
-       return xdp->rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL ?
-               __xsk_rcv_zc(xs, xdp, len) :
-               __xsk_rcv(xs, xdp, len, explicit_free);
+       return 0;
 }
 
 static void xsk_flush(struct xdp_sock *xs)
@@ -261,18 +253,41 @@ int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
        int err;
 
        spin_lock_bh(&xs->rx_lock);
-       err = xsk_rcv(xs, xdp, false);
-       xsk_flush(xs);
+       err = xsk_rcv_check(xs, xdp);
+       if (!err) {
+               err = __xsk_rcv(xs, xdp);
+               xsk_flush(xs);
+       }
        spin_unlock_bh(&xs->rx_lock);
        return err;
 }
 
+static int xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
+{
+       int err;
+       u32 len;
+
+       err = xsk_rcv_check(xs, xdp);
+       if (err)
+               return err;
+
+       if (xdp->rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL) {
+               len = xdp->data_end - xdp->data;
+               return __xsk_rcv_zc(xs, xdp, len);
+       }
+
+       err = __xsk_rcv(xs, xdp);
+       if (!err)
+               xdp_return_buff(xdp);
+       return err;
+}
+
 int __xsk_map_redirect(struct xdp_sock *xs, struct xdp_buff *xdp)
 {
        struct list_head *flush_list = this_cpu_ptr(&xskmap_flush_list);
        int err;
 
-       err = xsk_rcv(xs, xdp, true);
+       err = xsk_rcv(xs, xdp);
        if (err)
                return err;