mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 21:59:12 -04:00
qcacld-3.0: Fix race condition between connect and disconnect
Scenario: In case of STA + STA, NB/SB issues disconnection for vdev 0 when vdev 1 is in connecting state. As connection is blocking serialization command and it can try multiple candidates and can take upto 30+ sec, there is a chance that disconnect may get timeout and is followed by vdev delete from osif. This can lead to vdev delete sent without vdev down/stop and bss peer delete for vdev 0. So abort connection when trying for candidate if any of the vdev is waiting for disconnect, to avoid disconnect timeout. Change-Id: I876550532524767e811c9fd03e85e16d6a90b940 CRs-Fixed: 3049934
This commit is contained in:
parent
a3e3461b48
commit
2033fd4633
2 changed files with 55 additions and 2 deletions
|
|
@ -8471,6 +8471,11 @@ QDF_STATUS csr_roam_disconnect(struct mac_context *mac_ctx, uint32_t session_id,
|
|||
|| CSR_IS_CONN_NDI(&session->connectedProfile)) {
|
||||
status = csr_roam_issue_disassociate_cmd(mac_ctx, session_id,
|
||||
reason, mac_reason);
|
||||
} else if (csr_is_deauth_disassoc_already_active(mac_ctx, session_id,
|
||||
session->connectedProfile.bssid)) {
|
||||
/* Return success if Disconnect is already in progress */
|
||||
sme_debug("Disconnect already in queue return success");
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
} else if (session->scan_info.profile) {
|
||||
mac_ctx->roam.roamSession[session_id].connectState =
|
||||
eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING;
|
||||
|
|
@ -8670,6 +8675,37 @@ bool is_disconnect_pending(struct mac_context *pmac, uint8_t vdev_id)
|
|||
return disconnect_cmd_exist;
|
||||
}
|
||||
|
||||
bool is_disconnect_pending_on_other_vdev(struct mac_context *pmac,
|
||||
uint8_t vdev_id)
|
||||
{
|
||||
tListElem *entry = NULL;
|
||||
tListElem *next_entry = NULL;
|
||||
tSmeCmd *command = NULL;
|
||||
bool disconnect_cmd_exist = false;
|
||||
|
||||
entry = csr_nonscan_pending_ll_peek_head(pmac, LL_ACCESS_NOLOCK);
|
||||
while (entry) {
|
||||
next_entry = csr_nonscan_pending_ll_next(pmac, entry,
|
||||
LL_ACCESS_NOLOCK);
|
||||
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
|
||||
/*
|
||||
* check if any other vdev NB disconnect or SB disconnect
|
||||
* (eSmeCommandWmStatusChange) is pending
|
||||
*/
|
||||
if (command && (CSR_IS_DISCONNECT_COMMAND(command) ||
|
||||
command->command == eSmeCommandWmStatusChange) &&
|
||||
command->vdev_id != vdev_id) {
|
||||
sme_debug("disconnect is pending on vdev:%d, cmd:%d",
|
||||
command->vdev_id, command->command);
|
||||
disconnect_cmd_exist = true;
|
||||
break;
|
||||
}
|
||||
entry = next_entry;
|
||||
}
|
||||
|
||||
return disconnect_cmd_exist;
|
||||
}
|
||||
|
||||
#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
|
||||
static void
|
||||
csr_clear_other_bss_sae_single_pmk_entry(struct mac_context *mac,
|
||||
|
|
@ -8789,7 +8825,7 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac,
|
|||
struct csr_roam_connectedinfo *prev_connect_info;
|
||||
struct wlan_crypto_pmksa *pmksa;
|
||||
uint32_t len = 0, roamId = 0, reason_code = 0;
|
||||
bool is_dis_pending;
|
||||
bool is_dis_pending, is_dis_pending_on_other_vdev;
|
||||
bool use_same_bss = false;
|
||||
uint8_t max_retry_count = 1;
|
||||
bool retry_same_bss = false;
|
||||
|
|
@ -8893,6 +8929,9 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac,
|
|||
reason_code);
|
||||
|
||||
is_dis_pending = is_disconnect_pending(mac, session_ptr->sessionId);
|
||||
is_dis_pending_on_other_vdev =
|
||||
is_disconnect_pending_on_other_vdev(mac,
|
||||
session_ptr->sessionId);
|
||||
is_time_allowed =
|
||||
csr_is_time_allowed_for_connect_attempt(pCommand,
|
||||
session_ptr->vdev_id);
|
||||
|
|
@ -8901,7 +8940,7 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac,
|
|||
* if userspace has issued disconnection or we have reached mac tries or
|
||||
* max time, driver should not continue for next connection.
|
||||
*/
|
||||
if (is_dis_pending || !is_time_allowed ||
|
||||
if (is_dis_pending || is_dis_pending_on_other_vdev || !is_time_allowed ||
|
||||
session_ptr->join_bssid_count >= CSR_MAX_BSSID_COUNT)
|
||||
attempt_next_bss = false;
|
||||
|
||||
|
|
@ -9017,6 +9056,9 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac,
|
|||
if (is_dis_pending)
|
||||
sme_err("disconnect is pending, complete roam");
|
||||
|
||||
if (is_dis_pending_on_other_vdev)
|
||||
sme_err("disconnect is pending on other vdev, complete roam");
|
||||
|
||||
if (!is_time_allowed)
|
||||
sme_err("time can exceed the active timeout for connection attempt");
|
||||
|
||||
|
|
|
|||
|
|
@ -974,6 +974,17 @@ csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle,
|
|||
bool is_disconnect_pending(struct mac_context *mac_ctx,
|
||||
uint8_t sessionid);
|
||||
|
||||
/**
|
||||
* is_disconnect_pending_on_other_vdev() - To check whether a disconnect req
|
||||
* is pending on any other vdev or not
|
||||
* @mac_tx: mac context
|
||||
* @sessionid: session id
|
||||
*
|
||||
* Return true if disconnect is pending on any other vdev
|
||||
*/
|
||||
bool is_disconnect_pending_on_other_vdev(struct mac_context *mac_ctx,
|
||||
uint8_t sessionid);
|
||||
|
||||
QDF_STATUS
|
||||
csr_roam_prepare_bss_config_from_profile(struct mac_context *mac_ctx,
|
||||
struct csr_roam_profile *profile,
|
||||
|
|
|
|||
Loading…
Reference in a new issue