[PATCH] qualcommax: qca_edma: do not set a zero RX hash

Julius Bairaktaris julius at bairaktaris.de
Sat Oct 24 03:48:13 PDT 2026


Resend as text only for the mailinglist.

On Thu, Oct 22, 2026, John Macias wrote:
> The RX preheader can carry a 5-tuple or 3-tuple hash flag with a zero
> hash value. edma_rx_hash() still passes that value to skb_set_hash()
> as an L4 (or L3) hash, so every such flow gets the same hash and the
> stack does not compute a software hash for it. RPS then steers all
> of these flows to one CPU.

A zero hash makes get_rps_cpu() skip RPS, so the frame stays on the CPU
that took the interrupt. With one RX queue that is one CPU for all
traffic, which matches what you saw.

> This was measured with the single-queue driver from before commit
> 207962a8 ("qualcommax: qca_edma: add multi-queue RX and TX");
> edma_rx_hash() is unchanged since.

The hash was zero because nothing programmed it. Out of reset the PPE
RSS hash puts every flow in the same bucket. Commit da1356d2125
("qualcommax: qca_ppe: spread CPU-bound flows by RSS hash"), merged
together with 207962a8, programs the seed, mix and final registers, so
the preheader now carries a per-flow hash. edma_rx_hash() did not need
to change for that.

Could you rerun the UDP and TCP test on current main with RPS on the
conduit? If the loss is gone, this patch is not needed. A flow whose
programmed hash happens to be zero then only loses RPS for itself.

> + if (!(pre2 & EDMA_RXPH_HASH_MASK))
> + return;

If zero hashes still show up on current main, please send the pre2
values and the traffic that produces them. That would point to a
parser case that does not hash, and the fix belongs there rather than
here.

Julius

Am Sa., 24. Okt. 2026 um 10:01 Uhr schrieb Julius Bairaktaris
<julius at bairaktaris.de>:
>
> On Thu, Oct 22, 2026, John Macias wrote:
> > The RX preheader can carry a 5-tuple or 3-tuple hash flag with a zero
> > hash value. edma_rx_hash() still passes that value to skb_set_hash()
> > as an L4 (or L3) hash, so every such flow gets the same hash and the
> > stack does not compute a software hash for it. RPS then steers all
> > of these flows to one CPU.
>
> A zero hash makes get_rps_cpu() skip RPS, so the frame stays on the CPU
> that took the interrupt. With one RX queue that is one CPU for all
> traffic, which matches what you saw.
>
> > This was measured with the single-queue driver from before commit
> > 207962a8 ("qualcommax: qca_edma: add multi-queue RX and TX");
> > edma_rx_hash() is unchanged since.
>
> The hash was zero because nothing programmed it. Out of reset the PPE
> RSS hash puts every flow in the same bucket. Commit da1356d2125
> ("qualcommax: qca_ppe: spread CPU-bound flows by RSS hash"), merged
> together with 207962a8, programs the seed, mix and final registers, so
> the preheader now carries a per-flow hash. edma_rx_hash() did not need
> to change for that.
>
> Could you rerun the UDP and TCP test on current main with RPS on the
> conduit? If the loss is gone, this patch is not needed. A flow whose
> programmed hash happens to be zero then only loses RPS for itself.
>
> > + if (!(pre2 & EDMA_RXPH_HASH_MASK))
> > + return;
>
> If zero hashes still show up on current main, please send the pre2
> values and the traffic that produces them. That would point to a
> parser case that does not hash, and the fix belongs there rather than
> here.
>
> Julius
>
> On Thu, Oct 22, 2026 06:27 AM, John Macias <dencity7 at gmail.com> wrote:
>>
>> The RX preheader can carry a 5-tuple or 3-tuple hash flag with a zero
>> hash value. edma_rx_hash() still passes that value to skb_set_hash()
>> as an L4 (or L3) hash, so every such flow gets the same hash and the
>> stack does not compute a software hash for it. RPS then steers all
>> of these flows to one CPU.
>>
>> On a Netgear RAX120 v1 (IPQ8074) with RPS enabled on the conduit,
>> UDP forwarded at 900 Mb/s LAN->WAN lost 18-21% with one CPU saturated;
>> skipping zero hashes let the software hash spread flows and the same
>> test ran at 900 Mb/s without loss (TCP 760 -> 941 Mb/s). This was
>> measured with the single-queue driver from before commit 207962a8
>> ("qualcommax: qca_edma: add multi-queue RX and TX"); edma_rx_hash() is
>> unchanged since.
>>
>> Skip the hash when its value is zero.
>>
>> Assisted-by: LLM
>> Signed-off-by: John Macias <dencity7 at gmail.com>
>> ---
>>  .../files/drivers/net/ethernet/qualcomm/qca_edma.c         | 7 +++++++
>>  1 file changed, 7 insertions(+)
>>
>> diff --git a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c
>> index b17ab7d1..5a0e0379 100644
>> --- a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c
>> +++ b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c
>> @@ -584,6 +584,13 @@ static void edma_rx_hash(struct net_device *netdev, struct sk_buff *skb,
>>         if (flag != EDMA_RXPH_HASH_5TUPLE && flag != EDMA_RXPH_HASH_3TUPLE)
>>                 return;
>>
>> +       /* A zero hash carries no flow information. Setting it as an L4 hash
>> +        * would stop the stack from computing a software hash, so RPS would
>> +        * steer every flow to the same CPU.
>> +        */
>> +       if (!(pre2 & EDMA_RXPH_HASH_MASK))
>> +               return;
>> +
>>         skb_set_hash(skb, hash_32(pre2 & EDMA_RXPH_HASH_MASK, 32),
>>                      flag == EDMA_RXPH_HASH_5TUPLE ? PKT_HASH_TYPE_L4 :
>>                                                      PKT_HASH_TYPE_L3);
>> --
>> 2.47.3
>>



More information about the openwrt-devel mailing list