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 <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2022-09-21 16:46:38 +02:00 committed by Fabio Baltieri
commit f239c3d0e9
2 changed files with 33 additions and 24 deletions

View file

@ -54,9 +54,15 @@ LOG_MODULE_REGISTER(can_stm32, CONFIG_CAN_LOG_LEVEL);
*/ */
static struct k_mutex filter_mutex; 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) 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; const struct can_stm32_config *cfg = dev->config;
CAN_TypeDef *can = cfg->can; CAN_TypeDef *can = cfg->can;
uint32_t bus_off; uint32_t bus_off;
int status;
bus_off = can->ESR & CAN_ESR_BOFF; bus_off = can->ESR & CAN_ESR_BOFF;
if ((can->TSR & CAN_TSR_RQCP0) | bus_off) { if ((can->TSR & CAN_TSR_RQCP0) | bus_off) {
data->mb0.error = status = can->TSR & CAN_TSR_TXOK0 ? 0 :
can->TSR & CAN_TSR_TXOK0 ? 0 :
can->TSR & CAN_TSR_TERR0 ? -EIO : can->TSR & CAN_TSR_TERR0 ? -EIO :
can->TSR & CAN_TSR_ALST0 ? -EBUSY : can->TSR & CAN_TSR_ALST0 ? -EBUSY :
bus_off ? -ENETUNREACH : bus_off ? -ENETUNREACH :
-EIO; -EIO;
/* clear the request. */ /* clear the request. */
can->TSR |= CAN_TSR_RQCP0; 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) { if ((can->TSR & CAN_TSR_RQCP1) | bus_off) {
data->mb1.error = status = can->TSR & CAN_TSR_TXOK1 ? 0 :
can->TSR & CAN_TSR_TXOK1 ? 0 :
can->TSR & CAN_TSR_TERR1 ? -EIO : can->TSR & CAN_TSR_TERR1 ? -EIO :
can->TSR & CAN_TSR_ALST1 ? -EBUSY : can->TSR & CAN_TSR_ALST1 ? -EBUSY :
bus_off ? -ENETUNREACH : bus_off ? -ENETUNREACH :
-EIO; -EIO;
/* clear the request. */ /* clear the request. */
can->TSR |= CAN_TSR_RQCP1; 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) { if ((can->TSR & CAN_TSR_RQCP2) | bus_off) {
data->mb2.error = status = can->TSR & CAN_TSR_TXOK2 ? 0 :
can->TSR & CAN_TSR_TXOK2 ? 0 :
can->TSR & CAN_TSR_TERR2 ? -EIO : can->TSR & CAN_TSR_TERR2 ? -EIO :
can->TSR & CAN_TSR_ALST2 ? -EBUSY : can->TSR & CAN_TSR_ALST2 ? -EBUSY :
bus_off ? -ENETUNREACH : bus_off ? -ENETUNREACH :
-EIO; -EIO;
/* clear the request. */ /* clear the request. */
can->TSR |= CAN_TSR_RQCP2; 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) { if (can->TSR & CAN_TSR_TME) {
@ -415,6 +419,12 @@ static int can_stm32_stop(const struct device *dev)
goto unlock; 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) { if (cfg->phy != NULL) {
ret = can_transceiver_disable(cfg->phy); ret = can_transceiver_disable(cfg->phy);
if (ret != 0) { if (ret != 0) {

View file

@ -25,7 +25,6 @@
struct can_stm32_mailbox { struct can_stm32_mailbox {
can_tx_callback_t tx_callback; can_tx_callback_t tx_callback;
void *callback_arg; void *callback_arg;
int error;
}; };
struct can_stm32_data { struct can_stm32_data {