From 18d4b6fe8435fb6d0e4ff00fa6434676a7b509be Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Fri, 20 Mar 2020 17:49:03 +0530 Subject: [PATCH] qcacmn: Update the mc timer state after its deleted Currently qdf mc timer stop api updates mc timer state to QDF_TIMER_STATE_STOPPED before it deletes the timer which may lead to race condition where if any other thread tries to read the state of the timer and re-start the timer considering it is stopped which may get deleted after that. To address above issue, update the timer state after timer delete. Change-Id: I302b89bdedf23f8277eacb6d42b5bd8e6daa4d05 CRs-Fixed: 2643254 --- qdf/linux/src/qdf_mc_timer.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/qdf/linux/src/qdf_mc_timer.c b/qdf/linux/src/qdf_mc_timer.c index b4c0453275..b2591b32e9 100644 --- a/qdf/linux/src/qdf_mc_timer.c +++ b/qdf/linux/src/qdf_mc_timer.c @@ -100,21 +100,27 @@ qdf_export_symbol(qdf_try_allowing_sleep); */ QDF_TIMER_STATE qdf_mc_timer_get_current_state(qdf_mc_timer_t *timer) { + QDF_TIMER_STATE timer_state = QDF_TIMER_STATE_UNUSED; + if (!timer) { QDF_ASSERT(0); - return QDF_TIMER_STATE_UNUSED; + return timer_state; } + qdf_spin_lock_irqsave(&timer->platform_info.spinlock); + switch (timer->state) { case QDF_TIMER_STATE_STOPPED: case QDF_TIMER_STATE_STARTING: case QDF_TIMER_STATE_RUNNING: case QDF_TIMER_STATE_UNUSED: - return timer->state; + timer_state = timer->state; + break; default: QDF_ASSERT(0); - return QDF_TIMER_STATE_UNUSED; } + qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock); + return timer_state; } qdf_export_symbol(qdf_mc_timer_get_current_state); @@ -741,12 +747,14 @@ QDF_STATUS qdf_mc_timer_stop(qdf_mc_timer_t *timer) return QDF_STATUS_SUCCESS; } - timer->state = QDF_TIMER_STATE_STOPPED; - qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock); del_timer(&(timer->platform_info.timer)); + qdf_spin_lock_irqsave(&timer->platform_info.spinlock); + timer->state = QDF_TIMER_STATE_STOPPED; + qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock); + qdf_try_allowing_sleep(timer->type); return QDF_STATUS_SUCCESS;