#define VHOST_NET_WEIGHT 0x80000
 
 /* Max number of packets transferred before requeueing the job.
- * Using this limit prevents one virtqueue from starving rx. */
-#define VHOST_NET_PKT_WEIGHT(vq) ((vq)->num * 2)
+ * Using this limit prevents one virtqueue from starving others with small
+ * pkts.
+ */
+#define VHOST_NET_PKT_WEIGHT 256
 
 /* MAX number of TX used buffers for outstanding zerocopy */
 #define VHOST_MAX_PEND 128
                        vhost_zerocopy_signal_used(net, vq);
                vhost_net_tx_packet(net);
                if (unlikely(total_len >= VHOST_NET_WEIGHT) ||
-                   unlikely(++sent_pkts >= VHOST_NET_PKT_WEIGHT(vq))) {
+                   unlikely(++sent_pkts >= VHOST_NET_PKT_WEIGHT)) {
                        vhost_poll_queue(&vq->poll);
                        break;
                }
        struct socket *sock;
        struct iov_iter fixup;
        __virtio16 num_buffers;
+       int recv_pkts = 0;
 
        mutex_lock_nested(&vq->mutex, 0);
        sock = vq->private_data;
                if (unlikely(vq_log))
                        vhost_log_write(vq, vq_log, log, vhost_len);
                total_len += vhost_len;
-               if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
+               if (unlikely(total_len >= VHOST_NET_WEIGHT) ||
+                   unlikely(++recv_pkts >= VHOST_NET_PKT_WEIGHT)) {
                        vhost_poll_queue(&vq->poll);
                        goto out;
                }