]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
can: ifi_canfd: ifi_canfd_handle_lec_err(): fix {rx,tx}_errors statistics
authorDario Binacchi <dario.binacchi@amarulasolutions.com>
Fri, 22 Nov 2024 22:15:48 +0000 (23:15 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 14 Dec 2024 18:51:26 +0000 (19:51 +0100)
[ Upstream commit bb03d568bb21b4afe7935d1943bcf68ddea3ea45 ]

The ifi_canfd_handle_lec_err() function was incorrectly incrementing only
the receive error counter, even in cases of bit or acknowledgment errors
that occur during transmission.

Fix the issue by incrementing the appropriate counter based on the
type of error.

Fixes: 5bbd655a8bd0 ("can: ifi: Add more detailed error reporting")
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
Reviewed-by: Marek Vasut <marex@denx.de>
Link: https://patch.msgid.link/20241122221650.633981-8-dario.binacchi@amarulasolutions.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/can/ifi_canfd/ifi_canfd.c

index e8318e984bf2f194f8f22d4f8e3eb1a195ad5020..6a66d63f25c1d7b6ca1ab8e2abb6e43294d3d56c 100644 (file)
@@ -393,36 +393,55 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
                return 0;
 
        priv->can.can_stats.bus_error++;
-       stats->rx_errors++;
 
        /* Propagate the error condition to the CAN stack. */
        skb = alloc_can_err_skb(ndev, &cf);
-       if (unlikely(!skb))
-               return 0;
 
        /* Read the error counter register and check for new errors. */
-       cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+       if (likely(skb))
+               cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
 
-       if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST)
-               cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
+       if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST) {
+               stats->rx_errors++;
+               if (likely(skb))
+                       cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
+       }
 
-       if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST)
-               cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+       if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST) {
+               stats->tx_errors++;
+               if (likely(skb))
+                       cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+       }
 
-       if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST)
-               cf->data[2] |= CAN_ERR_PROT_BIT0;
+       if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST) {
+               stats->tx_errors++;
+               if (likely(skb))
+                       cf->data[2] |= CAN_ERR_PROT_BIT0;
+       }
 
-       if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST)
-               cf->data[2] |= CAN_ERR_PROT_BIT1;
+       if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST) {
+               stats->tx_errors++;
+               if (likely(skb))
+                       cf->data[2] |= CAN_ERR_PROT_BIT1;
+       }
 
-       if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST)
-               cf->data[2] |= CAN_ERR_PROT_STUFF;
+       if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST) {
+               stats->rx_errors++;
+               if (likely(skb))
+                       cf->data[2] |= CAN_ERR_PROT_STUFF;
+       }
 
-       if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST)
-               cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+       if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST) {
+               stats->rx_errors++;
+               if (likely(skb))
+                       cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+       }
 
-       if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST)
-               cf->data[2] |= CAN_ERR_PROT_FORM;
+       if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST) {
+               stats->rx_errors++;
+               if (likely(skb))
+                       cf->data[2] |= CAN_ERR_PROT_FORM;
+       }
 
        /* Reset the error counter, ack the IRQ and re-enable the counter. */
        writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR);
@@ -430,6 +449,9 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
               priv->base + IFI_CANFD_INTERRUPT);
        writel(IFI_CANFD_ERROR_CTR_ER_ENABLE, priv->base + IFI_CANFD_ERROR_CTR);
 
+       if (unlikely(!skb))
+               return 0;
+
        netif_receive_skb(skb);
 
        return 1;