]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: fec: add fec_rx_error_check() to check RX errors
authorWei Fang <wei.fang@nxp.com>
Thu, 5 Feb 2026 08:57:29 +0000 (16:57 +0800)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 10 Feb 2026 09:58:19 +0000 (10:58 +0100)
Extract fec_rx_error_check() from fec_enet_rx_queue(), this helper is
used to check RX errors. And it will be used in XDP and XDP zero copy
paths in subsequent patches.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260205085742.2685134-3-wei.fang@nxp.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/freescale/fec_main.c

index ce433af02ad2deeb149ae20d1867e03e9bb6128e..ee4a20d8c438b4fb01c8b0a13cb3eae694812da7 100644 (file)
@@ -1747,6 +1747,41 @@ static void fec_enet_rx_vlan(const struct net_device *ndev, struct sk_buff *skb)
        }
 }
 
+static int fec_rx_error_check(struct net_device *ndev, u16 status)
+{
+       if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
+                     BD_ENET_RX_CR | BD_ENET_RX_OV | BD_ENET_RX_LAST |
+                     BD_ENET_RX_CL)) {
+               ndev->stats.rx_errors++;
+
+               if (status & BD_ENET_RX_OV) {
+                       /* FIFO overrun */
+                       ndev->stats.rx_fifo_errors++;
+                       return -EIO;
+               }
+
+               if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH |
+                             BD_ENET_RX_LAST)) {
+                       /* Frame too long or too short. */
+                       ndev->stats.rx_length_errors++;
+                       if ((status & BD_ENET_RX_LAST) && net_ratelimit())
+                               netdev_err(ndev, "rcv is not +last\n");
+               }
+
+               /* CRC Error */
+               if (status & BD_ENET_RX_CR)
+                       ndev->stats.rx_crc_errors++;
+
+               /* Report late collisions as a frame error. */
+               if (status & (BD_ENET_RX_NO | BD_ENET_RX_CL))
+                       ndev->stats.rx_frame_errors++;
+
+               return -EIO;
+       }
+
+       return 0;
+}
+
 /* During a receive, the bd_rx.cur points to the current incoming buffer.
  * When we update through the ring, if the next incoming buffer has
  * not been given to the system, we just set the empty indicator,
@@ -1807,29 +1842,8 @@ fec_enet_rx_queue(struct net_device *ndev, u16 queue_id, int budget)
 
                /* Check for errors. */
                status ^= BD_ENET_RX_LAST;
-               if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
-                          BD_ENET_RX_CR | BD_ENET_RX_OV | BD_ENET_RX_LAST |
-                          BD_ENET_RX_CL)) {
-                       ndev->stats.rx_errors++;
-                       if (status & BD_ENET_RX_OV) {
-                               /* FIFO overrun */
-                               ndev->stats.rx_fifo_errors++;
-                               goto rx_processing_done;
-                       }
-                       if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH
-                                               | BD_ENET_RX_LAST)) {
-                               /* Frame too long or too short. */
-                               ndev->stats.rx_length_errors++;
-                               if (status & BD_ENET_RX_LAST)
-                                       netdev_err(ndev, "rcv is not +last\n");
-                       }
-                       if (status & BD_ENET_RX_CR)     /* CRC Error */
-                               ndev->stats.rx_crc_errors++;
-                       /* Report late collisions as a frame error. */
-                       if (status & (BD_ENET_RX_NO | BD_ENET_RX_CL))
-                               ndev->stats.rx_frame_errors++;
+               if (unlikely(fec_rx_error_check(ndev, status)))
                        goto rx_processing_done;
-               }
 
                /* Process the incoming frame. */
                ndev->stats.rx_packets++;