From f239c3d0e99236cb354a38971bdf11b47f4322a3 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 21 Sep 2022 16:46:38 +0200 Subject: [PATCH] drivers: can: stm32: abort transfers after entering init mode Abort any pending transmissions after entering init mode and notify the senders. Fixes: #50545 Signed-off-by: Henrik Brix Andersen --- drivers/can/can_stm32.c | 56 ++++++++++++++++++++++++----------------- drivers/can/can_stm32.h | 1 - 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/drivers/can/can_stm32.c b/drivers/can/can_stm32.c index c67ea40005f..3437c692eb9 100644 --- a/drivers/can/can_stm32.c +++ b/drivers/can/can_stm32.c @@ -54,9 +54,15 @@ LOG_MODULE_REGISTER(can_stm32, CONFIG_CAN_LOG_LEVEL); */ static struct k_mutex filter_mutex; -static void can_stm32_signal_tx_complete(const struct device *dev, struct can_stm32_mailbox *mb) +static void can_stm32_signal_tx_complete(const struct device *dev, struct can_stm32_mailbox *mb, + int status) { - mb->tx_callback(dev, mb->error, mb->callback_arg); + can_tx_callback_t callback = mb->tx_callback; + + if (callback != NULL) { + callback(dev, status, mb->callback_arg); + mb->tx_callback = NULL; + } } static void can_stm32_rx_fifo_pop(CAN_FIFOMailBox_TypeDef *mbox, struct can_frame *frame) @@ -206,43 +212,41 @@ static inline void can_stm32_tx_isr_handler(const struct device *dev) const struct can_stm32_config *cfg = dev->config; CAN_TypeDef *can = cfg->can; uint32_t bus_off; + int status; bus_off = can->ESR & CAN_ESR_BOFF; if ((can->TSR & CAN_TSR_RQCP0) | bus_off) { - data->mb0.error = - can->TSR & CAN_TSR_TXOK0 ? 0 : - can->TSR & CAN_TSR_TERR0 ? -EIO : - can->TSR & CAN_TSR_ALST0 ? -EBUSY : - bus_off ? -ENETUNREACH : - -EIO; + status = can->TSR & CAN_TSR_TXOK0 ? 0 : + can->TSR & CAN_TSR_TERR0 ? -EIO : + can->TSR & CAN_TSR_ALST0 ? -EBUSY : + bus_off ? -ENETUNREACH : + -EIO; /* clear the request. */ can->TSR |= CAN_TSR_RQCP0; - can_stm32_signal_tx_complete(dev, &data->mb0); + can_stm32_signal_tx_complete(dev, &data->mb0, status); } if ((can->TSR & CAN_TSR_RQCP1) | bus_off) { - data->mb1.error = - can->TSR & CAN_TSR_TXOK1 ? 0 : - can->TSR & CAN_TSR_TERR1 ? -EIO : - can->TSR & CAN_TSR_ALST1 ? -EBUSY : - bus_off ? -ENETUNREACH : - -EIO; + status = can->TSR & CAN_TSR_TXOK1 ? 0 : + can->TSR & CAN_TSR_TERR1 ? -EIO : + can->TSR & CAN_TSR_ALST1 ? -EBUSY : + bus_off ? -ENETUNREACH : + -EIO; /* clear the request. */ can->TSR |= CAN_TSR_RQCP1; - can_stm32_signal_tx_complete(dev, &data->mb1); + can_stm32_signal_tx_complete(dev, &data->mb1, status); } if ((can->TSR & CAN_TSR_RQCP2) | bus_off) { - data->mb2.error = - can->TSR & CAN_TSR_TXOK2 ? 0 : - can->TSR & CAN_TSR_TERR2 ? -EIO : - can->TSR & CAN_TSR_ALST2 ? -EBUSY : - bus_off ? -ENETUNREACH : - -EIO; + status = can->TSR & CAN_TSR_TXOK2 ? 0 : + can->TSR & CAN_TSR_TERR2 ? -EIO : + can->TSR & CAN_TSR_ALST2 ? -EBUSY : + bus_off ? -ENETUNREACH : + -EIO; /* clear the request. */ can->TSR |= CAN_TSR_RQCP2; - can_stm32_signal_tx_complete(dev, &data->mb2); + can_stm32_signal_tx_complete(dev, &data->mb2, status); } if (can->TSR & CAN_TSR_TME) { @@ -415,6 +419,12 @@ static int can_stm32_stop(const struct device *dev) goto unlock; } + /* Abort any pending transmissions */ + can_stm32_signal_tx_complete(dev, &data->mb0, -ENETDOWN); + can_stm32_signal_tx_complete(dev, &data->mb1, -ENETDOWN); + can_stm32_signal_tx_complete(dev, &data->mb2, -ENETDOWN); + can->TSR |= CAN_TSR_ABRQ2 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ0; + if (cfg->phy != NULL) { ret = can_transceiver_disable(cfg->phy); if (ret != 0) { diff --git a/drivers/can/can_stm32.h b/drivers/can/can_stm32.h index 8e315d7e093..a90dcc51152 100644 --- a/drivers/can/can_stm32.h +++ b/drivers/can/can_stm32.h @@ -25,7 +25,6 @@ struct can_stm32_mailbox { can_tx_callback_t tx_callback; void *callback_arg; - int error; }; struct can_stm32_data {