dev_kfree_skb_any(skb);
 }
 
-static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
-                                    struct mlx4_en_rx_ring *ring)
+static bool mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
+                                     struct mlx4_en_rx_ring *ring)
 {
-       int index = ring->prod & ring->size_mask;
+       u32 missing = ring->actual_size - (ring->prod - ring->cons);
 
-       while ((u32) (ring->prod - ring->cons) < ring->actual_size) {
-               if (mlx4_en_prepare_rx_desc(priv, ring, index,
+       /* Try to batch allocations, but not too much. */
+       if (missing < 8)
+               return false;
+       do {
+               if (mlx4_en_prepare_rx_desc(priv, ring,
+                                           ring->prod & ring->size_mask,
                                            GFP_ATOMIC | __GFP_COLD))
                        break;
                ring->prod++;
-               index = ring->prod & ring->size_mask;
-       }
+       } while (--missing);
+
+       return true;
 }
 
 /* When hardware doesn't strip the vlan, we need to calculate the checksum
 
 out:
        rcu_read_unlock();
-       if (doorbell_pending)
-               mlx4_en_xmit_doorbell(priv->tx_ring[TX_XDP][cq->ring]);
 
+       if (polled) {
+               if (doorbell_pending)
+                       mlx4_en_xmit_doorbell(priv->tx_ring[TX_XDP][cq->ring]);
+
+               mlx4_cq_set_ci(&cq->mcq);
+               wmb(); /* ensure HW sees CQ consumer before we post new buffers */
+               ring->cons = cq->mcq.cons_index;
+       }
        AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
-       mlx4_cq_set_ci(&cq->mcq);
-       wmb(); /* ensure HW sees CQ consumer before we post new buffers */
-       ring->cons = cq->mcq.cons_index;
-       mlx4_en_refill_rx_buffers(priv, ring);
-       mlx4_en_update_rx_prod_db(ring);
+
+       if (mlx4_en_refill_rx_buffers(priv, ring))
+               mlx4_en_update_rx_prod_db(ring);
+
        return polled;
 }
 
                        return budget;
 
                /* Current cpu is not according to smp_irq_affinity -
-                * probably affinity changed. need to stop this NAPI
-                * poll, and restart it on the right CPU
+                * probably affinity changed. Need to stop this NAPI
+                * poll, and restart it on the right CPU.
+                * Try to avoid returning a too small value (like 0),
+                * to not fool net_rx_action() and its netdev_budget
                 */
-               done = 0;
+               if (done)
+                       done--;
        }
        /* Done for now */
        if (napi_complete_done(napi, done))