diff options
| author | Nirav Shah <nnshah@qti.qualcomm.com> | 2014-03-16 13:36:02 +0530 |
|---|---|---|
| committer | Akash Patel <c_akashp@qca.qualcomm.com> | 2014-03-20 10:05:41 -0700 |
| commit | 9640fb6dfd1a0d4ede136d33a9efc353326991f8 (patch) | |
| tree | df1632fde484972851ce5c65bdc01d0d7e6f6875 | |
| parent | 948c13ef01704b49b4eeae1d131ae9982dd90725 (diff) | |
P2P: proactive extension logic for RoC
Driver will request for extended RoC and
cancel it if no action packet is received and
use extended RoC if negotiation is in progress.
Change-Id: If3a5318979bfe4eb7441791bb09916f7f3d570b2
CRs-Fixed: 630569
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_main.h | 11 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_p2p.h | 1 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_main.c | 38 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_p2p.c | 313 |
4 files changed, 253 insertions, 110 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index ddc921d65974..2ff15b6f6449 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -579,6 +579,13 @@ typedef struct v_BOOL_t qBlocked; } hdd_thermal_mitigation_info_t; +typedef struct action_pkt_buffer +{ + tANI_U8* frame_ptr; + tANI_U32 frame_length; + tANI_U16 freq; +}action_pkt_buffer_t; + typedef struct hdd_remain_on_chan_ctx { struct net_device *dev; @@ -588,6 +595,8 @@ typedef struct hdd_remain_on_chan_ctx u64 cookie; rem_on_channel_request_type_t rem_on_chan_request; v_U32_t p2pRemOnChanTimeStamp; + vos_timer_t hdd_remain_on_chan_timer; + action_pkt_buffer_t action_pkt_buff; }hdd_remain_on_chan_ctx_t; typedef enum{ @@ -1036,7 +1045,6 @@ struct hdd_adapter_s v_U8_t psbChanged; /* UAPSD psb value configured through framework */ v_U8_t configuredPsb; - v_BOOL_t internalRoCinProgress; #ifdef IPA_OFFLOAD void *ipa_context; #endif @@ -1044,6 +1052,7 @@ struct hdd_adapter_s unsigned long prev_rx_packets; unsigned long prev_tx_packets; #endif + v_BOOL_t is_roc_inprogress; }; #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) diff --git a/CORE/HDD/inc/wlan_hdd_p2p.h b/CORE/HDD/inc/wlan_hdd_p2p.h index 3337760d6627..f0cd804ac172 100644 --- a/CORE/HDD/inc/wlan_hdd_p2p.h +++ b/CORE/HDD/inc/wlan_hdd_p2p.h @@ -40,6 +40,7 @@ #define WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX 3000 #define READY_EVENT_PROPOGATE_TIME 2 #define ESTIMATED_ROC_DUR_REQD_FOR_ACTION_TX 20 +#define COMPLETE_EVENT_PROPOGATE_TIME 10 #define ACTION_FRAME_DEFAULT_WAIT 200 diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 2ff72334f493..286a82f01a0a 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -7422,6 +7422,7 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) eHalStatus halStatus = eHAL_STATUS_SUCCESS; hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); union iwreq_data wrqu; + v_U8_t retry = 0; ENTER(); @@ -7455,7 +7456,23 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) { hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId); } - + if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION) { + while (pAdapter->is_roc_inprogress) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: ROC in progress for session %d!!!", + __func__, pAdapter->sessionId); + msleep(500); + if (retry++ > 3) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: ROC completion is not received.!!!", __func__); + sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId); + wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var, + msecs_to_jiffies(WAIT_CANCEL_REM_CHAN)); + break; + } + } + } if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) { INIT_COMPLETION(pAdapter->session_close_comp_var); @@ -7475,6 +7492,24 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) case WLAN_HDD_SOFTAP: case WLAN_HDD_P2P_GO: //Any softap specific cleanup here... + if (pAdapter->device_mode == WLAN_HDD_P2P_GO) { + while (pAdapter->is_roc_inprogress) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: ROC in progress for session %d!!!", + __func__, pAdapter->sessionId); + msleep(500); + if (retry++ > 3) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: ROC completion is not received.!!!", __func__); + WLANSAP_CancelRemainOnChannel( + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var, + msecs_to_jiffies(WAIT_CANCEL_REM_CHAN)); + break; + } + } + } + mutex_lock(&pHddCtx->sap_lock); if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)) { @@ -10352,7 +10387,6 @@ static int __init hdd_module_init ( void) } #endif /* #ifdef MODULE */ - /**--------------------------------------------------------------------------- \brief hdd_driver_exit() - Exit function diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c index 533650fe433b..027d75db90ca 100644 --- a/CORE/HDD/src/wlan_hdd_p2p.c +++ b/CORE/HDD/src/wlan_hdd_p2p.c @@ -152,11 +152,12 @@ eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx, } hddLog( LOG1, "Received remain on channel rsp"); + vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer); + vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer); cfgState->remain_on_chan_ctx = NULL; - if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request && - (pAdapter->internalRoCinProgress == VOS_FALSE) ) + if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) { if( cfgState->buf ) { @@ -202,8 +203,15 @@ eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx, NULL, 0 ); } + if(pRemainChanCtx->action_pkt_buff.frame_ptr != NULL + && pRemainChanCtx->action_pkt_buff.frame_length != 0 ) + { + vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr); + } vos_mem_free( pRemainChanCtx ); complete(&pAdapter->cancel_rem_on_chan_var); + pAdapter->is_roc_inprogress = FALSE; + hdd_allow_suspend(); return eHAL_STATUS_SUCCESS; } @@ -261,6 +269,7 @@ void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter) "%s: timeout waiting for cancel remain on channel ready indication", __func__); } + hdd_allow_suspend(); } } @@ -290,6 +299,49 @@ int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter) return status; } +void wlan_hdd_remain_on_chan_timeout(void *data) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *)data; + hdd_remain_on_chan_ctx_t *pRemainChanCtx; + hdd_cfg80211_state_t *cfgState; + + if(NULL == pAdapter) + { + hddLog( LOGE,"%s: pAdapter is NULL !!!", __func__); + return; + } + + cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + pRemainChanCtx = cfgState->remain_on_chan_ctx; + + if(NULL == pRemainChanCtx) + { + hddLog( LOGE,"%s: No Remain on channel is pending", __func__); + return; + } + + hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__); + + if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) || + ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ) + ) + { + sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ), + pAdapter->sessionId ); + } + else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode) + ) + { + WLANSAP_CancelRemainOnChannel( + (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + } + + hdd_allow_suspend(); + +} + static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, @@ -302,6 +354,13 @@ static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy, hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_remain_on_chan_ctx_t *pRemainChanCtx; hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter_temp; + VOS_STATUS status; + v_BOOL_t isGoPresent = VOS_FALSE; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", __func__,pAdapter->device_mode); @@ -359,6 +418,41 @@ static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy, cfgState->remain_on_chan_ctx = pRemainChanCtx; cfgState->current_freq = chan->center_freq; + pRemainChanCtx->action_pkt_buff.freq = 0; + pRemainChanCtx->action_pkt_buff.frame_ptr = NULL; + pRemainChanCtx->action_pkt_buff.frame_length = 0; + + /* Initialize Remain on chan timer */ + vos_status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer, + VOS_TIMER_TYPE_SW, + wlan_hdd_remain_on_chan_timeout, + pAdapter); + if (vos_status != VOS_STATUS_SUCCESS) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Not able to initalize remain_on_chan timer",__func__); + } + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter_temp = pAdapterNode->pAdapter; + if(pAdapter_temp->device_mode == WLAN_HDD_P2P_GO) + { + isGoPresent = VOS_TRUE; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + //Extending duration for proactive extension logic for RoC + if (isGoPresent == VOS_TRUE) + duration = 3 * duration; + else + duration = 5 * duration; + + + hdd_prevent_suspend(); INIT_COMPLETION(pAdapter->rem_on_chan_ready_event); //call sme API to start remain on channel. @@ -369,6 +463,7 @@ static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy, { tANI_U8 sessionId = pAdapter->sessionId; //call sme API to start remain on channel. + sme_RemainOnChannel( WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId, chan->hw_value, duration, @@ -398,6 +493,7 @@ static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy, "%s: WLANSAP_RemainOnChannel returned fail", __func__); cfgState->remain_on_chan_ctx = NULL; vos_mem_free (pRemainChanCtx); + hdd_allow_suspend(); return -EINVAL; } @@ -411,10 +507,12 @@ static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy, "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__); WLANSAP_CancelRemainOnChannel( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + hdd_allow_suspend(); return -EINVAL; } } + pAdapter->is_roc_inprogress = TRUE; return 0; } @@ -447,6 +545,7 @@ void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter ) { hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); hdd_remain_on_chan_ctx_t* pRemainChanCtx = cfgState->remain_on_chan_ctx; + VOS_STATUS status; hddLog( LOG1, "Ready on chan ind"); @@ -457,8 +556,15 @@ void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter ) pRemainChanCtx->p2pRemOnChanTimeStamp = vos_timer_get_system_time() - READY_EVENT_PROPOGATE_TIME; - if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request - && (pAdapter->internalRoCinProgress == VOS_FALSE) ) + //start timer for actual duration + 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"); + } + + if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) { cfg80211_ready_on_channel( #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) @@ -474,12 +580,39 @@ void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter ) pRemainChanCtx->duration, GFP_KERNEL ); } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request - || (pAdapter->internalRoCinProgress == VOS_TRUE)) + else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request) { complete(&pAdapter->offchannel_tx_event); } #endif + + // Check for cached action frame + if(pRemainChanCtx->action_pkt_buff.frame_length != 0) + { + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) + cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,pRemainChanCtx->action_pkt_buff.freq, 0, + pRemainChanCtx->action_pkt_buff.frame_ptr, + pRemainChanCtx->action_pkt_buff.frame_length, + GFP_ATOMIC ); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + cfg80211_rx_mgmt( pAdapter->dev, pRemainChanCtx->action_pkt_buff.freq, 0, + pRemainChanCtx->action_pkt_buff.frame_ptr, + pRemainChanCtx->action_pkt_buff.frame_length, + GFP_ATOMIC ); +#else + cfg80211_rx_mgmt( pAdapter->dev, pRemainChanCtx->action_pkt_buff.freq, + pRemainChanCtx->action_pkt_buff.frame_ptr, + pRemainChanCtx->action_pkt_buff.frame_length, + GFP_ATOMIC ); +#endif //LINUX_VERSION_CODE + + hddLog( LOGE,"%s: Sent cached action frame to supplicant", __func__); + vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr); + pRemainChanCtx->action_pkt_buff.frame_length = 0; + pRemainChanCtx->action_pkt_buff.freq = 0; + pRemainChanCtx->action_pkt_buff.frame_ptr = NULL; + } complete(&pAdapter->rem_on_chan_ready_event); } else @@ -566,6 +699,7 @@ int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy, } wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var, msecs_to_jiffies(WAIT_CANCEL_REM_CHAN)); + hdd_allow_suspend(); return 0; } @@ -746,60 +880,28 @@ int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, if( offchan && wait) { int status; - hdd_remain_on_chan_ctx_t old_roc_ctx; rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX; // In case of P2P Client mode if we are already // on the same channel then send the frame directly - //For remain on channel we issue a passive scan to firmware - //but currently there is no provision for dynamically extending - //the dwell time therefore cancelling the ongoing remain on channel - //and requesting for new one. - //The below logic will be extended for request type action frames if - //needed in future. if ((type == SIR_MAC_MGMT_FRAME) && - (subType == SIR_MAC_MGMT_ACTION) && - hdd_p2p_is_action_type_rsp(&buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET]) && - cfgState->remain_on_chan_ctx && - cfgState->current_freq == chan->center_freq ) { - - tANI_U32 current_time = vos_timer_get_system_time(); - - // In case of P2P Client mode if we are already - // on the same channel then send the frame directly only if - // there is enough remain on channel time left. - // If remain on channel time is about to expire in next 20ms - // then dont send frame without a fresh remain on channel as this - // may cause a race condition with lim remain_on_channel_timer - // which might expire by the time the action frame reaches lim - // layer. - // For Rome check remaining time of RoC only in case of GO NEG CNF. - // For other RSPs always extend - actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; - - if ( -#if defined (QCA_WIFI_2_0) && !defined (QCA_WIFI_ISOC) - (actionFrmType != WLAN_HDD_GO_NEG_CNF) || -#endif - ((int)(cfgState->remain_on_chan_ctx->duration - - (current_time - - cfgState->remain_on_chan_ctx->p2pRemOnChanTimeStamp)) < - ESTIMATED_ROC_DUR_REQD_FOR_ACTION_TX)) - { - hddLog(LOG1,"action frame: Extending the RoC"); - pAdapter->internalRoCinProgress = VOS_TRUE; - // saved old RoC Context - vos_mem_copy(&old_roc_ctx,cfgState->remain_on_chan_ctx, - sizeof(hdd_remain_on_chan_ctx_t)); - status = wlan_hdd_check_remain_on_channel(pAdapter); - if ( status ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Failed to cancel the existing RoC"); - pAdapter->internalRoCinProgress = VOS_FALSE; - } - } - } + (subType == SIR_MAC_MGMT_ACTION) && + hdd_p2p_is_action_type_rsp(&buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET]) && + cfgState->remain_on_chan_ctx && + cfgState->current_freq == chan->center_freq ) + { + if(wait) + { + 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"); + } + } + goto send_frame; + } if((cfgState->remain_on_chan_ctx != NULL) && (cfgState->current_freq == chan->center_freq) @@ -811,9 +913,6 @@ int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, } INIT_COMPLETION(pAdapter->offchannel_tx_event); - // Restore request type if it is internal RoC. - if(pAdapter->internalRoCinProgress == VOS_TRUE) - req_type = old_roc_ctx.rem_on_chan_request; status = wlan_hdd_request_remain_on_channel(wiphy, dev, chan, @@ -822,35 +921,8 @@ int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, #endif wait, cookie, req_type); - - // Assign the preserved cookie value here to appear as - // same RoC to supplicant - if (cfgState->remain_on_chan_ctx && - (pAdapter->internalRoCinProgress == VOS_TRUE)) - cfgState->remain_on_chan_ctx->cookie = old_roc_ctx.cookie; - if(0 != status) { - // If new RoC request fails then indicate complete RoC - // to supplicant if internalRoCinProgress using old RoC Context - if(pAdapter->internalRoCinProgress == VOS_TRUE) - { - hddLog( LOGE, "Indicate Complete RoC to supplicant for" - "cookie %llu",old_roc_ctx.cookie); - cfg80211_remain_on_channel_expired( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) - old_roc_ctx.dev->ieee80211_ptr, -#else - old_roc_ctx.dev, -#endif - old_roc_ctx.cookie, - &old_roc_ctx.chan, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) - old_roc_ctx.chan_type, -#endif - GFP_KERNEL); - pAdapter->internalRoCinProgress = VOS_FALSE; - } if( (-EBUSY == status) && (cfgState->current_freq == chan->center_freq) ) { @@ -869,32 +941,10 @@ int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX)); if(!status) { - // If Ready indication timeout occuers then indicate complete - // RoC to supplicant is internalRoCin Progress is set - if(cfgState->remain_on_chan_ctx && - (pAdapter->internalRoCinProgress == VOS_TRUE)) - { - hddLog( LOGE, "Indicate Complete RoC to supplicant for" - "cookie %llu Timeout",cfgState->remain_on_chan_ctx->cookie); - cfg80211_remain_on_channel_expired( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) - cfgState->remain_on_chan_ctx->dev->ieee80211_ptr, -#else - cfgState->remain_on_chan_ctx->dev, -#endif - cfgState->remain_on_chan_ctx->cookie, - &cfgState->remain_on_chan_ctx->chan, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) - cfgState->remain_on_chan_ctx->chan_type, -#endif - GFP_KERNEL); - pAdapter->internalRoCinProgress = VOS_FALSE; - } hddLog( LOGE, "Not able to complete remain on channel request" " within timeout period"); goto err_rem_channel; } - pAdapter->internalRoCinProgress = VOS_FALSE; } else if ( offchan ) { @@ -1531,10 +1581,13 @@ void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter, tANI_S8 rxRssi ) { tANI_U16 freq; + tANI_U16 extend_time; tANI_U8 type = 0; tANI_U8 subType = 0; tActionFrmType actionFrmType; hdd_cfg80211_state_t *cfgState = NULL; + VOS_STATUS status; + hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL; hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d\n", __func__, frameType, nFrameLength); @@ -1622,6 +1675,7 @@ void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter, } cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + pRemainChanCtx = cfgState->remain_on_chan_ctx; if ((type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_ACTION)) @@ -1668,6 +1722,51 @@ void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter, } } #endif + if (pRemainChanCtx != NULL) + { + if(actionFrmType == WLAN_HDD_GO_NEG_REQ || + actionFrmType == WLAN_HDD_GO_NEG_RESP || + actionFrmType == WLAN_HDD_INVITATION_REQ || + actionFrmType == WLAN_HDD_DEV_DIS_REQ || + actionFrmType == WLAN_HDD_PROV_DIS_REQ ) + { + hddLog( LOG1, "Extend RoC timer on reception of Action Frame"); + + if ((actionFrmType == WLAN_HDD_GO_NEG_REQ) + || (actionFrmType == WLAN_HDD_GO_NEG_RESP)) + extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT; + else + extend_time = ACTION_FRAME_DEFAULT_WAIT; + + 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) + { + hddLog( LOGE, "Remain on Channel timer start failed"); + } + } else { + // Buffer Packet + if(pRemainChanCtx->action_pkt_buff.frame_length == 0) + { + pRemainChanCtx->action_pkt_buff.frame_length = nFrameLength; + pRemainChanCtx->action_pkt_buff.freq = freq; + pRemainChanCtx->action_pkt_buff.frame_ptr + = vos_mem_malloc(nFrameLength); + vos_mem_copy(pRemainChanCtx->action_pkt_buff.frame_ptr, + pbFrames, nFrameLength); + hddLog( LOGE,"%s:" + "Action Pkt Cached successfully !!!", __func__); + } else { + hddLog( LOGE,"%s:" + "Frames are pending. dropping frame !!!", __func__); + } + return; + } + } + } if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) && (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) || |
