drivers: serial: uart_cc13xx_cc26xx: fix race

Fixing a race in tx/rx_constrained flag access.

Signed-off-by: Florian Grandel <fgrandel@code-for-humans.de>
This commit is contained in:
Florian Grandel 2023-09-04 09:34:05 +02:00 committed by Carles Cufí
parent c9c6676bdd
commit f7e5a103b6

View file

@ -9,6 +9,7 @@
#include <zephyr/device.h>
#include <errno.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/policy.h>
#include <zephyr/drivers/uart.h>
@ -26,6 +27,12 @@ struct uart_cc13xx_cc26xx_config {
uint32_t sys_clk_freq;
};
enum uart_cc13xx_cc26xx_pm_locks {
UART_CC13XX_CC26XX_PM_LOCK_TX,
UART_CC13XX_CC26XX_PM_LOCK_RX,
UART_CC13XX_CC26XX_PM_LOCK_COUNT,
};
struct uart_cc13xx_cc26xx_data {
struct uart_config uart_config;
const struct pinctrl_dev_config *pcfg;
@ -35,8 +42,7 @@ struct uart_cc13xx_cc26xx_data {
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
#ifdef CONFIG_PM
Power_NotifyObj postNotify;
bool tx_constrained;
bool rx_constrained;
ATOMIC_DEFINE(pm_lock, UART_CC13XX_CC26XX_PM_LOCK_COUNT);
#endif
};
@ -240,7 +246,7 @@ static void uart_cc13xx_cc26xx_irq_tx_enable(const struct device *dev)
#ifdef CONFIG_PM
struct uart_cc13xx_cc26xx_data *data = dev->data;
if (!data->tx_constrained) {
if (!atomic_test_and_set_bit(data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_TX)) {
/*
* When tx irq is enabled, it is implicit that we are expecting
* to transmit using the uart, hence we should no longer go
@ -252,7 +258,6 @@ static void uart_cc13xx_cc26xx_irq_tx_enable(const struct device *dev)
* would interfere with a transfer.
*/
pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
data->tx_constrained = true;
}
#endif
@ -268,9 +273,8 @@ static void uart_cc13xx_cc26xx_irq_tx_disable(const struct device *dev)
#ifdef CONFIG_PM
struct uart_cc13xx_cc26xx_data *data = dev->data;
if (data->tx_constrained) {
if (atomic_test_and_clear_bit(data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_TX)) {
pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
data->tx_constrained = false;
}
#endif
}
@ -294,9 +298,8 @@ static void uart_cc13xx_cc26xx_irq_rx_enable(const struct device *dev)
* to receive from the uart, hence we can no longer go into
* standby.
*/
if (!data->rx_constrained) {
if (!atomic_test_and_set_bit(data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_RX)) {
pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
data->rx_constrained = true;
}
#endif
@ -310,9 +313,8 @@ static void uart_cc13xx_cc26xx_irq_rx_disable(const struct device *dev)
#ifdef CONFIG_PM
struct uart_cc13xx_cc26xx_data *data = dev->data;
if (data->rx_constrained) {
if (atomic_test_and_clear_bit(data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_RX)) {
pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
data->rx_constrained = false;
}
#endif
@ -497,8 +499,8 @@ static const struct uart_driver_api uart_cc13xx_cc26xx_driver_api = {
do { \
struct uart_cc13xx_cc26xx_data *dev_data = dev->data; \
\
dev_data->rx_constrained = false; \
dev_data->tx_constrained = false; \
atomic_clear_bit(dev_data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_RX); \
atomic_clear_bit(dev_data->pm_lock, UART_CC13XX_CC26XX_PM_LOCK_TX); \
\
/* Set Power dependencies */ \
if (DT_INST_REG_ADDR(n) == 0x40001000) { \