Blame 0006-rtl8139-flush-queued-packets-when-RxBufPtr-is-writte.patch

77dc39
From 4044e0670486ad089367952843f17351c4f6faa0 Mon Sep 17 00:00:00 2001
77dc39
From: Stefan Hajnoczi <stefanha@redhat.com>
77dc39
Date: Wed, 22 May 2013 14:50:18 +0200
77dc39
Subject: [PATCH] rtl8139: flush queued packets when RxBufPtr is written
77dc39
77dc39
Net queues support efficient "receive disable".  For example, tap's file
77dc39
descriptor will not be polled while its peer has receive disabled.  This
77dc39
saves CPU cycles for needlessly copying and then dropping packets which
77dc39
the peer cannot receive.
77dc39
77dc39
rtl8139 is missing the qemu_flush_queued_packets() call that wakes the
77dc39
queue up when receive becomes possible again.
77dc39
77dc39
As a result, the Windows 7 guest driver reaches a state where the
77dc39
rtl8139 cannot receive packets.  The driver has actually refilled the
77dc39
receive buffer but we never resume reception.
77dc39
77dc39
The bug can be reproduced by running a large FTP 'get' inside a Windows
77dc39
7 guest:
77dc39
77dc39
  $ qemu -netdev tap,id=tap0,...
77dc39
         -device rtl8139,netdev=tap0
77dc39
77dc39
The Linux guest driver does not trigger the bug, probably due to a
77dc39
different buffer management strategy.
77dc39
77dc39
Reported-by: Oliver Francke <oliver.francke@filoo.de>
77dc39
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
77dc39
(cherry picked from commit 00b7ade807b5ce6779ddd86ce29c5521ec5c529a)
77dc39
---
77dc39
 hw/net/rtl8139.c | 3 +++
77dc39
 1 file changed, 3 insertions(+)
77dc39
77dc39
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
77dc39
index 9369507..7993f9f 100644
77dc39
--- a/hw/net/rtl8139.c
77dc39
+++ b/hw/net/rtl8139.c
77dc39
@@ -2575,6 +2575,9 @@ static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val)
77dc39
     /* this value is off by 16 */
77dc39
     s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);
77dc39
 
77dc39
+    /* more buffer space may be available so try to receive */
77dc39
+    qemu_flush_queued_packets(qemu_get_queue(s->nic));
77dc39
+
77dc39
     DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
77dc39
         s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
77dc39
 }