From: Simon Horman <horms@kernel.org>
To: Selvamani.Rajagopal@onsemi.com
Cc: Simon Horman <horms@kernel.org>,
parthiban.veerasooran@microchip.com, andrew+netdev@lunn.ch,
pier.beruto@onsemi.com, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, andrew@lunn.ch,
Parthiban.Veerasooran@microchip.com
Subject: Re: [PATCH net v3 2/3] net: ethernet: oa_tc6: Improvement in buffer overflow handling
Date: Fri, 10 Jul 2026 15:20:18 +0100 [thread overview]
Message-ID: <20260710142019.1619159-1-horms@kernel.org> (raw)
In-Reply-To: <20260705-fix-race-condition-and-crash-v3-2-3e51841e4d08@onsemi.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
net: ethernet: oa_tc6: Improvement in buffer overflow handling
This patch teaches the oa_tc6 rx path to detect when tail + length would
exceed skb->end, abandon the current rx_skb, and resume on the next
data chunk carrying a start_valid bit. It also propagates -EAGAIN as a
recoverable error through the chunk/footer processing and the outer
SPI transfer loop.
> diff --git a/drivers/net/ethernet/oa_tc6.c b/drivers/net/ethernet/oa_tc6.c
> index 5b24cce4f9b5..a6b8762f6052 100644
> --- a/drivers/net/ethernet/oa_tc6.c
> +++ b/drivers/net/ethernet/oa_tc6.c
[ ... ]
> @@ -931,8 +966,7 @@ static int oa_tc6_prcs_rx_chunk_payload(struct oa_tc6 *tc6, u8 *data,
> /* Process the chunk with only rx frame end */
> if (end_valid && !start_valid) {
> size = end_byte_offset + 1;
> - oa_tc6_prcs_rx_frame_end(tc6, data, size);
> - return 0;
> + return oa_tc6_prcs_rx_frame_end(tc6, data, size);
> }
>
> /* Process the chunk with previous rx frame end and next rx frame
[High]
Now that oa_tc6_prcs_rx_frame_end() returns int (and can return -EAGAIN
via oa_tc6_update_rx_skb() when tail + size > end), should the
"previous rx frame end + next rx frame start" branch also observe the
return value? That branch is not shown in the diff, but in the
resulting file it reads:
if (start_valid && end_valid && start_byte_offset > end_byte_offset) {
if (tc6->rx_skb) {
size = end_byte_offset + 1;
oa_tc6_prcs_rx_frame_end(tc6, data, size);
}
size = OA_TC6_CHUNK_PAYLOAD_SIZE - start_byte_offset;
return oa_tc6_prcs_rx_frame_start(tc6,
&data[start_byte_offset],
size);
}
If oa_tc6_prcs_rx_frame_end() here returns -EAGAIN, oa_tc6_look_for_new_frame()
has already set tc6->rx_buf_overflow = true and cleared rx_skb. Execution
then falls through to oa_tc6_prcs_rx_frame_start(), which allocates a
fresh rx_skb and copies the start bytes, but tc6->rx_buf_overflow stays
true because the guard
if (start_valid && tc6->rx_buf_overflow)
tc6->rx_buf_overflow = false;
is only evaluated on chunk entry. Subsequent ongoing chunks (no
start_valid) then hit the earlier
if (tc6->rx_buf_overflow)
return 0;
path and are silently dropped, and the partial rx_skb is later thrown
away by the next allocate_rx_skb() -> cleanup_ongoing_rx_skb(), which
also increments rx_dropped. Is this the intended behaviour for the
oversubscribed/chunk-loss scenario the patch is targeting?
[ ... ]
> @@ -972,8 +1004,9 @@ static u32 oa_tc6_get_rx_chunk_footer(struct oa_tc6 *tc6, u16 footer_offset)
> static int oa_tc6_process_spi_data_rx_buf(struct oa_tc6 *tc6, u16 length)
> {
> u16 no_of_rx_chunks = length / OA_TC6_CHUNK_SIZE;
> + bool retry = false;
> + int ret = 0;
> u32 footer;
> - int ret;
>
> /* All the rx chunks in the receive SPI data buffer are examined here */
> for (int i = 0; i < no_of_rx_chunks; i++) {
> @@ -982,8 +1015,11 @@ static int oa_tc6_process_spi_data_rx_buf(struct oa_tc6 *tc6, u16 length)
> OA_TC6_CHUNK_PAYLOAD_SIZE);
>
> ret = oa_tc6_process_rx_chunk_footer(tc6, footer);
> - if (ret)
> - return ret;
> + if (ret) {
> + if (ret != -EAGAIN)
> + return ret;
> + retry = true;
> + }
>
> /* If there is a data valid chunks then process it for the
> * information needed to determine the validity and the location
> @@ -995,12 +1031,25 @@ static int oa_tc6_process_spi_data_rx_buf(struct oa_tc6 *tc6, u16 length)
>
> ret = oa_tc6_prcs_rx_chunk_payload(tc6, payload,
> footer);
> - if (ret)
> - return ret;
> + if (ret) {
> + if (ret != -ENOMEM && ret != -EAGAIN)
> + return ret;
> + retry = true;
> + }
> }
> }
[Medium]
Is it intentional that a real -ENOMEM from oa_tc6_prcs_rx_chunk_payload()
(originating in oa_tc6_allocate_rx_skb() -> netdev_alloc_skb_ip_align())
is now folded into the retry path and converted to -EAGAIN at the end
of this function?
Before this patch, -ENOMEM propagated up through oa_tc6_try_spi_transfer()
and produced a netdev_err("Device error: %d", ret) plus
oa_tc6_free_ongoing_skbs() cleanup. With this change, the outer while
loop treats -EAGAIN as non-fatal, so sustained memory exhaustion is
reported only as increments to stats.rx_dropped from
oa_tc6_allocate_rx_skb().
The commit message describes the change as being about buffer overflow
errors; is the change in visibility for allocation failures intended?
>
> - return 0;
> + /* As a recoverable error, not bailing out on error code
> + * -EAGAIN. If subsequent loop iterations, if any, succeeds,
> + * error code would be overwritten. retry flag helps to
> + * make the caller to continue and retry.
> + */
> + if (retry) {
> + ret = -EAGAIN;
> + oa_tc6_look_for_new_frame(tc6);
> + }
> +
> + return ret;
> }
[High]
Can this unconditional oa_tc6_look_for_new_frame() discard a frame that
was successfully started later in the same buffer?
Consider a buffer where iteration N returns -EAGAIN from
oa_tc6_process_rx_chunk_footer() due to STATUS0 rx overflow (which
already sets rx_buf_overflow and clears rx_skb), and a later iteration
N+K carries a start_valid chunk that clears rx_buf_overflow via
if (start_valid && tc6->rx_buf_overflow)
tc6->rx_buf_overflow = false;
allocates a fresh rx_skb in oa_tc6_prcs_rx_frame_start(), and writes
the start bytes without further error. retry is still true from
iteration N, so on loop exit the terminal oa_tc6_look_for_new_frame()
frees that newly-started rx_skb (incrementing rx_dropped) and re-sets
rx_buf_overflow = true.
On the next SPI transfer, the ongoing chunks of that frame are then
dropped by the top-of-function
if (tc6->rx_buf_overflow)
return 0;
guard in oa_tc6_prcs_rx_chunk_payload() until yet another start_valid
arrives. Would it be safer to only call oa_tc6_look_for_new_frame()
here if the last iteration was still in an errored state, e.g. by
tracking the outcome of the most recent chunk rather than an aggregate
retry flag?
[ ... ]
next prev parent reply other threads:[~2026-07-10 14:20 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-05 22:59 [PATCH net v3 0/3] Fix to possible skb leak due to race condtion in tx path Selvamani Rajagopal via B4 Relay
2026-07-05 22:59 ` [PATCH net v3 1/3] net: ethernet: oa_tc6: Protect skb pointer used by two different kernel instances Selvamani Rajagopal via B4 Relay
2026-07-05 22:59 ` [PATCH net v3 2/3] net: ethernet: oa_tc6: Improvement in buffer overflow handling Selvamani Rajagopal via B4 Relay
2026-07-10 14:20 ` Simon Horman [this message]
2026-07-10 18:03 ` Selvamani Rajagopal
2026-07-05 22:59 ` [PATCH net v3 3/3] net: ethernet: oa_tc6: Carrier off when disable_traffic is set Selvamani Rajagopal via B4 Relay
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=20260710142019.1619159-1-horms@kernel.org \
--to=horms@kernel.org \
--cc=Selvamani.Rajagopal@onsemi.com \
--cc=andrew+netdev@lunn.ch \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=parthiban.veerasooran@microchip.com \
--cc=pier.beruto@onsemi.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox