]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
can: c_can: c_can_handle_bus_err(): update statistics if skb allocation fails
authorDario Binacchi <dario.binacchi@amarulasolutions.com>
Fri, 22 Nov 2024 22:15:42 +0000 (23:15 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Tue, 26 Nov 2024 09:49:21 +0000 (10:49 +0100)
Ensure that the statistics are always updated, even if the skb
allocation fails.

Fixes: 4d6d26537940 ("can: c_can: fix {rx,tx}_errors statistics")
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
Link: https://patch.msgid.link/20241122221650.633981-2-dario.binacchi@amarulasolutions.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/c_can/c_can_main.c

index 511615dc334196183849dede182f4fc80874ef3e..cc371d0c9f3c769051ff1e0a8954d8c52dbcdbf6 100644 (file)
@@ -1014,49 +1014,57 @@ static int c_can_handle_bus_err(struct net_device *dev,
 
        /* propagate the error condition to the CAN stack */
        skb = alloc_can_err_skb(dev, &cf);
-       if (unlikely(!skb))
-               return 0;
 
        /* check for 'last error code' which tells us the
         * type of the last error to occur on the CAN bus
         */
-       cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+       if (likely(skb))
+               cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
 
        switch (lec_type) {
        case LEC_STUFF_ERROR:
                netdev_dbg(dev, "stuff error\n");
-               cf->data[2] |= CAN_ERR_PROT_STUFF;
+               if (likely(skb))
+                       cf->data[2] |= CAN_ERR_PROT_STUFF;
                stats->rx_errors++;
                break;
        case LEC_FORM_ERROR:
                netdev_dbg(dev, "form error\n");
-               cf->data[2] |= CAN_ERR_PROT_FORM;
+               if (likely(skb))
+                       cf->data[2] |= CAN_ERR_PROT_FORM;
                stats->rx_errors++;
                break;
        case LEC_ACK_ERROR:
                netdev_dbg(dev, "ack error\n");
-               cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+               if (likely(skb))
+                       cf->data[3] = CAN_ERR_PROT_LOC_ACK;
                stats->tx_errors++;
                break;
        case LEC_BIT1_ERROR:
                netdev_dbg(dev, "bit1 error\n");
-               cf->data[2] |= CAN_ERR_PROT_BIT1;
+               if (likely(skb))
+                       cf->data[2] |= CAN_ERR_PROT_BIT1;
                stats->tx_errors++;
                break;
        case LEC_BIT0_ERROR:
                netdev_dbg(dev, "bit0 error\n");
-               cf->data[2] |= CAN_ERR_PROT_BIT0;
+               if (likely(skb))
+                       cf->data[2] |= CAN_ERR_PROT_BIT0;
                stats->tx_errors++;
                break;
        case LEC_CRC_ERROR:
                netdev_dbg(dev, "CRC error\n");
-               cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+               if (likely(skb))
+                       cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
                stats->rx_errors++;
                break;
        default:
                break;
        }
 
+       if (unlikely(!skb))
+               return 0;
+
        netif_receive_skb(skb);
        return 1;
 }