summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirav Shah <nnshah@qti.qualcomm.com>2014-04-17 17:38:43 +0530
committerPitani Venkata Rajesh Kumar <c_vpitan@qti.qualcomm.com>2014-04-22 11:48:41 +0530
commit45799d49e9cb6c67f247d375abfcb3f6e73f2e02 (patch)
tree2a6caf25b5a11eed86dc569b33416f4409f1aff9
parentc69169710313d30156d1846d20662d1f4f0b0e04 (diff)
P2P: Add Cancel RoC progress flag to handle race condition
Add hdd_remain_on_chan_cancel_in_progress flag to handle race condition between Action Tx packet or cancel RoC from supplicant and complete event. Change-Id: I7e9dd5e01675e1344be4628eeb56fb6db150e597 CRs-Fixed: 650326
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h1
-rw-r--r--CORE/HDD/src/wlan_hdd_p2p.c121
2 files changed, 109 insertions, 13 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 9afb22b77ef3..a6ddfa4fcb32 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -619,6 +619,7 @@ typedef struct hdd_remain_on_chan_ctx
v_U32_t p2pRemOnChanTimeStamp;
vos_timer_t hdd_remain_on_chan_timer;
action_pkt_buffer_t action_pkt_buff;
+ v_BOOL_t hdd_remain_on_chan_cancel_in_progress;
}hdd_remain_on_chan_ctx_t;
typedef enum{
diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c
index 937196c17c85..c946e55b180d 100644
--- a/CORE/HDD/src/wlan_hdd_p2p.c
+++ b/CORE/HDD/src/wlan_hdd_p2p.c
@@ -264,12 +264,34 @@ eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
{
hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+ hdd_remain_on_chan_ctx_t *pRemainChanCtx;
int status = 0;
+ mutex_lock(&cfgState->remain_on_chan_ctx_lock);
if(cfgState->remain_on_chan_ctx != NULL)
{
hddLog( LOG1, "Cancel Existing Remain on Channel");
+ vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
+ pRemainChanCtx = cfgState->remain_on_chan_ctx;
+ if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE)
+ {
+ mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
+ hddLog( LOG1,
+ "ROC timer cancellation in progress,"
+ " wait for completion");
+ status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
+ msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
+ if (0 >= status)
+ {
+ hddLog( LOGE,
+ "%s:wait on cancel_rem_on_chan_var failed %d",
+ __func__, status);
+ }
+ return;
+ }
+ pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
+ mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
/* Wait till remain on channel ready indication before issuing cancel
* remain on channel request, otherwise if remain on channel not
* received and if the driver issues cancel remain on channel then lim
@@ -320,7 +342,8 @@ void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
__func__, status);
}
hdd_allow_suspend();
- }
+ } else
+ mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
}
int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
@@ -370,6 +393,13 @@ void wlan_hdd_remain_on_chan_timeout(void *data)
return;
}
+ if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
+ {
+ hddLog( LOGE, FL("Cancellation already in progress"));
+ return;
+ }
+
+ pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
@@ -475,6 +505,7 @@ static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
pRemainChanCtx->action_pkt_buff.freq = 0;
pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
pRemainChanCtx->action_pkt_buff.frame_length = 0;
+ pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
/* Initialize Remain on chan timer */
vos_status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
@@ -636,11 +667,18 @@ void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
vos_timer_get_system_time() - READY_EVENT_PROPOGATE_TIME;
//start timer for actual duration
+ if(VOS_TIMER_STATE_RUNNING ==
+ vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
+ {
+ hddLog( LOGE, "Timer Started before ready event!!!");
+ vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
+ }
status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
(pRemainChanCtx->duration + COMPLETE_EVENT_PROPOGATE_TIME));
if (status != VOS_STATUS_SUCCESS)
{
- hddLog( LOGE, "Remain on Channel timer start failed");
+ hddLog( LOGE, "%s: Remain on Channel timer start failed",
+ __func__);
}
if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
@@ -715,6 +753,7 @@ int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
#endif
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+ hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
int status;
@@ -741,6 +780,30 @@ int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
return -EINVAL;
}
+
+ if (NULL != cfgState->remain_on_chan_ctx)
+ {
+ vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
+ if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
+ {
+ mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
+ hddLog( LOG1,
+ FL("ROC timer cancellation in progress,"
+ " wait for completion"));
+ status = wait_for_completion_interruptible_timeout(
+ &pAdapter->cancel_rem_on_chan_var,
+ msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
+ if (0 >= status)
+ {
+ hddLog( LOGE,
+ "%s:wait on cancel_rem_on_chan_var failed %d",
+ __func__, status);
+ }
+ return 0;
+ }
+ else
+ pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
+ }
mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
/* wait until remain on channel ready event received
@@ -840,6 +903,7 @@ int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
#endif
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+ hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
tANI_U16 extendedWait = 0;
tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
@@ -999,20 +1063,42 @@ int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
cfgState->remain_on_chan_ctx &&
cfgState->current_freq == chan->center_freq )
{
- if(wait)
+ if(VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
+ &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
{
vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
status = vos_timer_start(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
wait);
if(status != VOS_STATUS_SUCCESS)
{
- hddLog( LOGE, "Remain on Channel timer start failed");
+ hddLog( LOGE, "%s: Remain on Channel timer start failed",
+ __func__);
}
+ mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
+ goto send_frame;
+ } else {
+
+ if(pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE)
+ {
+ mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ "action frame tx: waiting for completion of ROC ");
+
+ status = wait_for_completion_interruptible_timeout(
+ &pAdapter->cancel_rem_on_chan_var,
+ msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
+ if (0 >= status)
+ {
+ hddLog( LOGE,
+ "%s:wait on cancel_rem_on_chan_var failed %d",
+ __func__, status);
+ }
+
+ } else
+ mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
}
- mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
- goto send_frame;
- }
- mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
+ } else
+ mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
if((cfgState->remain_on_chan_ctx != NULL) &&
(cfgState->current_freq == chan->center_freq)
@@ -1879,12 +1965,21 @@ void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
if(completion_done(&pAdapter->rem_on_chan_ready_event))
{
- vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
- status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
- extend_time);
- if (status != VOS_STATUS_SUCCESS)
+ if(VOS_TIMER_STATE_RUNNING ==
+ vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
{
- hddLog( LOGE, "Remain on Channel timer start failed");
+ vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
+ status = vos_timer_start(
+ &pRemainChanCtx->hdd_remain_on_chan_timer,
+ extend_time);
+ if (status != VOS_STATUS_SUCCESS)
+ {
+ hddLog( LOGE, "%s: Remain on Channel timer start failed",
+ __func__);
+ }
+ } else {
+ hddLog( LOG1, "%s: Rcvd action frame after timer expired",
+ __func__);
}
} else {
// Buffer Packet