Skip to content

Commit 3749637

Browse files
Jimmy Assarssonmarckleinebudde
authored andcommitted
can: kvaser_usb: 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 <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 7e0c2f1 commit 3749637

File tree

2 files changed

+60
-95
lines changed

2 files changed

+60
-95
lines changed

drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c

Lines changed: 50 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,42 @@ kvaser_usb_hydra_bus_status_to_can_state(const struct kvaser_usb_net_priv *priv,
926926
}
927927
}
928928

929+
static void kvaser_usb_hydra_change_state(struct kvaser_usb_net_priv *priv,
930+
const struct can_berr_counter *bec,
931+
struct can_frame *cf,
932+
enum can_state new_state)
933+
{
934+
struct net_device *netdev = priv->netdev;
935+
enum can_state old_state = priv->can.state;
936+
enum can_state tx_state, rx_state;
937+
938+
tx_state = (bec->txerr >= bec->rxerr) ?
939+
new_state : CAN_STATE_ERROR_ACTIVE;
940+
rx_state = (bec->txerr <= bec->rxerr) ?
941+
new_state : CAN_STATE_ERROR_ACTIVE;
942+
can_change_state(netdev, cf, tx_state, rx_state);
943+
944+
if (new_state == CAN_STATE_BUS_OFF && old_state < CAN_STATE_BUS_OFF) {
945+
if (priv->can.restart_ms == 0)
946+
kvaser_usb_hydra_send_simple_cmd_async(priv, CMD_STOP_CHIP_REQ);
947+
948+
can_bus_off(netdev);
949+
}
950+
951+
if (priv->can.restart_ms &&
952+
old_state >= CAN_STATE_BUS_OFF &&
953+
new_state < CAN_STATE_BUS_OFF) {
954+
priv->can.can_stats.restarts++;
955+
if (cf)
956+
cf->can_id |= CAN_ERR_RESTARTED;
957+
}
958+
if (cf && new_state != CAN_STATE_BUS_OFF) {
959+
cf->can_id |= CAN_ERR_CNT;
960+
cf->data[6] = bec->txerr;
961+
cf->data[7] = bec->rxerr;
962+
}
963+
}
964+
929965
static void kvaser_usb_hydra_update_state(struct kvaser_usb_net_priv *priv,
930966
u8 bus_status,
931967
const struct can_berr_counter *bec)
@@ -951,41 +987,11 @@ static void kvaser_usb_hydra_update_state(struct kvaser_usb_net_priv *priv,
951987
return;
952988

953989
skb = alloc_can_err_skb(netdev, &cf);
954-
if (skb) {
955-
enum can_state tx_state, rx_state;
956-
957-
tx_state = (bec->txerr >= bec->rxerr) ?
958-
new_state : CAN_STATE_ERROR_ACTIVE;
959-
rx_state = (bec->txerr <= bec->rxerr) ?
960-
new_state : CAN_STATE_ERROR_ACTIVE;
961-
can_change_state(netdev, cf, tx_state, rx_state);
962-
}
963-
964-
if (new_state == CAN_STATE_BUS_OFF && old_state < CAN_STATE_BUS_OFF) {
965-
if (!priv->can.restart_ms)
966-
kvaser_usb_hydra_send_simple_cmd_async
967-
(priv, CMD_STOP_CHIP_REQ);
968-
969-
can_bus_off(netdev);
970-
}
971-
972-
if (!skb) {
990+
kvaser_usb_hydra_change_state(priv, bec, cf, new_state);
991+
if (skb)
992+
netif_rx(skb);
993+
else
973994
netdev_warn(netdev, "No memory left for err_skb\n");
974-
return;
975-
}
976-
977-
if (priv->can.restart_ms &&
978-
old_state >= CAN_STATE_BUS_OFF &&
979-
new_state < CAN_STATE_BUS_OFF)
980-
priv->can.can_stats.restarts++;
981-
982-
if (new_state != CAN_STATE_BUS_OFF) {
983-
cf->can_id |= CAN_ERR_CNT;
984-
cf->data[6] = bec->txerr;
985-
cf->data[7] = bec->rxerr;
986-
}
987-
988-
netif_rx(skb);
989995
}
990996

991997
static void kvaser_usb_hydra_state_event(const struct kvaser_usb *dev,
@@ -1080,7 +1086,6 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,
10801086
struct net_device_stats *stats = &netdev->stats;
10811087
struct can_frame *cf;
10821088
struct sk_buff *skb;
1083-
struct skb_shared_hwtstamps *shhwtstamps;
10841089
struct can_berr_counter bec;
10851090
enum can_state new_state, old_state;
10861091
u8 bus_status;
@@ -1097,51 +1102,22 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,
10971102
&new_state);
10981103

10991104
skb = alloc_can_err_skb(netdev, &cf);
1105+
if (new_state != old_state)
1106+
kvaser_usb_hydra_change_state(priv, &bec, cf, new_state);
11001107

