imx_fec: Change queue flushing heuristics
authorAndrey Smirnov <andrew.smirnov@gmail.com>
Thu, 11 Jan 2018 13:25:35 +0000 (13:25 +0000)
committerPeter Maydell <peter.maydell@linaro.org>
Thu, 11 Jan 2018 13:25:35 +0000 (13:25 +0000)
commitb2b012afdd9c03ba8a1619f45301d34f358d367b
tree800e5b6041f4b753a9a867c09daa3b4b6a46027d
parenta6383e99ffc3b615d8465aebbd5d48f1fa9b2949
imx_fec: Change queue flushing heuristics

In current implementation, packet queue flushing logic seem to suffer
from a deadlock like scenario if a packet is received by the interface
before before Rx ring is initialized by Guest's driver. Consider the
following sequence of events:

1. A QEMU instance is started against a TAP device on Linux
   host, running Linux guest, e. g., something to the effect
   of:

   qemu-system-arm \
      -net nic,model=imx.fec,netdev=lan0 \
      netdev tap,id=lan0,ifname=tap0,script=no,downscript=no \
      ... rest of the arguments ...

2. Once QEMU starts, but before guest reaches the point where
   FEC deriver is done initializing the HW, Guest, via TAP
   interface, receives a number of multicast MDNS packets from
   Host (not necessarily true for every OS, but it happens at
   least on Fedora 25)

3. Recieving a packet in such a state results in
   imx_eth_can_receive() returning '0', which in turn causes
   tap_send() to disable corresponding event (tap.c:203)

4. Once Guest's driver reaches the point where it is ready to
   recieve packets it prepares Rx ring descriptors and writes
   ENET_RDAR_RDAR to ENET_RDAR register to indicate to HW that
   more descriptors are ready. And at this points emulation
   layer does this:

     s->regs[index] = ENET_RDAR_RDAR;
                 imx_eth_enable_rx(s);

   which, combined with:

      if (!s->regs[ENET_RDAR]) {
     qemu_flush_queued_packets(qemu_get_queue(s->nic));
  }

   results in Rx queue never being flushed and corresponding
   I/O event beign disabled.

To prevent the problem, change the code to always flush packet queue
when ENET_RDAR transitions 0 -> ENET_RDAR_RDAR.

Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Jason Wang <jasowang@redhat.com>
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
Cc: qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org
Cc: yurovsky@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
hw/net/imx_fec.c