qcacld-3.0: Do not send WMI commands in ROAM_HO_FAIL handling

When firmware sends WMI_ROAM_REASON_HO_FAILED event to host,
it has already deleted the peer. Host should not send peer
and vdev cleanup commands to firmware.

Add disassoc_reason field to roamCmd to indicate that CSR wants to
disconnect because of ROAM_HO_FAIL. Copy that information to PE
session, send it to WMA using WMA_DELETE_BSS_HO_FAIL_REQ.
Add wma_delete_bss_ho_fail() to take care of driver state cleanup
without sending commands to firmware.

CRs-Fixed: 1083649
Change-Id: Icdd7571214ea5510c0cdbc44c69d6b5060f5892c
This commit is contained in:
Deepak Dhamdhere 2016-10-27 10:58:29 -07:00 • committed by Prakash Dhavali
commit 2dae1bd94d
16 changed files with 171 additions and 20 deletions

View file

@ -402,7 +402,7 @@ static inline void ol_txrx_peer_find_add_id(struct ol_txrx_pdev_t *pdev,
qdf_spin_unlock(&pdev->peer_map_unmap_lock);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: peer %p ID %d peer_id[%d] peer_id_ref_cnt %d peer->ref_cnt %d",
__func__, peer, peer_id, i,
qdf_atomic_read(&pdev->

View file

@ -1390,6 +1390,7 @@ typedef struct sSirSmeDisassocReq {
/* This flag tells LIM whether to send the disassoc OTA or not */
/* This will be set in while handing off from one AP to other */
uint8_t doNotSendOverTheAir;
bool process_ho_fail;
} qdf_packed tSirSmeDisassocReq, *tpSirSmeDisassocReq;
/* / Definition for Tkip countermeasures request */

View file

@ -253,9 +253,11 @@ typedef struct sSirMbMsgP2p {
#define SIR_HAL_TIMER_ADJUST_ADAPTIVE_THRESHOLD_IND \
(SIR_HAL_ITC_MSG_TYPES_BEGIN + 44)
#define SIR_HAL_SET_LINK_STATE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 45)
#define SIR_HAL_DELETE_BSS_HO_FAIL_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 46)
#define SIR_HAL_DELETE_BSS_HO_FAIL_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 47)
/*
* (SIR_HAL_ITC_MSG_TYPES_BEGIN + 46) to
* (SIR_HAL_ITC_MSG_TYPES_BEGIN + 48) to
* (SIR_HAL_ITC_MSG_TYPES_BEGIN + 57) are unused
*/

View file

@ -485,6 +485,7 @@ typedef struct sPESession /* Added to Support BT-AMP */
uint8_t *access_policy_vendor_ie;
uint8_t access_policy;
bool ignore_assoc_disallowed;
bool process_ho_fail;
} tPESession, *tpPESession;
/*-------------------------------------------------------------------------

View file

@ -3396,7 +3396,12 @@ lim_del_bss(tpAniSirGlobal pMac, tpDphHashNode pStaDs, uint16_t bssIdx,
/* we need to defer the message until we get the response back from HAL. */
SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
msgQ.type = WMA_DELETE_BSS_REQ;
lim_log(pMac, LOGW, FL("process_ho_fail = %d"),
psessionEntry->process_ho_fail);
if (psessionEntry->process_ho_fail)
msgQ.type = WMA_DELETE_BSS_HO_FAIL_REQ;
else
msgQ.type = WMA_DELETE_BSS_REQ;
msgQ.reserved = 0;
msgQ.bodyptr = pDelBssParams;
msgQ.bodyval = 0;

View file

@ -446,6 +446,7 @@ uint8_t static def_msg_decision(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
&& !pMac->lim.gLimSystemInScanLearnMode) {
if ((limMsg->type != WMA_ADD_BSS_RSP)
&& (limMsg->type != WMA_DELETE_BSS_RSP)
&& (limMsg->type != WMA_DELETE_BSS_HO_FAIL_RSP)
&& (limMsg->type != WMA_ADD_STA_RSP)
&& (limMsg->type != WMA_DELETE_STA_RSP)
&& (limMsg->type != WMA_SET_BSSKEY_RSP)
@ -1763,6 +1764,7 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
lim_process_mlm_del_sta_rsp(mac_ctx, msg);
break;
case WMA_DELETE_BSS_RSP:
case WMA_DELETE_BSS_HO_FAIL_RSP:
lim_handle_delete_bss_rsp(mac_ctx, msg);
break;
case WMA_CSA_OFFLOAD_EVENT:

View file

@ -2450,6 +2450,8 @@ static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBu
psessionEntry->smeSessionId = smesessionId;
psessionEntry->transactionId = smetransactionId;
lim_log(pMac, LOGW, FL("ho_fail: %d "), smeDisassocReq.process_ho_fail);
psessionEntry->process_ho_fail = smeDisassocReq.process_ho_fail;
switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
case eLIM_STA_ROLE:

View file

@ -2284,6 +2284,13 @@ void lim_handle_delete_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ MsgQ)
qdf_mem_free(MsgQ->bodyptr);
return;
}
/*
* During DEL BSS handling, the PE Session will be deleted, but it is
* better to clear this flag if the session is hanging around due
* to some error conditions so that the next DEL_BSS request does
* not take the HO_FAIL path
*/
psessionEntry->process_ho_fail = false;
if (LIM_IS_IBSS_ROLE(psessionEntry))
lim_ibss_del_bss_rsp(pMac, MsgQ->bodyptr, psessionEntry);
else if (LIM_IS_UNKNOWN_ROLE(psessionEntry))

View file

@ -394,7 +394,9 @@ uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg)
CASE_RETURN_STRING(WMA_ADD_BSS_REQ);
CASE_RETURN_STRING(WMA_ADD_BSS_RSP);
CASE_RETURN_STRING(WMA_DELETE_BSS_REQ);
CASE_RETURN_STRING(WMA_DELETE_BSS_HO_FAIL_REQ);
CASE_RETURN_STRING(WMA_DELETE_BSS_RSP);
CASE_RETURN_STRING(WMA_DELETE_BSS_HO_FAIL_RSP);
CASE_RETURN_STRING(WMA_SEND_BEACON_REQ);
CASE_RETURN_STRING(WMA_SET_BSSKEY_REQ);
CASE_RETURN_STRING(WMA_SET_BSSKEY_RSP);

View file

@ -649,6 +649,7 @@ typedef enum {
eCSR_DISCONNECT_REASON_IBSS_LEAVE,
eCSR_DISCONNECT_REASON_STA_HAS_LEFT,
eCSR_DISCONNECT_REASON_NDI_DELETE,
eCSR_DISCONNECT_REASON_ROAM_HO_FAIL,
} eCsrRoamDisconnectReason;
typedef enum {

View file

@ -406,6 +406,7 @@ typedef struct tagRoamCmd {
bool fStopWds;
tSirMacAddr peerMac;
tSirMacReasonCodes reason;
eCsrRoamDisconnectReason disconnect_reason;
} tRoamCmd;
typedef struct tagSetKeyCmd {
@ -1000,6 +1001,7 @@ typedef struct tagCsrRoamSession {
bool supported_nss_1x1;
bool disable_hi_rssi;
bool dhcp_done;
uint8_t disconnect_reason;
} tCsrRoamSession;
typedef struct tagCsrRoamStruct {

View file

@ -5670,6 +5670,8 @@ QDF_STATUS csr_roam_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand)
sms_log(pMac, LOG1, FL("Roam Reason : %d, sessionId: %d"),
pCommand->u.roamCmd.roamReason, sessionId);
pSession->disconnect_reason = pCommand->u.roamCmd.disconnect_reason;
switch (pCommand->u.roamCmd.roamReason) {
case eCsrForcedDisassoc:
if (eCSR_ROAMING_STATE_IDLE == pMac->roam.curState[sessionId]) {
@ -5678,7 +5680,6 @@ QDF_STATUS csr_roam_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand)
" %d"), eCSR_ROAMING_STATE_IDLE);
return QDF_STATUS_E_FAILURE;
}
status = csr_roam_process_disassoc_deauth(pMac, pCommand,
true, false);
csr_free_roam_profile(pMac, sessionId);
@ -8218,6 +8219,9 @@ QDF_STATUS csr_roam_issue_disassociate_cmd(tpAniSirGlobal pMac, uint32_t session
case eCSR_DISCONNECT_REASON_DISASSOC:
pCommand->u.roamCmd.roamReason = eCsrForcedDisassoc;
break;
case eCSR_DISCONNECT_REASON_ROAM_HO_FAIL:
pCommand->u.roamCmd.roamReason = eCsrForcedDisassoc;
break;
case eCSR_DISCONNECT_REASON_IBSS_JOIN_FAILURE:
pCommand->u.roamCmd.roamReason =
eCsrSmeIssuedIbssJoinFailure;
@ -8239,6 +8243,7 @@ QDF_STATUS csr_roam_issue_disassociate_cmd(tpAniSirGlobal pMac, uint32_t session
default:
break;
}
pCommand->u.roamCmd.disconnect_reason = reason;
status = csr_queue_sme_command(pMac, pCommand, true);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
@ -14561,6 +14566,8 @@ QDF_STATUS csr_send_mb_disassoc_req_msg(tpAniSirGlobal pMac, uint32_t sessionId,
bssId, QDF_MAC_ADDR_SIZE);
}
pMsg->reasonCode = reasonCode;
pMsg->process_ho_fail = (pSession->disconnect_reason ==
eCSR_DISCONNECT_REASON_ROAM_HO_FAIL) ? true : false;
/*
* The state will be DISASSOC_HANDOFF only when we are doing
* handoff. Here we should not send the disassoc over the air
@ -18877,7 +18884,8 @@ void csr_process_ho_fail_ind(tpAniSirGlobal pMac, void *pMsgBuf)
eCSR_REASON_ROAM_HO_FAIL);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"LFR3:Issue Disconnect on session %d", sessionId);
csr_roam_disconnect(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
csr_roam_disconnect(pMac, sessionId,
eCSR_DISCONNECT_REASON_ROAM_HO_FAIL);
}
#endif /* WLAN_FEATURE_ROAM_OFFLOAD */

View file

@ -597,6 +597,8 @@ int32_t wma_find_vdev_by_type(tp_wma_handle wma, int32_t type);
void wma_set_vdev_intrabss_fwd(tp_wma_handle wma_handle,
tpDisableIntraBssFwd pdis_intra_fwd);
void wma_delete_bss_ho_fail(tp_wma_handle wma, tpDeleteBssParams params);
/*
* wma_mgmt.c functions declarations
*/

View file

@ -145,7 +145,9 @@
#define WMA_ADD_BSS_REQ SIR_HAL_ADD_BSS_REQ
#define WMA_ADD_BSS_RSP SIR_HAL_ADD_BSS_RSP
#define WMA_DELETE_BSS_REQ SIR_HAL_DELETE_BSS_REQ
#define WMA_DELETE_BSS_HO_FAIL_REQ SIR_HAL_DELETE_BSS_HO_FAIL_REQ
#define WMA_DELETE_BSS_RSP SIR_HAL_DELETE_BSS_RSP
#define WMA_DELETE_BSS_HO_FAIL_RSP SIR_HAL_DELETE_BSS_HO_FAIL_RSP
#define WMA_SEND_BEACON_REQ SIR_HAL_SEND_BEACON_REQ
#define WMA_SEND_PROBE_RSP_TMPL SIR_HAL_SEND_PROBE_RSP_TMPL

View file

@ -1053,7 +1053,7 @@ QDF_STATUS wma_set_peer_param(void *wma_ctx, uint8_t *peer_addr,
}
/**
* wma_remove_peer() - send remove peer command to fw
* wma_remove_peer() - remove peer information from host driver and fw
* @wma: wma handle
* @bssid: mac address
* @vdev_id: vdev id
@ -1104,7 +1104,7 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
param.peer_tid_bitmap = peer_tid_bitmap;
param.vdev_id = vdev_id;
wmi_unified_peer_flush_tids_send(wma->wmi_handle, bssid,
&param);
&param);
if (wma_is_vdev_in_ibss_mode(wma, vdev_id)) {
WMA_LOGD("%s: bssid %pM peer->mac_addr %pM", __func__,
@ -1112,7 +1112,8 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
peer_addr = peer_mac_addr;
}
wmi_unified_peer_delete_send(wma->wmi_handle, peer_addr, vdev_id);
wmi_unified_peer_delete_send(wma->wmi_handle, peer_addr,
vdev_id);
#undef PEER_ALL_TID_BITMASK
}
@ -4225,6 +4226,109 @@ void wma_delete_sta(tp_wma_handle wma, tpDeleteStaParams del_sta)
#endif
}
/**
* wma_delete_bss_ho_fail() - process delete bss request for handoff failure
* @wma: wma handle
* @params: del bss parameters
*
* Delete BSS in case of ROAM_HO_FAIL processing is handled separately in
* this routine. It needs to be done without sending any commands to firmware
* because firmware has already stopped and deleted peer and vdev is down.
* Relevent logic is aggregated from other routines. It changes the host
* data structures without sending VDEV_STOP, PEER_FLUSH_TIDS, PEER_DELETE
* and VDEV_DOWN commands to firmware.
*
* Return: none
*/
void wma_delete_bss_ho_fail(tp_wma_handle wma, tpDeleteBssParams params)
{
ol_txrx_pdev_handle pdev;
ol_txrx_peer_handle peer = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t peer_id;
ol_txrx_vdev_handle txrx_vdev = NULL;
struct wma_txrx_node *iface;
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
if (NULL == pdev) {
WMA_LOGE("%s:Unable to get TXRX context", __func__);
goto fail_del_bss_ho_fail;
}
peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, &peer_id);
if (!peer) {
WMA_LOGP("%s: Failed to find peer %pM", __func__,
params->bssid);
status = QDF_STATUS_E_FAILURE;
goto fail_del_bss_ho_fail;
}
iface = &wma->interfaces[params->smesessionId];
if (!iface || !iface->handle) {
WMA_LOGE("%s vdev id %d is already deleted",
__func__, params->smesessionId);
goto fail_del_bss_ho_fail;
}
qdf_mem_zero(iface->bssid, IEEE80211_ADDR_LEN);
txrx_vdev = wma_find_vdev_by_id(wma, params->smesessionId);
if (!txrx_vdev) {
WMA_LOGE("%s:Invalid vdev handle", __func__);
status = QDF_STATUS_E_FAILURE;
goto fail_del_bss_ho_fail;
}
/* Free the allocated stats response buffer for the the session */
if (iface->stats_rsp) {
qdf_mem_free(iface->stats_rsp);
iface->stats_rsp = NULL;
}
if (iface->psnr_req) {
qdf_mem_free(iface->psnr_req);
iface->psnr_req = NULL;
}
qdf_mem_zero(&iface->ns_offload_req,
sizeof(iface->ns_offload_req));
qdf_mem_zero(&iface->arp_offload_req,
sizeof(iface->arp_offload_req));
WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP (del_bss)",
__func__, params->smesessionId);
ol_txrx_vdev_pause(iface->handle,
OL_TXQ_PAUSE_REASON_VDEV_STOP);
iface->pause_bitmap |= (1 << PAUSE_TYPE_HOST);
ol_txrx_vdev_flush(iface->handle);
WMA_LOGD("%s, vdev_id: %d, un-pausing tx_ll_queue for VDEV_STOP rsp",
__func__, params->smesessionId);
ol_txrx_vdev_unpause(iface->handle,
OL_TXQ_PAUSE_REASON_VDEV_STOP);
iface->pause_bitmap &= ~(1 << PAUSE_TYPE_HOST);
qdf_atomic_set(&iface->bss_status, WMA_BSS_STATUS_STOPPED);
WMA_LOGD("%s: (type %d subtype %d) BSS is stopped",
__func__, iface->type, iface->sub_type);
iface->vdev_up = false;
params->status = QDF_STATUS_SUCCESS;
if (!iface->peer_count) {
WMA_LOGE("%s: Can't remove peer with peer_addr %pM vdevid %d peer_count %d",
__func__, params->bssid, params->smesessionId,
iface->peer_count);
goto fail_del_bss_ho_fail;
}
if (peer)
ol_txrx_peer_detach(peer);
iface->peer_count--;
WMA_LOGE("%s: Removed peer %p with peer_addr %pM vdevid %d peer_count %d",
__func__, peer, params->bssid, params->smesessionId,
iface->peer_count);
fail_del_bss_ho_fail:
params->status = status;
wma_send_msg(wma, WMA_DELETE_BSS_HO_FAIL_RSP, (void *)params, 0);
}
/**
* wma_delete_bss() - process delete bss request from upper layer
* @wma: wma handle
@ -4242,6 +4346,7 @@ void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params)
uint8_t max_wait_iterations = 0;
ol_txrx_vdev_handle txrx_vdev = NULL;
bool roam_synch_in_progress = false;
struct wma_txrx_node *iface;
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
@ -4280,15 +4385,21 @@ void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params)
goto out;
}
iface = &wma->interfaces[params->smesessionId];
if (!iface || !iface->handle) {
WMA_LOGE("%s vdev id %d is already deleted",
__func__, params->smesessionId);
goto out;
}
/*Free the allocated stats response buffer for the the session */
if (wma->interfaces[params->smesessionId].stats_rsp) {
qdf_mem_free(wma->interfaces[params->smesessionId].stats_rsp);
wma->interfaces[params->smesessionId].stats_rsp = NULL;
if (iface->stats_rsp) {
qdf_mem_free(iface->stats_rsp);
iface->stats_rsp = NULL;
}
if (wma->interfaces[params->smesessionId].psnr_req) {
qdf_mem_free(wma->interfaces[params->smesessionId].psnr_req);
wma->interfaces[params->smesessionId].psnr_req = NULL;
if (iface->psnr_req) {
qdf_mem_free(iface->psnr_req);
iface->psnr_req = NULL;
}
if (wlan_op_mode_ibss == ol_txrx_get_opmode(txrx_vdev))
@ -4298,7 +4409,7 @@ void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params)
roam_synch_in_progress = true;
WMA_LOGD("LFR3:%s: Setting vdev_up to FALSE for session %d",
__func__, params->smesessionId);
wma->interfaces[params->smesessionId].vdev_up = false;
iface->vdev_up = false;
goto detach_peer;
}
msg = wma_fill_vdev_req(wma, params->smesessionId, WMA_DELETE_BSS_REQ,
@ -4332,18 +4443,17 @@ void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params)
WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP (del_bss)",
__func__, params->smesessionId);
ol_txrx_vdev_pause(wma->interfaces[params->smesessionId].handle,
ol_txrx_vdev_pause(iface->handle,
OL_TXQ_PAUSE_REASON_VDEV_STOP);
wma->interfaces[params->smesessionId].pause_bitmap |=
(1 << PAUSE_TYPE_HOST);
iface->pause_bitmap |= (1 << PAUSE_TYPE_HOST);
if (wmi_unified_vdev_stop_send(wma->wmi_handle, params->smesessionId)) {
WMA_LOGP("%s: %d Failed to send vdev stop", __func__, __LINE__);
wma_remove_vdev_req(wma, params->smesessionId,
WMA_TARGET_REQ_TYPE_VDEV_STOP);
WMA_TARGET_REQ_TYPE_VDEV_STOP);
status = QDF_STATUS_E_FAILURE;
goto detach_peer;
}
}
WMA_LOGD("%s: bssid %pM vdev_id %d",
__func__, params->bssid, params->smesessionId);
return;

View file

@ -6198,6 +6198,10 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg)
case WMA_DELETE_STA_REQ:
wma_delete_sta(wma_handle, (tpDeleteStaParams) msg->bodyptr);
break;
case WMA_DELETE_BSS_HO_FAIL_REQ:
wma_delete_bss_ho_fail(wma_handle,
(tpDeleteBssParams) msg->bodyptr);
break;
case WMA_DELETE_BSS_REQ:
wma_delete_bss(wma_handle, (tpDeleteBssParams) msg->bodyptr);
break;