summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirav Shah <nnshah@qti.qualcomm.com>2014-03-16 13:36:02 +0530
committerAkash Patel <c_akashp@qca.qualcomm.com>2014-03-20 10:05:41 -0700
commit9640fb6dfd1a0d4ede136d33a9efc353326991f8 (patch)
treedf1632fde484972851ce5c65bdc01d0d7e6f6875
parent948c13ef01704b49b4eeae1d131ae9982dd90725 (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.h11
-rw-r--r--CORE/HDD/inc/wlan_hdd_p2p.h1
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c38
-rw-r--r--CORE/HDD/src/wlan_hdd_p2p.c313
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)) ||