All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [PULL 18/39] hw/net/allwinner-sun8i-emac: traverse transmit queue using TX_CUR_DESC register value
Date: Fri, 12 Mar 2021 13:51:19 +0000	[thread overview]
Message-ID: <20210312135140.1099-19-peter.maydell@linaro.org> (raw)
In-Reply-To: <20210312135140.1099-1-peter.maydell@linaro.org>

From: Niek Linnenbank <nieklinnenbank@gmail.com>

Currently the emulated EMAC for sun8i always traverses the transmit queue
from the head when transferring packets. It searches for a list of consecutive
descriptors whichs are flagged as ready for processing and transmits their payloads
accordingly. The controller stops processing once it finds a descriptor that is not
marked ready.

While the above behaviour works in most situations, it is not the same as the actual
EMAC in hardware. Actual hardware uses the TX_CUR_DESC register value to keep track
of the last position in the transmit queue and continues processing from that position
when software triggers the start of DMA processing. The currently emulated behaviour can
lead to packet loss on transmit when software fills the transmit queue with ready
descriptors that overlap the tail of the circular list.

This commit modifies the emulated EMAC for sun8i such that it processes
the transmit queue using the TX_CUR_DESC register in the same way as hardware.

Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210310195820.21950-2-nieklinnenbank@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/net/allwinner-sun8i-emac.c | 62 +++++++++++++++++++----------------
 1 file changed, 34 insertions(+), 28 deletions(-)

diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
index bf91803d65a..ff611f18fbd 100644
--- a/hw/net/allwinner-sun8i-emac.c
+++ b/hw/net/allwinner-sun8i-emac.c
@@ -339,35 +339,40 @@ static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s)
     qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0);
 }
 
-static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
-                                               FrameDescriptor *desc,
-                                               size_t min_size)
+static bool allwinner_sun8i_emac_desc_owned(FrameDescriptor *desc,
+                                            size_t min_buf_size)
 {
-    uint32_t paddr = desc->next;
-
-    dma_memory_read(&s->dma_as, paddr, desc, sizeof(*desc));
-
-    if ((desc->status & DESC_STATUS_CTL) &&
-        (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
-        return paddr;
-    } else {
-        return 0;
-    }
+    return (desc->status & DESC_STATUS_CTL) && (min_buf_size == 0 ||
+           (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_buf_size);
 }
 
-static uint32_t allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
-                                              FrameDescriptor *desc,
-                                              uint32_t start_addr,
-                                              size_t min_size)
+static void allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
+                                          FrameDescriptor *desc,
+                                          uint32_t phys_addr)
+{
+    dma_memory_read(&s->dma_as, phys_addr, desc, sizeof(*desc));
+}
+
+static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
+                                               FrameDescriptor *desc)
+{
+    const uint32_t nxt = desc->next;
+    allwinner_sun8i_emac_get_desc(s, desc, nxt);
+    return nxt;
+}
+
+static uint32_t allwinner_sun8i_emac_find_desc(AwSun8iEmacState *s,
+                                               FrameDescriptor *desc,
+                                               uint32_t start_addr,
+                                               size_t min_size)
 {
     uint32_t desc_addr = start_addr;
 
     /* Note that the list is a cycle. Last entry points back to the head. */
     while (desc_addr != 0) {
-        dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc));
+        allwinner_sun8i_emac_get_desc(s, desc, desc_addr);
 
-        if ((desc->status & DESC_STATUS_CTL) &&
-            (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
+        if (allwinner_sun8i_emac_desc_owned(desc, min_size)) {
             return desc_addr;
         } else if (desc->next == start_addr) {
             break;
@@ -383,14 +388,14 @@ static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s,
                                              FrameDescriptor *desc,
                                              size_t min_size)
 {
-    return allwinner_sun8i_emac_get_desc(s, desc, s->rx_desc_curr, min_size);
+    return allwinner_sun8i_emac_find_desc(s, desc, s->rx_desc_curr, min_size);
 }
 
 static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
-                                             FrameDescriptor *desc,
-                                             size_t min_size)
+                                             FrameDescriptor *desc)
 {
-    return allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_head, min_size);
+    allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_curr);
+    return s->tx_desc_curr;
 }
 
 static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s,
@@ -470,7 +475,8 @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc,
         bytes_left -= desc_bytes;
 
         /* Move to the next descriptor */
-        s->rx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 64);
+        s->rx_desc_curr = allwinner_sun8i_emac_find_desc(s, &desc, desc.next,
+                                                         AW_SUN8I_EMAC_MIN_PKT_SZ);
         if (!s->rx_desc_curr) {
             /* Not enough buffer space available */
             s->int_sta |= INT_STA_RX_BUF_UA;
@@ -495,10 +501,10 @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
     size_t transmitted = 0;
     static uint8_t packet_buf[2048];
 
-    s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc, 0);
+    s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc);
 
     /* Read all transmit descriptors */
-    while (s->tx_desc_curr != 0) {
+    while (allwinner_sun8i_emac_desc_owned(&desc, 0)) {
 
         /* Read from physical memory into packet buffer */
         bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
@@ -524,7 +530,7 @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
             packet_bytes = 0;
             transmitted++;
         }
-        s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 0);
+        s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc);
     }
 
     /* Raise transmit completed interrupt */
