can: kvaser_pciefd: Update stats and state even if alloc_can_err_skb() fails

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>
This commit is contained in:
Jimmy Assarsson 2024-12-30 15:26:44 +01:00 committed by Marc Kleine-Budde
parent 0dfa617c3f
commit e048c5e55f

View 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,