qemu-e2k/hw/net
Andrey Smirnov 7e354ed4df fsl_etsec: Fix Tx BD ring wrapping handling
Current code that handles Tx buffer desciprtor ring scanning employs the
following algorithm:

	1. Restore current buffer descriptor pointer from TBPTRn

	2. Process current descriptor

	3. If current descriptor has BD_WRAP flag set set current
	   descriptor pointer to start of the descriptor ring

	4. If current descriptor points to start of the ring exit the
	   loop, otherwise increment current descriptor pointer and go
	   to #2

	5. Store current descriptor in TBPTRn

The way the code is implemented results in buffer descriptor ring being
scanned starting at offset/descriptor #0. While covering 99% of the
cases, this algorithm becomes problematic for a number of edge cases.

Consider the following scenario: guest OS driver initializes descriptor
ring to N individual descriptors and starts sending data out. Depending
on the volume of traffic and probably guest OS driver implementation it
is possible that an edge case where a packet, spread across 2
descriptors is placed in descriptors N - 1 and 0 in that order(it is
easy to imagine similar examples involving more than 2 descriptors).

What happens then is aforementioned algorithm starts at descriptor 0,
sees a descriptor marked as BD_LAST, which it happily sends out as a
separate packet(very much malformed at this point) then the iteration
continues and the first part of the original packet is tacked to the
next transmission which ends up being bogus as well.

This behvaiour can be pretty reliably observed when scp'ing data from a
guest OS via TAP interface for files larger than 160K (every time for
700K+).

This patch changes the scanning algorithm to do the following:

	1. Restore "current" buffer descriptor pointer from
	   TBPTRn

	2. If "current" descriptor does not have BD_TX_READY set, goto #6

	3. Process current descriptor

	4. If "current" descriptor has BD_WRAP flag set "current"
	   descriptor pointer to start of the descriptor ring otherwise
	   set increment "current" by the size of one descriptor

	5. Goto #1

	6. Save "current" buffer descriptor in TBPTRn

This way we preserve the information about which descriptor was
processed last and always start where we left off avoiding the original
problem. On top of that, judging by the following excerpt from
MPC8548ERM (p. 14-48):

"... When the end of the TxBD ring is reached, eTSEC initializes TBPTRn
to the value in the corresponding TBASEn. The TBPTR register is
internally written by the eTSEC’s DMA controller during
transmission. The pointer increments by eight (bytes) each time a
descriptor is closed successfully by the eTSEC..."

revised algorithm might also a more correct way of emulating this aspect
of eTSEC peripheral.

Cc: Alexander Graf <agraf@suse.de>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: qemu-devel@nongnu.org
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2017-01-06 10:38:21 +08:00
..
fsl_etsec fsl_etsec: Fix Tx BD ring wrapping handling 2017-01-06 10:38:21 +08:00
rocker net: rocker: set limit to DMA buffer size 2016-10-26 09:57:59 +08:00
Makefile.objs e1000e: fix building without CONFIG_VMXNET3_PCI 2016-07-18 16:17:02 +08:00
allwinner_emac.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
cadence_gem.c cadence_gem: Fix priority queue out of bounds access 2016-10-04 13:28:09 +01:00
dp8393x.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
e1000.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
e1000_regs.h Clean up header guards that don't match their file name 2016-07-12 16:19:16 +02:00
e1000e.c e1000e: Flush all receive queues on receive enable 2016-09-27 17:54:22 +08:00
e1000e_core.c e1000e: Don't zero out buffer address in rx descriptor 2016-10-26 09:57:59 +08:00
e1000e_core.h e1000e: Flush all receive queues on receive enable 2016-09-27 17:54:22 +08:00
e1000x_common.c hw/net/e1000: Don't use *_to_cpup() 2016-06-27 16:39:56 +01:00
e1000x_common.h e1000: Move out code that will be reused in e1000e 2016-06-02 10:42:29 +08:00
eepro100.c net: eepro100: fix memory leak in device uninit 2016-10-26 09:57:59 +08:00
etraxfs_eth.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
imx_fec.c imx_fec: fix error in qemu_send_packet argument 2016-09-27 17:54:22 +08:00
lan9118.c hw/ptimer: Introduce timer policy feature 2016-09-22 18:13:06 +01:00
lance.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
mcf_fec.c net: mcf: check receive buffer size register value 2016-12-05 17:45:14 +08:00
milkymist-minimac2.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
mipsnet.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
ne2000-isa.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
ne2000.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
ne2000.h Clean up decorations and whitespace around header guards 2016-07-12 16:20:46 +02:00
net_rx_pkt.c net_pkt: Extend packet abstraction as required by e1000e functionality 2016-06-02 10:42:28 +08:00
net_rx_pkt.h net_pkt: Extend packet abstraction as required by e1000e functionality 2016-06-02 10:42:28 +08:00
net_tx_pkt.c net: vmxnet: use g_new for pkt initialisation 2016-08-18 12:05:18 +08:00
net_tx_pkt.h clean-includes: run it once more 2016-06-16 18:39:03 +02:00
opencores_eth.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
pcnet-pci.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
pcnet.c net: pcnet: fix source formatting and indentation 2016-10-26 09:57:59 +08:00
pcnet.h Clean up decorations and whitespace around header guards 2016-07-12 16:20:46 +02:00
rtl8139.c rtl8139: correctly handle PHY reset 2017-01-06 10:38:05 +08:00
smc91c111.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
spapr_llan.c spapr_llan: convert to trace framework instead of DPRINTF 2016-09-23 10:29:40 +10:00
stellaris_enet.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
trace-events e1000e: Fix CTRL_EXT.EIAME behavior 2016-09-27 17:54:22 +08:00
vhost_net.c vhost: check for vhost_ops before using. 2016-08-10 17:47:29 +03:00
virtio-net.c virtio, vhost, pc, pci: documentation, fixes and cleanups 2016-11-15 19:50:36 +00:00
vmware_utils.h vmxnet3: Fix reading/writing guest memory specially when behind an IOMMU 2016-06-28 10:13:57 +08:00
vmxnet3.c net: vmxnet: initialise local tx descriptor 2016-10-26 09:57:59 +08:00
vmxnet3.h Clean up ill-advised or unusual header guards 2016-07-12 16:20:46 +02:00
vmxnet_debug.h Clean up ill-advised or unusual header guards 2016-07-12 16:20:46 +02:00
xen_nic.c xen: Rename xen_be_send_notify 2016-10-28 17:54:21 -07:00
xgmac.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
xilinx_axienet.c qapi: Change Netdev into a flat union 2016-07-19 20:18:02 +02:00
xilinx_ethlite.c hw/net: Fix a heap overflow in xlnx.xps-ethernetlite 2016-08-09 15:27:18 +08:00