From 4e695c71f384791ef27489198681a68e265f4a2c Mon Sep 17 00:00:00 2001 From: DipSwitch Date: Wed, 31 May 2017 14:06:23 +0200 Subject: [PATCH] driver/at86rf2xx: Fix possible race condition where at86rf2xx_configure returns to the wrong state if waited on finished state in at86rf2xx_setstate --- drivers/at86rf2xx/at86rf2xx_getset.c | 18 ++++++++++-------- drivers/at86rf2xx/at86rf2xx_internal.c | 4 ++-- drivers/include/at86rf2xx.h | 4 +++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/at86rf2xx/at86rf2xx_getset.c b/drivers/at86rf2xx/at86rf2xx_getset.c index 8f5265095ebe5..b61d950bdb78f 100644 --- a/drivers/at86rf2xx/at86rf2xx_getset.c +++ b/drivers/at86rf2xx/at86rf2xx_getset.c @@ -444,17 +444,12 @@ static inline void _set_state(at86rf2xx_t *dev, uint8_t state, uint8_t cmd) dev->state = state; } -void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) +uint8_t at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) { uint8_t old_state = at86rf2xx_get_status(dev); if (state == old_state) { - return; - } - - if (state == AT86RF2XX_STATE_FORCE_TRX_OFF) { - _set_state(dev, AT86RF2XX_STATE_TRX_OFF, state); - return; + return old_state; } /* make sure there is no ongoing transmission, or state transition already @@ -465,8 +460,13 @@ void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) old_state = at86rf2xx_get_status(dev); } + if (state == AT86RF2XX_STATE_FORCE_TRX_OFF) { + _set_state(dev, AT86RF2XX_STATE_TRX_OFF, state); + return old_state; + } + if (state == old_state) { - return; + return old_state; } /* we need to go via PLL_ON if we are moving between RX_AACK_ON <-> TX_ARET_ON */ @@ -493,6 +493,8 @@ void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) } else { _set_state(dev, state, state); } + + return old_state; } void at86rf2xx_reset_state_machine(at86rf2xx_t *dev) diff --git a/drivers/at86rf2xx/at86rf2xx_internal.c b/drivers/at86rf2xx/at86rf2xx_internal.c index 660b691b6cfc1..6a2017d0f8a61 100644 --- a/drivers/at86rf2xx/at86rf2xx_internal.c +++ b/drivers/at86rf2xx/at86rf2xx_internal.c @@ -147,7 +147,7 @@ void at86rf2xx_hardware_reset(at86rf2xx_t *dev) void at86rf2xx_configure_phy(at86rf2xx_t *dev) { - uint8_t state = at86rf2xx_get_status(dev); + uint8_t prev_state = at86rf2xx_get_status(dev); /* we must be in TRX_OFF before changing the PHY configuration */ at86rf2xx_set_state(dev, AT86RF2XX_STATE_TRX_OFF); @@ -200,7 +200,7 @@ void at86rf2xx_configure_phy(at86rf2xx_t *dev) #endif /* Return to the state we had before reconfiguring */ - at86rf2xx_set_state(dev, state); + at86rf2xx_set_state(dev, prev_state); } #if defined(MODULE_AT86RF233) || defined(MODULE_AT86RF231) diff --git a/drivers/include/at86rf2xx.h b/drivers/include/at86rf2xx.h index 3afee08987fcc..9e3453f2d807e 100644 --- a/drivers/include/at86rf2xx.h +++ b/drivers/include/at86rf2xx.h @@ -385,8 +385,10 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state); * * @param[in] dev device to change state of * @param[in] state the targeted new state + * + * @return the previous error before the new state was set */ -void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state); +uint8_t at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state); /** * @brief Reset the internal state machine to TRX_OFF mode.