On Mon, Oct 12, 2026 at 11:38 AM Christophe Leroy (CS GROUP)
<[email protected]> wrote:
>
>
>
> Le 12/10/2026 à 20:28, Rosen Penev a écrit :
> > On Mon, Oct 12, 2026 at 11:18 AM Christophe Leroy (CS GROUP)
> > <[email protected]> wrote:
> >>
> >>
> >>
> >> Le 12/10/2026 à 20:00, Rosen Penev a écrit :
> >>> __csum_partial() walks the buffer linearly and reads each cache line
> >>> exactly once. On cores without a hardware prefetcher, such as the 464FP
> >>> in the APM82181, every new line is therefore a demand miss that stalls
> >>> the loop. Packets received by non-coherent DMA are never in the cache,
> >>> so this is the common case for GRO checksum validation: when routing
> >>> TCP with GRO enabled on a Meraki MX60, __csum_partial() takes about 30%
> >>> of all cycles and is the top entry in the profile.
> >>>
> >>> Issue a dcbt four cache lines (128 bytes) ahead in the main loop.
> >>> dcbt is only a hint and never faults, so prefetching past the end of
> >>> the buffer is harmless. Lines that are already cached, for example when
> >>> checksumming data the CPU just wrote, are left untouched.
> >>>
> >>> Measured on a Meraki MX60 (APM82181 at 800 MHz), single TCP stream
> >>> routed through a qca8k DSA switch, iperf3 median of 5. Only the dcbt
> >>> was toggled at runtime, in the same boot:
> >>>
> >>>                 LAN->WAN               WAN->LAN
> >>>                 Mbit/s  csum cycles    Mbit/s  csum cycles
> >>>     before      495     30.5%          439     27.2%
> >>>     after       599     15.3%          520     13.7%
> >>>
> >>> That is 58% less time spent in __csum_partial() per byte.
> >>>
> >>> The prefetch distance was chosen with an earlier, slower driver
> >>> configuration (median of 3, Mbit/s):
> >>>
> >>>     distance    LAN->WAN   WAN->LAN
> >>>     none        370        341
> >>>     64 bytes    430        381
> >>>     96 bytes    438        397
> >>>     128 bytes   438        385
> >>>     160 bytes   434        386
> >>>     256 bytes   423        383
> >>>
> >>> Prefetching the first lines before entering the loop made no
> >>> measurable difference and is not done.
> >>>
> >>> Assisted-by: LLM
> >>> Signed-off-by: Rosen Penev <[email protected]>
> >>
> >> csum_partial_copy_generic() does the same, so your patch makes sense.
> >>
> >> Wondering if you should use MAX_COPY_PREFETCH instead of hardcoding value 
> >> 4.
> > li      r9,MAX_COPY_PREFETCH*L1_CACHE_BYTES /* prefetch distance */
> >
> > LLM comment:
> >
> > What changes per platform: MAX_COPY_PREFETCH is 4 on every 32-bit
> > config except 8xx, where it is 1. So 44x, 47x and e500mc behave
> > exactly as before; on the 44x (canyonlands) build the instruction is
> > still li r9, 128. The one difference is 8xx, which now prefetches 16
> > bytes ahead instead of 64. That fits how the copy routine already
> > treats 8xx, but I didn't benchmark it.
> >
> > My comment:
> > I don't have an 8xx device so I don't know if this works properly there or 
> > not.
>
> I have an 885 and might do the test one day, but I won't have time
> during the coming weeks. Nevertheless I have the feeling it makes sense
> to implement something based on MAX_COPY_PREFETCH to resemble
> csum_partial_copy_generic()
I got a user to test this setup with MAX_COPY_PREFETCH

Using Sophos RED 15w, right after sysupgrade -n, got an iperf3 -c
result of ~633Mb/s with the suggested change, vs. ~583Mb/s with the
latest snapshot build from the web site, ie. without this PR.
>
> >>
> >> Reviewed-by: Christophe Leroy (CS GROUP) <[email protected]>
> > I'll keep this in v3.
> >>
> >>> ---
> >>>    v2: reword commit message and retest numbers.
> >>>    arch/powerpc/lib/checksum_32.S | 4 +++-
> >>>    1 file changed, 3 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/arch/powerpc/lib/checksum_32.S 
> >>> b/arch/powerpc/lib/checksum_32.S
> >>> index cd00b9bdd772..5a14d45c7b9d 100644
> >>> --- a/arch/powerpc/lib/checksum_32.S
> >>> +++ b/arch/powerpc/lib/checksum_32.S
> >>> @@ -43,6 +43,7 @@ _GLOBAL(__csum_partial)
> >>>        bdnz    2b
> >>>    21: srwi.   r6,r4,4         /* # blocks of 4 words to do */
> >>>        beq     3f
> >>> +     li      r9,4*L1_CACHE_BYTES     /* prefetch distance */
> >>>        lwz     r0,4(r3)
> >>>        mtctr   r6
> >>>        lwz     r6,8(r3)
> >>> @@ -52,7 +53,8 @@ _GLOBAL(__csum_partial)
> >>>        lwzu    r8,16(r3)
> >>>        adde    r5,r5,r7
> >>>        bdz     23f
> >>> -22:  lwz     r0,4(r3)
> >>> +22:  dcbt    r3,r9
> >>> +     lwz     r0,4(r3)
> >>>        adde    r5,r5,r8
> >>>        lwz     r6,8(r3)
> >>>        adde    r5,r5,r0
> >>
>

Reply via email to