1101-
if (new_state != old_state) {
1102-
if (skb) {
1103-
enum can_state tx_state, rx_state;
1104-
1105-
tx_state = (bec.txerr >= bec.rxerr) ?
1106-
new_state : CAN_STATE_ERROR_ACTIVE;
1107-
rx_state = (bec.txerr <= bec.rxerr) ?
1108-
new_state : CAN_STATE_ERROR_ACTIVE;
1109-
1110-
can_change_state(netdev, cf, tx_state, rx_state);
1111-
1112-
if (priv->can.restart_ms &&
1113-
old_state >= CAN_STATE_BUS_OFF &&
1114-
new_state < CAN_STATE_BUS_OFF)
1115-
cf->can_id |= CAN_ERR_RESTARTED;
1116-
}
1117-
1118-
if (new_state == CAN_STATE_BUS_OFF) {
1119-
if (!priv->can.restart_ms)
1120-
kvaser_usb_hydra_send_simple_cmd_async
1121-
(priv, CMD_STOP_CHIP_REQ);
1122-
1123-
can_bus_off(netdev);
1124-
}
1125-
}
1126-
1127-
if (!skb) {
1128-
stats->rx_dropped++;
1129-
netdev_warn(netdev, "No memory left for err_skb\n");
1130-
return;
1131-
}
1132-
1133-
shhwtstamps = skb_hwtstamps(skb);
1134-
shhwtstamps->hwtstamp = hwtstamp;
1108+
if (skb) {
1109+
struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
11351110

1136-
cf->can_id |= CAN_ERR_BUSERROR;
1137-
if (new_state != CAN_STATE_BUS_OFF) {
1138-
cf->can_id |= CAN_ERR_CNT;
1111+
shhwtstamps->hwtstamp = hwtstamp;
1112+
cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT;
11391113
cf->data[6] = bec.txerr;
11401114
cf->data[7] = bec.rxerr;
1115+
netif_rx(skb);
1116+
} else {
1117+
stats->rx_dropped++;
1118+
netdev_warn(netdev, "No memory left for err_skb\n");
11411119
}
11421120

1143-
netif_rx(skb);
1144-
11451121
priv->bec.txerr = bec.txerr;
11461122
priv->bec.rxerr = bec.rxerr;
11471123
}

drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,8 +1121,6 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
11211121
const struct kvaser_usb_err_summary *es)
11221122
{
11231123
struct can_frame *cf;
1124-
struct can_frame tmp_cf = { .can_id = CAN_ERR_FLAG,
1125-
.len = CAN_ERR_DLC };
11261124
struct sk_buff *skb;
11271125
struct net_device_stats *stats;
11281126
struct kvaser_usb_net_priv *priv;
@@ -1143,18 +1141,9 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
11431141
if (!netif_running(priv->netdev))
11441142
return;
11451143

1146-
/* Update all of the CAN interface's state and error counters before
1147-
* trying any memory allocation that can actually fail with -ENOMEM.
1148-
*
1149-
* We send a temporary stack-allocated error CAN frame to
1150-
* can_change_state() for the very same reason.
1151-
*
1152-
* TODO: Split can_change_state() responsibility between updating the
1153-
* CAN interface's state and counters, and the setting up of CAN error
1154-
* frame ID and data to userspace. Remove stack allocation afterwards.
1155-
*/
11561144
old_state = priv->can.state;
1157-
kvaser_usb_leaf_rx_error_update_can_state(priv, es, &tmp_cf);
1145+
skb = alloc_can_err_skb(priv->netdev, &cf);
1146+
kvaser_usb_leaf_rx_error_update_can_state(priv, es, cf);
11581147
new_state = priv->can.state;
11591148

11601149
/* If there are errors, request status updates periodically as we do
@@ -1168,13 +1157,6 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
11681157
schedule_delayed_work(&leaf->chip_state_req_work,
11691158
msecs_to_jiffies(500));
11701159

1171-
skb = alloc_can_err_skb(priv->netdev, &cf);
1172-
if (!skb) {
1173-
stats->rx_dropped++;
1174-
return;
1175-
}
1176-
memcpy(cf, &tmp_cf, sizeof(*cf));
1177-
11781160
if (new_state != old_state) {
11791161
if (es->status &
11801162
(M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) {
@@ -1187,11 +1169,18 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
11871169
if (priv->can.restart_ms &&
11881170
old_state == CAN_STATE_BUS_OFF &&
11891171
new_state < CAN_STATE_BUS_OFF) {
1190-
cf->can_id |= CAN_ERR_RESTARTED;
1172+
if (cf)
1173+
cf->can_id |= CAN_ERR_RESTARTED;
11911174
netif_carrier_on(priv->netdev);
11921175
}
11931176
}
11941177

1178+
if (!skb) {
1179+
stats->rx_dropped++;
1180+
netdev_warn(priv->netdev, "No memory left for err_skb\n");
1181+
return;
1182+
}
1183+
11951184
switch (dev->driver_info->family) {
11961185
case KVASER_LEAF:
11971186
if (es->leaf.error_factor) {

0 commit comments

Comments
 (0)