]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
net: recv(): return -EAGAIN instead of 0 when no cleanup is expected
authorJerome Forissier <jerome.forissier@linaro.org>
Wed, 9 Oct 2024 09:42:08 +0000 (11:42 +0200)
committerTom Rini <trini@konsulko.com>
Sun, 27 Oct 2024 23:03:40 +0000 (17:03 -0600)
Some drivers do not behave properly when free_pkt() is called with a
length of zero. It is an issue I observed when developing the lwIP
series [1] (see "QEMU CI tests for r2dplus_i82557c, r2dplus_rtl8139"
in the change log) and which I fixed incorrectly by not calling
free_pkt() when recv() returns 0. That turned out to be wrong for two
reasons:

1. The DM documentation [2] clearly requires it:

  "The **recv** function polls for availability of a new packet. [...]
   If there is an error [...], return 0 if you require the packet to
   be cleaned up normally, or a negative error code otherwise (cleanup
   not necessary or already done).

   If **free_pkt** is defined, U-Boot will call it after a received
   packet has been processed [...]. free_pkt() will be called after
   recv(), for the same packet [...]"

2. The imx8mp_evk platform will fail with OOM errors if free_pkt() is
   not called after recv() returns 0:

   u-boot=> tftp 192.168.0.16:50M
   Using ethernet@30be0000 device
   TFTP from server 192.168.0.16; our IP address is 192.168.0.48
   Filename '50M'.
   Load address: 0x40480000
   Loading: #######################fecmxc_recv: error allocating packetp
   fecmxc_recv: error allocating packetp
   fecmxc_recv: error allocating packetp
   ...

Therefore, make recv() return -EAGAIN instead of 0 when no packet is
available and the driver doesn't expect free_pkt() to be called
subsequently.

[1] https://lists.denx.de/pipermail/u-boot/2024-August/562861.html
[2] doc/develop/driver-model/ethernet.rst

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/net/eepro100.c
drivers/net/rtl8139.c

index d18a8d577ca422c9b6edeb28da21eb953dc7fae8..f64dbb7d6a12a26e9858f976a0dd9db52e2efe76 100644 (file)
@@ -678,7 +678,7 @@ static int eepro100_recv_common(struct eepro100_priv *priv, uchar **packetp)
        status = le16_to_cpu(desc->status);
 
        if (!(status & RFD_STATUS_C))
-               return 0;
+               return -EAGAIN;
 
        /* Valid frame status. */
        if (status & RFD_STATUS_OK) {
index 2e0afad089f8e03aa17469cd36b7285f1b691819..5f4b1e2d3a07808b556fa2fa7a647759c620bc82 100644 (file)
@@ -433,7 +433,7 @@ static int rtl8139_recv_common(struct rtl8139_priv *priv, unsigned char *rxdata,
        int length = 0;
 
        if (inb(priv->ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY)
-               return 0;
+               return -EAGAIN;
 
        priv->rxstatus = inw(priv->ioaddr + RTL_REG_INTRSTATUS);
        /* See below for the rest of the interrupt acknowledges.  */