u64 addr;
        int err;
 
-       if (xs->dev != xdp->rxq->dev || xs->queue_id != xdp->rxq->queue_index)
-               return -EINVAL;
+       spin_lock_bh(&xs->rx_lock);
+
+       if (xs->dev != xdp->rxq->dev || xs->queue_id != xdp->rxq->queue_index) {
+               err = -EINVAL;
+               goto out_unlock;
+       }
 
        if (!xskq_peek_addr(xs->umem->fq, &addr) ||
            len > xs->umem->chunk_size_nohr - XDP_PACKET_HEADROOM) {
-               xs->rx_dropped++;
-               return -ENOSPC;
+               err = -ENOSPC;
+               goto out_drop;
        }
 
        addr += xs->umem->headroom;
        memcpy(buffer, xdp->data_meta, len + metalen);
        addr += metalen;
        err = xskq_produce_batch_desc(xs->rx, addr, len);
-       if (!err) {
-               xskq_discard_addr(xs->umem->fq);
-               xsk_flush(xs);
-               return 0;
-       }
+       if (err)
+               goto out_drop;
+
+       xskq_discard_addr(xs->umem->fq);
+       xskq_produce_flush_desc(xs->rx);
 
+       spin_unlock_bh(&xs->rx_lock);
+
+       xs->sk.sk_data_ready(&xs->sk);
+       return 0;
+
+out_drop:
        xs->rx_dropped++;
+out_unlock:
+       spin_unlock_bh(&xs->rx_lock);
        return err;
 }
 
 
        xs = xdp_sk(sk);
        mutex_init(&xs->mutex);
+       spin_lock_init(&xs->rx_lock);
        spin_lock_init(&xs->tx_completion_lock);
 
        mutex_lock(&net->xdp.lock);