[PATCH] net: ravb: Fix RX error handling

Marek Vasut marek.vasut at mailbox.org
Sun Apr 20 18:36:44 CEST 2025


On 4/15/25 12:02 PM, Paul Barker wrote:
> On 13/04/2025 14:11, Marek Vasut wrote:
>> Correctly handle RX errors in ravb_recv() by returning 0 instead
>> of -EAGAIN on RX error.
>>
>> In case the RAVB driver detects an RX error in ravb_recv(), it must
>> not return the -EAGAIN, but instead must return 0. Both error codes
>> are handled in eth-uclass.c eth_rx() and -EAGAIN is rewritten to 0
>> at the end of eth_rx(), but negative return code from the .recv()
>> callback does not trigger .free_pkt() callback, which would clean
>> up and re-enqueue the descriptor which holds the currently received
>> corrupted packet. The .free_pkt() must be called for this descriptor,
>> otherwise the follow up received data become corrupted too, even if
>> those packets are correctly received. Returning 0 from the .recv()
>> callback assures the corrupted packet is not processed by the network
>> stack, but is skipped instead.
>>
>> For TFTP loading, an RX error produces the timeout "T" output and
>> resumes the TFTP loading operation shortly afterward, without any
>> data corruption.
>>
>> Signed-off-by: Marek Vasut <marek.vasut+renesas at mailbox.org>
>> ---
>> Cc: Joe Hershberger <joe.hershberger at ni.com>
>> Cc: Nobuhiro Iwamatsu <iwamatsu at nigauri.org>
>> Cc: Paul Barker <paul.barker.ct at bp.renesas.com>
>> Cc: Ramon Fried <rfried.dev at gmail.com>
>> Cc: Tom Rini <trini at konsulko.com>
>> Cc: u-boot at lists.denx.de
>> ---
>>   drivers/net/ravb.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
>> index 539fd37ee59..da3e9dbeacd 100644
>> --- a/drivers/net/ravb.c
>> +++ b/drivers/net/ravb.c
>> @@ -192,7 +192,7 @@ static int ravb_recv(struct udevice *dev, int flags, uchar **packetp)
>>   	/* Check for errors */
>>   	if (desc->data.ctrl & RAVB_RX_DESC_MSC_RX_ERR_MASK) {
>>   		desc->data.ctrl &= ~RAVB_RX_DESC_MSC_MASK;
>> -		return -EAGAIN;
>> +		return 0;
> 
> Hi Marek,
> 
> At this point in the function we haven't stored anything to *packetp.
> 
> Looking at the relevant bit of eth_rx():
> 
>          for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++) {
>                  ret = eth_get_ops(current)->recv(current, flags, &packet);
>                  flags = 0;
>                  if (ret > 0)
>                          net_process_received_packet(packet, ret);
>                  if (ret >= 0 && eth_get_ops(current)->free_pkt)
>                          eth_get_ops(current)->free_pkt(current, packet, ret);
>                  if (ret <= 0)
>                          break;
>          }
> 
> So if ->recv() returns zero without storing to *packetp, we will call
> ->free_pkt() with a packet argument that is either uninitialized or
> points to the packet from the last iteration through the loop.
Fixed in V2, thanks !


More information about the U-Boot mailing list