diff options
author | Avi Kivity <avi@redhat.com> | 2012-07-16 10:52:03 +0300 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2012-07-16 10:52:03 +0300 |
commit | 7fa12eb15f95c269f488fce4096093c96dbaffab (patch) | |
tree | 8ca766bebdead1ae21819bdc691b1097008ae834 /hw/rtl8139.c | |
parent | 6f82a5ea52302bab33287b0191538be6f9138637 (diff) | |
parent | 785adb09b9fd0d4df6707f00247ec519c42fcfc6 (diff) |
Merge tag 'v1.1.1' into stable-1.1qemu-kvm-1.1.1
* tag 'v1.1.1': (34 commits)
update VERSION for v1.1.1
s390x: fix s390 virtio aliases
rtl8139: validate rx ring before receiving packets
ahci: SATA FIS is 20 bytes, not 0x20
qemu-img: document qed format on qemu-img man page
virtio: Fix compiler warning for non Linux hosts
sheepdog: fix return value of do_load_save_vm_state
qemu/xendisk: set maximum number of grants to be used
build: install qmp-commands.txt
fdc: fix implied seek while there is no media in drive
qcow2: fix autoclear image header update
Prevent disk data loss when closing qemu
qcow2: fix endianness conversion
pci_bridge_dev: fix error path in pci_bridge_dev_initfn()
qdev: release parent properties on dc->init failure
intel-hda: Fix reset of MSI function
ahci: Fix reset of MSI function
rtl8139: honor RxOverflow flag in can_receive method
configure: Fix build for some versions of glibc (9pfs)
monitor: Fix memory leak with readline completion
...
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'hw/rtl8139.c')
-rw-r--r-- | hw/rtl8139.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 2413bc3d2..7b150475f 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -781,6 +781,13 @@ static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high) #endif } +/* Workaround for buggy guest driver such as linux who allocates rx + * rings after the receiver were enabled. */ +static bool rtl8139_cp_rx_valid(RTL8139State *s) +{ + return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0); +} + static int rtl8139_can_receive(VLANClientState *nc) { RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; @@ -792,14 +799,14 @@ static int rtl8139_can_receive(VLANClientState *nc) if (!rtl8139_receiver_enabled(s)) return 1; - if (rtl8139_cp_receiver_enabled(s)) { + if (rtl8139_cp_receiver_enabled(s) && rtl8139_cp_rx_valid(s)) { /* ??? Flow control not implemented in c+ mode. This is a hack to work around slirp deficiencies anyway. */ return 1; } else { avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); - return (avail == 0 || avail >= 1514); + return (avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow)); } } @@ -937,6 +944,10 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ if (rtl8139_cp_receiver_enabled(s)) { + if (!rtl8139_cp_rx_valid(s)) { + return size; + } + DPRINTF("in C+ Rx mode ================\n"); /* begin C+ receiver mode */ |