diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 029cd8194ed5..64350777765e 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -211,6 +211,7 @@ struct c_can_priv { struct c_can_raminit raminit_sys; /* RAMINIT via syscon regmap */ void (*raminit)(const struct c_can_priv *priv, bool enable); u32 comm_rcv_high; + raw_spinlock_t echo_skb_lock; /* Protects echo_skb array access for RT kernel */ }; struct net_device *alloc_c_can_dev(int msg_obj_num); diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c index 511615dc3341..46f09c92a23c 100644 --- a/drivers/net/can/c_can/c_can_main.c +++ b/drivers/net/can/c_can/c_can_main.c @@ -456,6 +456,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, struct c_can_priv *priv = netdev_priv(dev); struct c_can_tx_ring *tx_ring = &priv->tx; u32 idx, obj, cmd = IF_COMM_TX; + unsigned long flags; if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; @@ -476,7 +477,10 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, * transmit as we might race against do_tx(). */ c_can_setup_tx_object(dev, IF_TX, frame, idx); + /* Minimal lock hold time - only during echo_skb write */ + raw_spin_lock_irqsave(&priv->echo_skb_lock, flags); can_put_echo_skb(skb, dev, idx, 0); + raw_spin_unlock_irqrestore(&priv->echo_skb_lock, flags); obj = idx + priv->msg_obj_tx_first; c_can_object_put(dev, IF_TX, obj, cmd); @@ -740,7 +744,10 @@ static void c_can_do_tx(struct net_device *dev) * NAPI. We are not transmitting. */ c_can_inval_tx_object(dev, IF_NAPI, obj); + /* Minimal lock hold time - only during echo_skb read */ + raw_spin_lock(&priv->echo_skb_lock); bytes += can_get_echo_skb(dev, idx, NULL); + raw_spin_unlock(&priv->echo_skb_lock); pkts++; } @@ -1224,6 +1231,7 @@ struct net_device *alloc_c_can_dev(int msg_obj_num) return NULL; priv = netdev_priv(dev); + raw_spin_lock_init(&priv->echo_skb_lock); priv->msg_obj_num = msg_obj_num; priv->msg_obj_rx_num = msg_obj_num - msg_obj_tx_num; priv->msg_obj_rx_first = 1;