-- 
2.20.1



  parent reply	other threads:[~2021-03-12 14:06 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-12 13:51 [PULL 00/39] target-arm queue Peter Maydell
2021-03-12 13:51 ` [PULL 01/39] hw/misc: versal: Add a model of the XRAM controller Peter Maydell
2021-03-12 13:51 ` [PULL 02/39] hw/arm: versal: Add support for the XRAMs Peter Maydell
2021-03-12 13:51 ` [PULL 03/39] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate Peter Maydell
2021-03-12 13:51 ` [PULL 04/39] dma: Introduce dma_aligned_pow2_mask() Peter Maydell
2021-03-12 13:51 ` [PULL 05/39] virtio-iommu: Handle non power of 2 range invalidations Peter Maydell
2021-03-12 13:51 ` [PULL 06/39] hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set Peter Maydell
2021-03-12 13:51 ` [PULL 07/39] hw/arm/smmuv3: Enforce invalidation on a power of two range Peter Maydell
2021-03-12 13:51 ` [PULL 08/39] hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling Peter Maydell
2021-03-12 13:51 ` [PULL 09/39] hw/arm/smmuv3: Uniformize sid traces Peter Maydell
2021-03-12 13:51 ` [PULL 10/39] target/arm: Fix sve_uzp_p vs odd vector lengths Peter Maydell
2021-03-12 13:51 ` [PULL 11/39] target/arm: Fix sve_zip_p " Peter Maydell
2021-03-12 13:51 ` [PULL 12/39] target/arm: Fix sve_punpk_p " Peter Maydell
2021-03-12 13:51 ` [PULL 13/39] target/arm: Update find_last_active for PREDDESC Peter Maydell
2021-03-12 13:51 ` [PULL 14/39] target/arm: Update BRKA, BRKB, BRKN " Peter Maydell
2021-03-12 13:51 ` [PULL 15/39] target/arm: Update CNTP " Peter Maydell
2021-03-12 13:51 ` [PULL 16/39] target/arm: Update WHILE " Peter Maydell
2021-03-12 13:51 ` [PULL 17/39] target/arm: Update sve reduction vs simd_desc Peter Maydell
2021-03-12 13:51 ` Peter Maydell [this message]
2021-03-12 13:51 ` [PULL 19/39] tests/acceptance/boot_linux_console: remove Armbian 19.11.3 bionic test for orangepi-pc machine Peter Maydell
2021-03-12 13:51 ` [PULL 20/39] tests/acceptance/boot_linux_console: change URL for test_arm_orangepi_bionic_20_08 Peter Maydell
2021-03-12 13:51 ` [PULL 21/39] tests/acceptance: update sunxi kernel from armbian to 5.10.16 Peter Maydell
2021-03-12 13:51 ` [PULL 22/39] tests/acceptance: drop ARMBIAN_ARTIFACTS_CACHED condition for orangepi-pc, cubieboard tests Peter Maydell
2021-03-12 13:51 ` [PULL 23/39] hw/timer/sse-timer: Propagate eventual error in sse_timer_realize() Peter Maydell
2021-03-12 13:51 ` [PULL 24/39] accel: kvm: Fix kvm_type invocation Peter Maydell
2021-03-12 13:51 ` [PULL 25/39] hw/arm/virt: KVM: The IPA lower bound is 32 Peter Maydell
2021-03-12 13:51 ` [PULL 26/39] hw/misc: Add GPIOs for duty in NPCM7xx PWM Peter Maydell
2021-03-12 13:51 ` [PULL 27/39] hw/misc: Add NPCM7XX MFT Module Peter Maydell
2021-03-12 13:51 ` [PULL 28/39] hw/arm: Add MFT device to NPCM7xx Soc Peter Maydell
2021-03-12 13:51 ` [PULL 29/39] hw/arm: Connect PWM fans in NPCM7XX boards Peter Maydell
2021-03-12 13:51 ` [PULL 30/39] tests/qtest: Test PWM fan RPM using MFT in PWM test Peter Maydell
2021-03-12 13:51 ` [PULL 31/39] hw/display/pl110: Remove dead code for non-32-bpp surfaces Peter Maydell
2021-03-12 13:51 ` [PULL 32/39] hw/display/pl110: Pull included-once parts of template header into pl110.c Peter Maydell
2021-03-12 13:51 ` [PULL 33/39] hw/display/pl110: Remove use of BITS from pl110_template.h Peter Maydell
2021-03-12 13:51 ` [PULL 34/39] hw/display/pxa2xx_lcd: Remove dead code for non-32-bpp surfaces Peter Maydell
2021-03-12 13:51 ` [PULL 35/39] hw/display/pxa2xx_lcd: Remove dest_width state field Peter Maydell
2021-03-12 13:51 ` [PULL 36/39] hw/display/pxa2xx: Remove use of BITS in pxa2xx_template.h Peter Maydell
2021-03-12 13:51 ` [PULL 37/39] hw/display/pxa2xx: Apply brace-related coding style fixes to template header Peter Maydell
2021-03-12 13:51 ` [PULL 38/39] hw/display/pxa2xx: Apply whitespace-only " Peter Maydell
2021-03-12 13:51 ` [PULL 39/39] hw/display/pxa2xx: Inline " Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210312135140.1099-19-peter.maydell@linaro.org \
    --to=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.