mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 00:24:41 -04:00
qcacld-3.0: Handle disconnect requests during LFR3 roaming
Propagation from cld3.0-1.1 to cld3.0-2.0 Upper layer can send cfg80211 disconnect command anytime in the life of a connection. It arrive when firmware roaming may have started, completed, failed, etc. Processing of roam events may collide with processing of disconnect command in the host driver. Defer the hdd disconnect command if roaming has started. Upon completing roaming send the deferred disconnect command to sme which will eventually complete the requested disconnect. If disconnect is deferred during roaming, then do not send the new roam event to supplicant since it is not expected and upon honoring the disconnect later, a disconnect event would be sent to supplicant. Remove the earlier workaround done to send a try again error message to upper layers upon receiving a disconnect request when roaming is in progress Firmware can now handle the ROAM_SCAN_OFFLOAD_STOP command even if it is in the middle of roaming operation. Hence remove this check in SME. Add LFR3 roaming state to the cds_is_connection_in_progress API since it currently captures only LFR2 roaming states. Change-Id: Id352d94b41f0766889ceebd0b57b2c566ce3ca42 CRs-Fixed: 1114853
This commit is contained in:
parent
426bd9eda3
commit
a578414c8a
7 changed files with 163 additions and 34 deletions
|
|
@ -899,10 +899,15 @@ bool cds_is_connection_in_progress(uint8_t *session_id,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
if ((QDF_STA_MODE == adapter->device_mode) &&
|
||||
/*
|
||||
* sme_neighbor_middle_of_roaming is for LFR2
|
||||
* hdd_is_roaming_in_progress is for LFR3
|
||||
*/
|
||||
if (((QDF_STA_MODE == adapter->device_mode) &&
|
||||
sme_neighbor_middle_of_roaming(
|
||||
WLAN_HDD_GET_HAL_CTX(adapter),
|
||||
adapter->sessionId)) {
|
||||
adapter->sessionId)) ||
|
||||
hdd_is_roaming_in_progress(adapter)) {
|
||||
cds_err("%p(%d) Reassociation in progress",
|
||||
WLAN_HDD_GET_STATION_CTX_PTR(adapter),
|
||||
adapter->sessionId);
|
||||
|
|
|
|||
|
|
@ -1144,8 +1144,28 @@ struct hdd_adapter_s {
|
|||
struct hdd_connect_pm_context connect_rpm_ctx;
|
||||
|
||||
bool fast_roaming_allowed;
|
||||
/*
|
||||
* defer disconnect is used as a flag by roaming to check
|
||||
* if any disconnect has been deferred because of roaming
|
||||
* and handle it. It stores the source of the disconnect.
|
||||
* Based on the source, it will appropriately handle the
|
||||
* disconnect.
|
||||
*/
|
||||
uint8_t defer_disconnect;
|
||||
/*
|
||||
* cfg80211 issues a reason for disconnect. Store this reason if the
|
||||
* disconnect is being deferred.
|
||||
*/
|
||||
uint8_t cfg80211_disconnect_reason;
|
||||
};
|
||||
|
||||
/*
|
||||
* Below two definitions are useful to distinguish the
|
||||
* source of the disconnect when a disconnect is deferred
|
||||
*/
|
||||
#define DEFER_DISCONNECT_TRY_DISCONNECT 1
|
||||
#define DEFER_DISCONNECT_CFG80211_DISCONNECT 2
|
||||
|
||||
#define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station)
|
||||
#define WLAN_HDD_GET_AP_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.ap)
|
||||
#define WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter) (&(pAdapter)->sessionCtx.station.WextState)
|
||||
|
|
@ -2163,7 +2183,7 @@ static inline int wlan_hdd_validate_session_id(u8 session_id)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bool hdd_is_roaming_in_progress(void);
|
||||
bool hdd_is_roaming_in_progress(hdd_adapter_t *adapter);
|
||||
void hdd_set_roaming_in_progress(bool value);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2040,9 +2040,10 @@ static void hdd_send_re_assoc_event(struct net_device *dev,
|
|||
hdd_notice("Req RSN IE:");
|
||||
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
|
||||
final_req_ie, (ssid_ie_len + reqRsnLength));
|
||||
cfg80211_roamed_bss(dev, bss,
|
||||
final_req_ie, (ssid_ie_len + reqRsnLength),
|
||||
rspRsnIe, rspRsnLength, GFP_KERNEL);
|
||||
if (!pAdapter->defer_disconnect)
|
||||
cfg80211_roamed_bss(dev, bss,
|
||||
final_req_ie, (ssid_ie_len + reqRsnLength),
|
||||
rspRsnIe, rspRsnLength, GFP_KERNEL);
|
||||
|
||||
qdf_mem_copy(assoc_req_ies,
|
||||
(u8 *)pCsrRoamInfo->pbFrames + pCsrRoamInfo->nBeaconLength,
|
||||
|
|
@ -2637,7 +2638,8 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
|
|||
pConnectedProfile->SSID.ssId,
|
||||
pRoamInfo->u.
|
||||
pConnectedProfile->SSID.length);
|
||||
cfg80211_roamed_bss(dev,
|
||||
if (!pAdapter->defer_disconnect)
|
||||
cfg80211_roamed_bss(dev,
|
||||
roam_bss,
|
||||
pFTAssocReq,
|
||||
assocReqlen,
|
||||
|
|
@ -4786,6 +4788,8 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
|
|||
hdd_info("After Roam Synch Comp: NAPI Serialize OFF");
|
||||
hdd_napi_serialize(0);
|
||||
hdd_set_roaming_in_progress(false);
|
||||
if (pAdapter->defer_disconnect)
|
||||
hdd_process_defer_disconnect(pAdapter);
|
||||
break;
|
||||
case eCSR_ROAM_SHOULD_ROAM:
|
||||
/* notify apps that we can't pass traffic anymore */
|
||||
|
|
@ -5046,6 +5050,11 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
|
|||
WLAN_CONTROL_PATH);
|
||||
cds_set_connection_in_progress(false);
|
||||
hdd_set_roaming_in_progress(false);
|
||||
/*
|
||||
* If disconnect operation is in deferred state, do it now.
|
||||
*/
|
||||
if (pAdapter->defer_disconnect)
|
||||
hdd_process_defer_disconnect(pAdapter);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -4335,6 +4335,19 @@ int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
|
|||
!roam_info_ptr->roamSynchInProgress)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The user space has issued a disconnect when roaming is in
|
||||
* progress. The disconnect should be honored gracefully.
|
||||
* If the roaming is complete and the roam event is sent
|
||||
* back to the user space, it will get confused as it is
|
||||
* expecting a disconnect event. So, do not send the event
|
||||
* and handle the disconnect later.
|
||||
*/
|
||||
if (adapter->defer_disconnect) {
|
||||
hdd_notice("LFR3:Do not send roam auth event");
|
||||
return 0;
|
||||
}
|
||||
|
||||
skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
|
||||
&(adapter->wdev),
|
||||
ETH_ALEN + req_rsn_len + rsp_rsn_len +
|
||||
|
|
@ -13904,8 +13917,34 @@ int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
|
|||
unsigned long rc;
|
||||
hdd_station_ctx_t *pHddStaCtx;
|
||||
int status, result = 0;
|
||||
tHalHandle hal;
|
||||
|
||||
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
|
||||
hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
|
||||
if (pAdapter->device_mode == QDF_STA_MODE) {
|
||||
hdd_notice("Stop firmware roaming");
|
||||
sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
|
||||
}
|
||||
/*
|
||||
* If firmware has already started roaming process, driver
|
||||
* needs to defer the processing of this disconnect request.
|
||||
*
|
||||
*/
|
||||
if (hdd_is_roaming_in_progress(pAdapter)) {
|
||||
/*
|
||||
* Defer the disconnect action until firmware roaming
|
||||
* result is received. If STA is in connected state after
|
||||
* that, send the disconnect command to CSR, otherwise
|
||||
* CSR would have already sent disconnect event to upper
|
||||
* layer.
|
||||
*/
|
||||
|
||||
hdd_err("Roaming in progress, <try disconnect> deferred.");
|
||||
pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
|
||||
pAdapter->cfg80211_disconnect_reason =
|
||||
eCSR_DISCONNECT_REASON_UNSPECIFIED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
|
||||
(eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
|
||||
|
|
@ -14156,6 +14195,7 @@ static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
|
|||
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
|
||||
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
|
||||
eConnectionState prev_conn_state;
|
||||
tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
|
||||
|
||||
ENTER();
|
||||
|
||||
|
|
@ -14163,18 +14203,41 @@ static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
|
|||
|
||||
if (0 != status)
|
||||
return status;
|
||||
if (pAdapter->device_mode == QDF_STA_MODE) {
|
||||
hdd_notice("Stop firmware roaming");
|
||||
status = sme_stop_roaming(hal, pAdapter->sessionId,
|
||||
eCsrHddIssued);
|
||||
}
|
||||
/*
|
||||
* If firmware has already started roaming process, driver
|
||||
* needs to defer the processing of this disconnect request.
|
||||
*/
|
||||
if (hdd_is_roaming_in_progress(pAdapter)) {
|
||||
/*
|
||||
* Defer the disconnect action until firmware roaming
|
||||
* result is received. If STA is in connected state after
|
||||
* that, send the disconnect command to CSR, otherwise
|
||||
* CSR would have already sent disconnect event to upper
|
||||
* layer.
|
||||
*/
|
||||
hdd_err("Roaming in progress, disconnect command deferred.");
|
||||
pAdapter->defer_disconnect =
|
||||
DEFER_DISCONNECT_CFG80211_DISCONNECT;
|
||||
pAdapter->cfg80211_disconnect_reason = reason;
|
||||
return 0;
|
||||
}
|
||||
|
||||
prev_conn_state = pHddStaCtx->conn_info.connState;
|
||||
|
||||
/*stop tx queues */
|
||||
/* stop tx queues */
|
||||
hdd_notice("Disabling queues");
|
||||
wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
|
||||
WLAN_CONTROL_PATH);
|
||||
wlan_hdd_netif_queue_control(pAdapter,
|
||||
WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH);
|
||||
hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
|
||||
pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
|
||||
INIT_COMPLETION(pAdapter->disconnect_comp_var);
|
||||
|
||||
/*issue disconnect */
|
||||
/* issue disconnect */
|
||||
|
||||
status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
|
||||
pAdapter->sessionId, reason);
|
||||
|
|
@ -14326,11 +14389,6 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
|
|||
|
||||
status = wlan_hdd_validate_context(pHddCtx);
|
||||
|
||||
if (hdd_is_roaming_in_progress()) {
|
||||
hdd_err("Roaming In Progress. Ignore!!!");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (0 != status)
|
||||
return status;
|
||||
|
||||
|
|
@ -16564,6 +16622,36 @@ void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_process_defer_disconnect() - Handle the deferred disconnect
|
||||
* @adapter: HDD Adapter
|
||||
*
|
||||
* If roaming is in progress and there is a request to
|
||||
* disconnect the session, then it is deferred. Once
|
||||
* roaming is complete/aborted, then this routine is
|
||||
* used to resume the disconnect that was deferred
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
|
||||
{
|
||||
switch (adapter->defer_disconnect) {
|
||||
case DEFER_DISCONNECT_CFG80211_DISCONNECT:
|
||||
adapter->defer_disconnect = 0;
|
||||
wlan_hdd_disconnect(adapter,
|
||||
adapter->cfg80211_disconnect_reason);
|
||||
break;
|
||||
case DEFER_DISCONNECT_TRY_DISCONNECT:
|
||||
wlan_hdd_try_disconnect(adapter);
|
||||
adapter->defer_disconnect = 0;
|
||||
break;
|
||||
default:
|
||||
hdd_info("Invalid source to defer:%d. Hence not handling it",
|
||||
adapter->defer_disconnect);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define CNT_DIFF(cur, prev) \
|
||||
((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
|
||||
#define MAX_COUNT 0xffffffff
|
||||
|
|
|
|||
|
|
@ -404,4 +404,18 @@ uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx);
|
|||
* Return: 0 for success, non-zero for failure
|
||||
*/
|
||||
int wlan_hdd_try_disconnect(hdd_adapter_t *adapter);
|
||||
|
||||
/**
|
||||
* hdd_process_defer_disconnect() - Handle the deferred disconnect
|
||||
* @adapter: HDD Adapter
|
||||
*
|
||||
* If roaming is in progress and there is a request to
|
||||
* disconnect the session, then it is deferred. Once
|
||||
* roaming is complete/aborted, then this routine is
|
||||
* used to resume the disconnect that was deferred
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void hdd_process_defer_disconnect(hdd_adapter_t *adapter);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10709,20 +10709,26 @@ void hdd_set_roaming_in_progress(bool value)
|
|||
|
||||
/**
|
||||
* hdd_is_roaming_in_progress() - check if roaming is in progress
|
||||
* @hdd_ctx - HDD context
|
||||
* @adapter - HDD adapter
|
||||
*
|
||||
* Return: true if roaming is in progress else false
|
||||
* Return: true if roaming is in progress for STA type, else false
|
||||
*/
|
||||
bool hdd_is_roaming_in_progress(void)
|
||||
bool hdd_is_roaming_in_progress(hdd_adapter_t *adapter)
|
||||
{
|
||||
hdd_context_t *hdd_ctx;
|
||||
bool ret_status = false;
|
||||
|
||||
hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
|
||||
if (!hdd_ctx) {
|
||||
hdd_err("HDD context is NULL");
|
||||
return false;
|
||||
return ret_status;
|
||||
}
|
||||
return hdd_ctx->roaming_in_progress;
|
||||
hdd_info("dev mode = %d, roaming_in_progress = %d",
|
||||
adapter->device_mode, hdd_ctx->roaming_in_progress);
|
||||
ret_status = ((adapter->device_mode == QDF_STA_MODE) &&
|
||||
hdd_ctx->roaming_in_progress);
|
||||
|
||||
return ret_status;
|
||||
}
|
||||
|
||||
/* Register the module init/exit functions */
|
||||
|
|
|
|||
|
|
@ -17745,19 +17745,6 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id,
|
|||
FL("Supplicant disabled driver roaming"));
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
|
||||
if (session->roam_synch_in_progress
|
||||
&& (ROAM_SCAN_OFFLOAD_STOP == command)) {
|
||||
/*
|
||||
* When roam synch is in progress for propagation, there is no
|
||||
* need to send down the STOP command since the firmware is not
|
||||
* expecting any WMI commands when the roam synch is in progress
|
||||
*/
|
||||
b_roam_scan_offload_started = false;
|
||||
sms_log(mac_ctx, LOG1, FL("Roam sync in progress"));
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
if (0 == csr_roam_is_roam_offload_scan_enabled(mac_ctx)) {
|
||||
sms_log(mac_ctx, LOGE, "isRoamOffloadScanEnabled not set");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
|
|
|||
Loading…
Reference in a new issue