diff options
| author | Ravi Joshi <ravij@qca.qualcomm.com> | 2014-05-29 18:17:34 -0700 |
|---|---|---|
| committer | Akash Patel <c_akashp@qca.qualcomm.com> | 2014-06-03 15:48:33 -0700 |
| commit | 12e242c2f4a3eb15329c34161bd178ffdb3ccb86 (patch) | |
| tree | 044a1f22f659cfedfd2daaf1e351c464bb995acf | |
| parent | 3ab1cfdb7b8972ed9c6510254e0eab2b04165dfe (diff) | |
qcacld: Fix for interface up/down handling as required for STA + STA
Provide the fix for interface up/down handling in the driver. Currently,
the driver just disables the tx and turns off the carrier which takes care
of indicating network subsystem that the interface is down. However,
the request is also required to make sure the underlying Wifi connection
is successfully cleaned up along with any pending data (tx/rx).
Change-Id: I946540219d2af3458b9037000e4d903c4e99eb3e
CRs-Fixed: 668287
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_main.h | 3 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg80211.c | 6 | ||||
| -rwxr-xr-x | CORE/HDD/src/wlan_hdd_main.c | 55 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_p2p.c | 2 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_wext.c | 2 |
5 files changed, 52 insertions, 16 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index e97c777ce2b3..5276bac5827c 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1509,7 +1509,8 @@ hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx ); VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter ); hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode ); void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ); -VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ); +VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + const v_BOOL_t bCloseSession); void hdd_set_station_ops( struct net_device *pWlanDev ); tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx); void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr); diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 52ca68d302fc..aba0b9e15819 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -3221,7 +3221,7 @@ static int wlan_hdd_change_iface_to_sta_mode(struct net_device *ndev, ENTER(); wdev = ndev->ieee80211_ptr; - hdd_stop_adapter(pHddCtx, pAdapter); + hdd_stop_adapter(pHddCtx, pAdapter, VOS_TRUE); hdd_deinit_adapter(pHddCtx, pAdapter); wdev->iftype = type; /*Check for sub-string p2p to confirm its a p2p interface*/ @@ -3452,12 +3452,12 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, if (pP2pAdapter) { - hdd_stop_adapter(pHddCtx, pP2pAdapter); + hdd_stop_adapter(pHddCtx, pP2pAdapter, VOS_TRUE); hdd_deinit_adapter(pHddCtx, pP2pAdapter); hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE); } } - hdd_stop_adapter( pHddCtx, pAdapter ); + hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE ); //De-init the adapter. hdd_deinit_adapter( pHddCtx, pAdapter ); diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index cbccf83b7c79..636c168d3d5b 100755 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -7013,11 +7013,40 @@ int hdd_stop (struct net_device *dev) return -ENODEV; } + /* Nothing to be done if the interface is not opened */ + if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: NETDEV Interface is not OPENED", __func__); + return -ENODEV; + } + + /* Make sure the interface is marked as closed */ clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__); + + /* Disable TX on the interface, after this hard_start_xmit() will not + * be called on that interface + */ netif_tx_disable(pAdapter->dev); + + /* Mark the interface status as "down" for outside world */ netif_carrier_off(pAdapter->dev); + /* The interface is marked as down for outside world (aka kernel) + * But the driver is pretty much alive inside. The driver needs to + * tear down the existing connection on the netdev (session) + * cleanup the data pipes and wait until the control plane is stabilized + * for this interface. The call also needs to wait until the above + * mentioned actions are completed before returning to the caller. + * Notice that the hdd_stop_adapter is requested not to close the session + * That is intentional to be able to scan if it is a STA/P2P interface + */ + hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE); + + /* DeInit the adapter. This ensures datapath cleanup as well */ + hdd_deinit_adapter(pHddCtx, pAdapter); + /* SoftAP ifaces should never go in power save mode making sure same here. */ if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode ) @@ -7032,8 +7061,9 @@ int hdd_stop (struct net_device *dev) return 0; } - /* Find if any iface is up then - if any iface is up then can't put device to sleep/ power save mode. */ + /* Find if any iface is up. If any iface is up then can't put device to + * sleep/power save mode + */ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) ) { @@ -8672,7 +8702,8 @@ void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter) } } -VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) +VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + const v_BOOL_t bCloseSession) { eHalStatus halStatus = eHAL_STATUS_SUCCESS; hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); @@ -8776,21 +8807,25 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) pAdapter->ipv6_notifier_registered = false; } #endif - if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) + /* It is possible that the caller of this function does not + * wish to close the session + */ + if (VOS_TRUE == bCloseSession && + test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) { INIT_COMPLETION(pAdapter->session_close_comp_var); if (eHAL_STATUS_SUCCESS == - sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, - hdd_smeCloseSessionCallback, pAdapter)) + sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, + hdd_smeCloseSessionCallback, pAdapter)) { //Block on a completion variable. Can't wait forever though. ret = wait_for_completion_timeout( - &pAdapter->session_close_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); + &pAdapter->session_close_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); if (0 >= ret) { hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld", - __func__, ret); + __func__, ret); } } } @@ -8911,7 +8946,7 @@ VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx ) while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { pAdapter = pAdapterNode->pAdapter; - hdd_stop_adapter( pHddCtx, pAdapter ); + hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE ); status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); pAdapterNode = pNext; } diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c index 99cef86fb774..4803ff63cf75 100644 --- a/CORE/HDD/src/wlan_hdd_p2p.c +++ b/CORE/HDD/src/wlan_hdd_p2p.c @@ -1684,7 +1684,7 @@ int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev ) wlan_hdd_release_intf_addr( pHddCtx, pVirtAdapter->macAddressCurrent.bytes ); - hdd_stop_adapter( pHddCtx, pVirtAdapter ); + hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE ); hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE ); EXIT(); return 0; diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 66c1362b08c3..9d3e0e3b1a8c 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -7262,7 +7262,7 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in } /*Make sure that pAdapter cleaned properly*/ - hdd_stop_adapter( pHddCtx, pAdapter_to_stop ); + hdd_stop_adapter( pHddCtx, pAdapter_to_stop, VOS_TRUE ); hdd_deinit_adapter( pHddCtx, pAdapter_to_stop ); memset(&pAdapter_to_stop->sessionCtx, 0, sizeof(pAdapter_to_stop->sessionCtx)); |
