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