[PATCH 5.4 087/141] can: m_can: m_can_tx_work_queue(): fix tx_skb race condition

From: Greg Kroah-Hartman
Date: Mon May 17 2021 - 11:16:24 EST

From: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx>

[ Upstream commit e04b2cfe61072c7966e1a5fb73dd1feb30c206ed ]

The m_can_start_xmit() function checks if the cdev->tx_skb is NULL and
returns with NETDEV_TX_BUSY in case tx_sbk is not NULL.

There is a race condition in the m_can_tx_work_queue(), where first
the skb is send to the driver and then the case tx_sbk is set to NULL.
A TX complete IRQ might come in between and wake the queue, which
results in tx_skb not being cleared yet.

Fixes: f524f829b75a ("can: m_can: Create a m_can platform framework")
Tested-by: Torin Cooper-Bennun <torin@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
drivers/net/can/m_can/m_can.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index b2224113987c..de275ccb4fd0 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -1418,6 +1418,8 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
int i;
int putidx;

+ cdev->tx_skb = NULL;
/* Generate ID field for TX buffer Element */
/* Common to all supported M_CAN versions */
if (cf->can_id & CAN_EFF_FLAG) {
@@ -1534,7 +1536,6 @@ static void m_can_tx_work_queue(struct work_struct *ws)

- cdev->tx_skb = NULL;

static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,