static int mlx5e_alloc_rx_wqes(struct mlx5e_rq *rq, u16 ix, u8 wqe_bulk)
 {
        struct mlx5_wq_cyc *wq = &rq->wqe.wq;
-       int err;
        int i;
 
        if (rq->xsk_pool) {
        }
 
        for (i = 0; i < wqe_bulk; i++) {
-               struct mlx5e_rx_wqe_cyc *wqe = mlx5_wq_cyc_get_wqe(wq, ix + i);
+               int j = mlx5_wq_cyc_ctr2ix(wq, ix + i);
+               struct mlx5e_rx_wqe_cyc *wqe;
 
-               err = mlx5e_alloc_rx_wqe(rq, wqe, ix + i);
-               if (unlikely(err))
-                       goto free_wqes;
-       }
+               wqe = mlx5_wq_cyc_get_wqe(wq, j);
 
-       return 0;
-
-free_wqes:
-       while (--i >= 0)
-               mlx5e_dealloc_rx_wqe(rq, ix + i);
+               if (unlikely(mlx5e_alloc_rx_wqe(rq, wqe, j)))
+                       break;
+       }
 
-       return err;
+       return i;
 }
 
 static inline void
 INDIRECT_CALLABLE_SCOPE bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq)
 {
        struct mlx5_wq_cyc *wq = &rq->wqe.wq;
+       bool busy = false;
        u8 wqe_bulk;
-       int err;
 
        if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state)))
                return false;
 
        do {
                u16 head = mlx5_wq_cyc_get_head(wq);
+               int count;
+               u8 bulk;
 
-               err = mlx5e_alloc_rx_wqes(rq, head, wqe_bulk);
-               if (unlikely(err)) {
+               /* Don't allow any newly allocated WQEs to share the same page
+                * with old WQEs that aren't completed yet. Stop earlier.
+                */
+               bulk = wqe_bulk - ((head + wqe_bulk) & rq->wqe.info.wqe_index_mask);
+
+               count = mlx5e_alloc_rx_wqes(rq, head, bulk);
+               if (likely(count > 0))
+                       mlx5_wq_cyc_push_n(wq, count);
+               if (unlikely(count != bulk)) {
                        rq->stats->buff_alloc_err++;
+                       busy = true;
                        break;
                }
-
-               mlx5_wq_cyc_push_n(wq, wqe_bulk);
        } while (mlx5_wq_cyc_missing(wq) >= wqe_bulk);
 
        /* ensure wqes are visible to device before updating doorbell record */
 
        mlx5_wq_cyc_update_db_record(wq);
 
-       return !!err;
+       return busy;
 }
 
 void mlx5e_free_icosq_descs(struct mlx5e_icosq *sq)