wlan: Initialize all adapter completion variables during open adater
In order to change the p2p device mode, delete and add virtual_iface
followed by change_iface will be invoked. But in this case device mode
is changed by invoking change_iface method without invoking delete and
add virtual_iface functions resulting in kernel panic.
This is because, in latter case hdd_open_adapter will not be invoked
for the intended device mode. Hence uninitialized completion variables
will be used for further operations.
To mitigate this issue, Initialize all completion variables of
hdd_adapter_t structure during open adapter irrespective of adapter's
device mode.
Change-Id: I067068c63d061cbc2da22b839f0f64a270f31ce6
CRs-Fixed: 930180
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 3c55dd5..cb4651f 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -6291,32 +6291,7 @@
pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
spin_lock_init(&pAdapter->lock_for_active_session);
- init_completion(&pAdapter->session_open_comp_var);
- init_completion(&pAdapter->session_close_comp_var);
- init_completion(&pAdapter->disconnect_comp_var);
- init_completion(&pAdapter->linkup_event_var);
- init_completion(&pAdapter->cancel_rem_on_chan_var);
- init_completion(&pAdapter->rem_on_chan_ready_event);
- init_completion(&pAdapter->pno_comp_var);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
- init_completion(&pAdapter->offchannel_tx_event);
-#endif
- init_completion(&pAdapter->tx_action_cnf_event);
-#ifdef FEATURE_WLAN_TDLS
- init_completion(&pAdapter->tdls_add_station_comp);
- init_completion(&pAdapter->tdls_del_station_comp);
- init_completion(&pAdapter->tdls_mgmt_comp);
- init_completion(&pAdapter->tdls_link_establish_req_comp);
-#endif
- init_completion(&pHddCtx->mc_sus_event_var);
- init_completion(&pHddCtx->tx_sus_event_var);
- init_completion(&pHddCtx->rx_sus_event_var);
- init_completion(&pAdapter->ula_complete);
- init_completion(&pAdapter->change_country_code);
-
#ifdef FEATURE_WLAN_BATCH_SCAN
- init_completion(&pAdapter->hdd_set_batch_scan_req_var);
- init_completion(&pAdapter->hdd_get_batch_scan_req_var);
pAdapter->pBatchScanRsp = NULL;
pAdapter->numScanList = 0;
pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
@@ -7012,6 +6987,7 @@
mutex_unlock(&pHddCtx->tdls_lock);
#endif
+ hdd_initialize_adapter_common(pAdapter);
status = hdd_init_station_mode( pAdapter );
if( VOS_STATUS_SUCCESS != status )
goto err_free_netdev;
@@ -7070,6 +7046,7 @@
NL80211_IFTYPE_P2P_GO;
pAdapter->device_mode = session_type;
+ hdd_initialize_adapter_common(pAdapter);
status = hdd_init_ap_mode(pAdapter);
if( VOS_STATUS_SUCCESS != status )
goto err_free_netdev;
@@ -7135,6 +7112,7 @@
#endif
status = hdd_register_interface( pAdapter, rtnl_held );
hdd_init_mon_mode( pAdapter );
+ hdd_initialize_adapter_common(pAdapter);
hdd_init_tx_rx( pAdapter );
set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
//Stop the Interface TX queue.
@@ -7159,6 +7137,7 @@
pAdapter->device_mode = session_type;
status = hdd_register_interface( pAdapter, rtnl_held );
+ hdd_initialize_adapter_common(pAdapter);
hdd_init_tx_rx( pAdapter );
//Stop the Interface TX queue.
@@ -7178,7 +7157,7 @@
if( VOS_STATUS_SUCCESS == status )
{
- //Add it to the hdd's session list.
+ //Add it to the hdd's session list.
pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
if( NULL == pHddAdapterNode )
{
@@ -9735,6 +9714,10 @@
init_completion(&pHddCtx->scan_info.abortscan_event_var);
init_completion(&pHddCtx->wiphy_channel_update_event);
init_completion(&pHddCtx->ssr_comp_var);
+ init_completion(&pHddCtx->mc_sus_event_var);
+ init_completion(&pHddCtx->tx_sus_event_var);
+ init_completion(&pHddCtx->rx_sus_event_var);
+
hdd_init_ll_stats_ctx(pHddCtx);
@@ -12412,6 +12395,44 @@
return status;
}
+void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter)
+{
+ if (NULL == pAdapter)
+ {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL ", __func__);
+ return;
+ }
+ init_completion(&pAdapter->session_open_comp_var);
+ init_completion(&pAdapter->session_close_comp_var);
+ init_completion(&pAdapter->disconnect_comp_var);
+ init_completion(&pAdapter->linkup_event_var);
+ init_completion(&pAdapter->cancel_rem_on_chan_var);
+ init_completion(&pAdapter->rem_on_chan_ready_event);
+ init_completion(&pAdapter->pno_comp_var);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ init_completion(&pAdapter->offchannel_tx_event);
+#endif
+ init_completion(&pAdapter->tx_action_cnf_event);
+#ifdef FEATURE_WLAN_TDLS
+ init_completion(&pAdapter->tdls_add_station_comp);
+ init_completion(&pAdapter->tdls_del_station_comp);
+ init_completion(&pAdapter->tdls_mgmt_comp);
+ init_completion(&pAdapter->tdls_link_establish_req_comp);
+#endif
+
+#ifdef WLAN_FEATURE_RMC
+ init_completion(&pAdapter->ibss_peer_info_comp);
+#endif /* WLAN_FEATURE_RMC */
+ init_completion(&pAdapter->ula_complete);
+ init_completion(&pAdapter->change_country_code);
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+ init_completion(&pAdapter->hdd_set_batch_scan_req_var);
+ init_completion(&pAdapter->hdd_get_batch_scan_req_var);
+#endif
+
+ return;
+}
//Register the module init/exit functions