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 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) {

View file

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