]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: fec: allow disable coalescing
authorJonas Rebmann <jre@pengutronix.de>
Thu, 26 Jun 2025 13:44:02 +0000 (15:44 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 1 Jul 2025 01:22:32 +0000 (18:22 -0700)
In the current implementation, IP coalescing is always enabled and
cannot be disabled.

As setting maximum frames to 0 or 1, or setting delay to zero implies
immediate delivery of single packets/IRQs, disable coalescing in
hardware in these cases.

This also guarantees that coalescing is never enabled with ICFT or ICTT
set to zero, a configuration that could lead to unpredictable behaviour
according to i.MX8MP reference manual.

Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
Reviewed-by: Wei Fang <wei.fang@nxp.com>
Link: https://patch.msgid.link/20250626-fec_deactivate_coalescing-v2-1-0b217f2e80da@pengutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/freescale/fec_main.c

index 63dac42720453a8b8a847bdd1eec76ac072030bf..d4eed252ad4098a7962f615bce98338bc3d12f5c 100644 (file)
@@ -3121,27 +3121,25 @@ static int fec_enet_us_to_itr_clock(struct net_device *ndev, int us)
 static void fec_enet_itr_coal_set(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
-       int rx_itr, tx_itr;
+       u32 rx_itr = 0, tx_itr = 0;
+       int rx_ictt, tx_ictt;
 
-       /* Must be greater than zero to avoid unpredictable behavior */
-       if (!fep->rx_time_itr || !fep->rx_pkts_itr ||
-           !fep->tx_time_itr || !fep->tx_pkts_itr)
-               return;
-
-       /* Select enet system clock as Interrupt Coalescing
-        * timer Clock Source
-        */
-       rx_itr = FEC_ITR_CLK_SEL;
-       tx_itr = FEC_ITR_CLK_SEL;
+       rx_ictt = fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr);
+       tx_ictt = fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr);
 
-       /* set ICFT and ICTT */
-       rx_itr |= FEC_ITR_ICFT(fep->rx_pkts_itr);
-       rx_itr |= FEC_ITR_ICTT(fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr));
-       tx_itr |= FEC_ITR_ICFT(fep->tx_pkts_itr);
-       tx_itr |= FEC_ITR_ICTT(fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr));
+       if (rx_ictt > 0 && fep->rx_pkts_itr > 1) {
+               /* Enable with enet system clock as Interrupt Coalescing timer Clock Source */
+               rx_itr = FEC_ITR_EN | FEC_ITR_CLK_SEL;
+               rx_itr |= FEC_ITR_ICFT(fep->rx_pkts_itr);
+               rx_itr |= FEC_ITR_ICTT(rx_ictt);
+       }
 
-       rx_itr |= FEC_ITR_EN;
-       tx_itr |= FEC_ITR_EN;
+       if (tx_ictt > 0 && fep->tx_pkts_itr > 1) {
+               /* Enable with enet system clock as Interrupt Coalescing timer Clock Source */
+               tx_itr = FEC_ITR_EN | FEC_ITR_CLK_SEL;
+               tx_itr |= FEC_ITR_ICFT(fep->tx_pkts_itr);
+               tx_itr |= FEC_ITR_ICTT(tx_ictt);
+       }
 
        writel(tx_itr, fep->hwp + FEC_TXIC0);
        writel(rx_itr, fep->hwp + FEC_RXIC0);