]> www.infradead.org Git - users/hch/misc.git/commitdiff
can: kvaser_pciefd: Update stats and state even if alloc_can_err_skb() fails
authorJimmy Assarsson <extja@kvaser.com>
Mon, 30 Dec 2024 14:26:44 +0000 (15:26 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Fri, 10 Jan 2025 10:32:39 +0000 (11:32 +0100)
Ensure statistics, error counters, and CAN state are updated consistently,
even when alloc_can_err_skb() fails during state changes or error message
frame reception.

Signed-off-by: Jimmy Assarsson <extja@kvaser.com>
Link: https://patch.msgid.link/20241230142645.128244-3-extja@kvaser.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/kvaser_pciefd.c

index fee012b57f3371423c4c668d7bf9370106cd5afa..e12ff12c4ba31c30f41bf2966c9864acf178d04e 100644 (file)
@@ -1234,11 +1234,15 @@ static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie,
 }
 
 static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can,
+                                      const struct can_berr_counter *bec,
                                       struct can_frame *cf,
                                       enum can_state new_state,
                                       enum can_state tx_state,
                                       enum can_state rx_state)
 {
+       enum can_state old_state;
+
+       old_state = can->can.state;
        can_change_state(can->can.dev, cf, tx_state, rx_state);
 
        if (new_state == CAN_STATE_BUS_OFF) {
@@ -1254,6 +1258,18 @@ static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can,
                        can_bus_off(ndev);
                }
        }
+       if (old_state == CAN_STATE_BUS_OFF &&
+           new_state == CAN_STATE_ERROR_ACTIVE &&
+           can->can.restart_ms) {
+               can->can.can_stats.restarts++;
+               if (cf)
+                       cf->can_id |= CAN_ERR_RESTARTED;
+       }
+       if (cf && new_state != CAN_STATE_BUS_OFF) {
+               cf->can_id |= CAN_ERR_CNT;
+               cf->data[6] = bec->txerr;
+               cf->data[7] = bec->rxerr;
+       }
 }
 
 static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p,
@@ -1299,14 +1315,7 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
        kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
        skb = alloc_can_err_skb(ndev, &cf);
        if (new_state != old_state) {
-               kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
-               if (old_state == CAN_STATE_BUS_OFF &&
-                   new_state == CAN_STATE_ERROR_ACTIVE &&
-                   can->can.restart_ms) {
-                       can->can.can_stats.restarts++;
-                       if (skb)
-                               cf->can_id |= CAN_ERR_RESTARTED;
-               }
+               kvaser_pciefd_change_state(can, &bec, cf, new_state, tx_state, rx_state);
        }
 
        can->err_rep_cnt++;
@@ -1359,6 +1368,7 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
 {
        struct can_berr_counter bec;
        enum can_state old_state, new_state, tx_state, rx_state;
+       int ret = 0;
 
        old_state = can->can.state;
 
@@ -1372,25 +1382,15 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
                struct can_frame *cf;
 
                skb = alloc_can_err_skb(ndev, &cf);
-               if (!skb) {
+               kvaser_pciefd_change_state(can, &bec, cf, new_state, tx_state, rx_state);
+               if (skb) {
+                       kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
+                       netif_rx(skb);
+               } else {
                        ndev->stats.rx_dropped++;
-                       return -ENOMEM;
+                       netdev_warn(ndev, "No memory left for err_skb\n");
+                       ret = -ENOMEM;
                }
-
-               kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
-               if (old_state == CAN_STATE_BUS_OFF &&
-                   new_state == CAN_STATE_ERROR_ACTIVE &&
-                   can->can.restart_ms) {
-                       can->can.can_stats.restarts++;
-                       cf->can_id |= CAN_ERR_RESTARTED;
-               }
-
-               kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
-
-               cf->data[6] = bec.txerr;
-               cf->data[7] = bec.rxerr;
-
-               netif_rx(skb);
        }
        can->bec.txerr = bec.txerr;
        can->bec.rxerr = bec.rxerr;
@@ -1398,7 +1398,7 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
        if (bec.txerr || bec.rxerr)
                mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
 
-       return 0;
+       return ret;
 }
 
 static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,