qcacld-3.0: Serialize the command eSmeCommandDelStaSession
The command eSmeCommandDelStaSession issues vdev delete to firmware. As this command eSmeCommandDelStaSession is not serialized, this may issue delete vdev before the peers for the vdev are deleted, resulting in fw assert. Serialization should be brought in for this command, so that first eSmeCommandRoam command will do vdev_stop-->remove_peer-->vdev_down and then eSmeCommandDelStaSession will be processed which will send vdev delete. Post the command eSmeCommandDelStaSession to the serialization module and WMA_DEL_STA_SELF_REQ will be posted from the sme eSmeCommandDelStaSession handler. Change-Id: I60fcbf622b961162c647db3638b5e019c5231971 CRs-Fixed: 2270982
This commit is contained in:
parent
13f092aea5
commit
b37dad385f
@ -375,6 +375,8 @@ struct addstafor_sessioncmd {
|
||||
struct delstafor_sessionCmd {
|
||||
/* Session self mac addr */
|
||||
tSirMacAddr selfMacAddr;
|
||||
csr_session_close_cb session_close_cb;
|
||||
void *context;
|
||||
};
|
||||
|
||||
struct csr_neighbor_roamconfig {
|
||||
|
@ -216,6 +216,18 @@ void csr_roam_wm_status_change_complete(tpAniSirGlobal mac_ctx,
|
||||
uint8_t session_id);
|
||||
void csr_roam_process_wm_status_change_command(tpAniSirGlobal pMac,
|
||||
tSmeCmd *pCommand);
|
||||
/**
|
||||
* csr_process_del_sta_session_command() - Post WMA_DEL_STA_SELF_REQ to wma
|
||||
*
|
||||
* @mac_ctx: global mac context
|
||||
* @sme_command: received Delete Self station request command
|
||||
*
|
||||
* This API sends the WMA_DEL_STA_SELF_REQ msg to WMA.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE
|
||||
*/
|
||||
QDF_STATUS csr_process_del_sta_session_command(tpAniSirGlobal mac_ctx,
|
||||
tSmeCmd *sme_command);
|
||||
void csr_reinit_roam_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand);
|
||||
void csr_reinit_wm_status_change_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand);
|
||||
QDF_STATUS csr_roam_send_set_key_cmd(tpAniSirGlobal mac_ctx,
|
||||
|
@ -51,6 +51,7 @@ typedef enum eSmeCommandType {
|
||||
eSmeCsrCommandMask = 0x10000,
|
||||
eSmeCommandRoam,
|
||||
eSmeCommandWmStatusChange,
|
||||
e_sme_command_del_sta_session,
|
||||
#ifdef FEATURE_WLAN_TDLS
|
||||
/*
|
||||
* eSmeTdlsCommandMask = 0x80000,
|
||||
|
@ -371,6 +371,11 @@ static void dump_csr_command_info(tpAniSirGlobal pMac, tSmeCmd *pCmd)
|
||||
pCmd->u.wmStatusChangeCmd.Type);
|
||||
break;
|
||||
|
||||
case e_sme_command_del_sta_session:
|
||||
sme_debug("Issue del STA command for session:%d",
|
||||
pCmd->sessionId);
|
||||
break;
|
||||
|
||||
default:
|
||||
sme_debug("default: Unhandled command %d",
|
||||
pCmd->command);
|
||||
@ -500,6 +505,9 @@ QDF_STATUS sme_ser_handle_active_cmd(struct wlan_serialization_command *cmd)
|
||||
csr_roam_process_wm_status_change_command(mac_ctx,
|
||||
sme_cmd);
|
||||
break;
|
||||
case e_sme_command_del_sta_session:
|
||||
csr_process_del_sta_session_command(mac_ctx, sme_cmd);
|
||||
break;
|
||||
case eSmeCommandAddTs:
|
||||
case eSmeCommandDelTs:
|
||||
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
|
||||
|
@ -162,6 +162,7 @@ static uint8_t *sme_trace_get_command_string(uint32_t command)
|
||||
CASE_RETURN_STRING(eSmeCsrCommandMask);
|
||||
CASE_RETURN_STRING(eSmeCommandRoam);
|
||||
CASE_RETURN_STRING(eSmeCommandWmStatusChange);
|
||||
CASE_RETURN_STRING(e_sme_command_del_sta_session);
|
||||
#ifdef FEATURE_WLAN_TDLS
|
||||
CASE_RETURN_STRING(eSmeCommandTdlsSendMgmt);
|
||||
CASE_RETURN_STRING(eSmeCommandTdlsAddPeer);
|
||||
|
@ -13319,6 +13319,41 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
QDF_STATUS csr_process_del_sta_session_command(tpAniSirGlobal mac_ctx,
|
||||
tSmeCmd *sme_command)
|
||||
{
|
||||
struct del_sta_self_params *del_sta_self_req;
|
||||
struct scheduler_msg msg = {0};
|
||||
QDF_STATUS status;
|
||||
|
||||
del_sta_self_req = qdf_mem_malloc(sizeof(struct del_sta_self_params));
|
||||
if (NULL == del_sta_self_req) {
|
||||
sme_err(" mem alloc failed for tDelStaSelfParams");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
qdf_mem_copy(del_sta_self_req->self_mac_addr,
|
||||
sme_command->u.delStaSessionCmd.selfMacAddr,
|
||||
sizeof(tSirMacAddr));
|
||||
|
||||
del_sta_self_req->session_id = sme_command->sessionId;
|
||||
del_sta_self_req->sme_callback =
|
||||
sme_command->u.delStaSessionCmd.session_close_cb;
|
||||
del_sta_self_req->sme_ctx = sme_command->u.delStaSessionCmd.context;
|
||||
msg.type = WMA_DEL_STA_SELF_REQ;
|
||||
msg.reserved = 0;
|
||||
msg.bodyptr = del_sta_self_req;
|
||||
msg.bodyval = 0;
|
||||
|
||||
sme_debug("sending WMA_DEL_STA_SELF_REQ");
|
||||
status = wma_post_ctrl_msg(mac_ctx, &msg);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
sme_err("wma_post_ctrl_msg failed");
|
||||
qdf_mem_free(del_sta_self_req);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_compute_mode_and_band() - computes dot11mode
|
||||
@ -17262,56 +17297,29 @@ QDF_STATUS csr_process_del_sta_session_rsp(tpAniSirGlobal pMac, uint8_t *pMsg)
|
||||
|
||||
|
||||
static QDF_STATUS
|
||||
csr_issue_del_sta_for_session_req(tpAniSirGlobal pMac, uint32_t sessionId,
|
||||
tSirMacAddr sessionMacAddr,
|
||||
csr_issue_del_sta_for_session_req(tpAniSirGlobal mac_ctx, uint32_t session_id,
|
||||
tSirMacAddr session_mac_addr,
|
||||
csr_session_close_cb callback,
|
||||
void *pContext)
|
||||
void *context)
|
||||
{
|
||||
struct del_sta_self_params *del_sta_self_req;
|
||||
struct scheduler_msg msg = {0};
|
||||
tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
|
||||
QDF_STATUS status;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
tSmeCmd *sme_command;
|
||||
|
||||
if (!wma_handle) {
|
||||
sme_err("wma handle is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
sme_command = csr_get_command_buffer(mac_ctx);
|
||||
if (NULL == sme_command) {
|
||||
status = QDF_STATUS_E_RESOURCES;
|
||||
} else {
|
||||
sme_command->command = e_sme_command_del_sta_session;
|
||||
sme_command->sessionId = (uint8_t)session_id;
|
||||
sme_command->u.delStaSessionCmd.session_close_cb = callback;
|
||||
sme_command->u.delStaSessionCmd.context = context;
|
||||
qdf_mem_copy(sme_command->u.delStaSessionCmd.selfMacAddr,
|
||||
session_mac_addr, sizeof(tSirMacAddr));
|
||||
status = csr_queue_sme_command(mac_ctx, sme_command, true);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status))
|
||||
sme_err("fail to send message status = %d", status);
|
||||
}
|
||||
|
||||
/* Need to wait for all peer delete command sent to FW
|
||||
* before sending VDEV delete command
|
||||
* otherwise it will cause FW assert
|
||||
* Need to do this before sending to scheduler queue
|
||||
* otherwise the scheduler thread will be blocked
|
||||
* and fail to handle the VDEV stop timeout callback
|
||||
* in which peer delete command will also be sent
|
||||
*/
|
||||
wma_vdev_wait_for_peer_delete_completion(wma_handle, sessionId);
|
||||
|
||||
del_sta_self_req = qdf_mem_malloc(sizeof(struct del_sta_self_params));
|
||||
if (NULL == del_sta_self_req) {
|
||||
sme_err(" mem alloc failed for tDelStaSelfParams");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
qdf_mem_copy(del_sta_self_req->self_mac_addr,
|
||||
sessionMacAddr, sizeof(tSirMacAddr));
|
||||
|
||||
del_sta_self_req->session_id = sessionId;
|
||||
del_sta_self_req->sme_callback = callback;
|
||||
del_sta_self_req->sme_ctx = pContext;
|
||||
msg.type = WMA_DEL_STA_SELF_REQ;
|
||||
msg.reserved = 0;
|
||||
msg.bodyptr = del_sta_self_req;
|
||||
msg.bodyval = 0;
|
||||
|
||||
sme_debug("sending WMA_DEL_STA_SELF_REQ");
|
||||
status = wma_post_ctrl_msg(pMac, &msg);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
sme_err("wma_post_ctrl_msg failed");
|
||||
qdf_mem_free(del_sta_self_req);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
void csr_cleanup_session(tpAniSirGlobal pMac, uint32_t sessionId)
|
||||
@ -20247,6 +20255,9 @@ enum wlan_serialization_cmd_type csr_get_cmd_type(tSmeCmd *sme_cmd)
|
||||
case eSmeCommandWmStatusChange:
|
||||
cmd_type = WLAN_SER_CMD_WM_STATUS_CHANGE;
|
||||
break;
|
||||
case e_sme_command_del_sta_session:
|
||||
cmd_type = WLAN_SER_CMD_DEL_STA_SESSION;
|
||||
break;
|
||||
case eSmeCommandAddTs:
|
||||
cmd_type = WLAN_SER_CMD_ADDTS;
|
||||
break;
|
||||
|
@ -1092,8 +1092,6 @@ struct wma_txrx_node {
|
||||
uint32_t nwType;
|
||||
void *staKeyParams;
|
||||
uint32_t peer_count;
|
||||
qdf_atomic_t fw_peer_count;
|
||||
qdf_event_t fw_peer_delete_completion;
|
||||
bool roam_synch_in_progress;
|
||||
void *plink_status_req;
|
||||
void *psnr_req;
|
||||
|
@ -587,7 +587,6 @@ static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle,
|
||||
goto out;
|
||||
}
|
||||
|
||||
QDF_BUG(qdf_atomic_read(&iface->fw_peer_count) == 0);
|
||||
|
||||
status = wmi_unified_vdev_delete_send(wma_handle->wmi_handle, vdev_id);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
@ -595,8 +594,6 @@ static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle,
|
||||
goto out;
|
||||
}
|
||||
|
||||
qdf_event_destroy(&iface->fw_peer_delete_completion);
|
||||
|
||||
WMA_LOGD("vdev_id:%hu vdev_hdl:%pK", vdev_id, iface->handle);
|
||||
if (!generate_rsp) {
|
||||
WMA_LOGE("Call txrx detach w/o callback for vdev %d", vdev_id);
|
||||
@ -701,60 +698,10 @@ static void wma_force_vdev_cleanup(tp_wma_handle wma_handle, uint8_t vdev_id)
|
||||
wma_peer_remove_for_vdev_callback,
|
||||
wma_handle);
|
||||
|
||||
qdf_atomic_init(&iface->fw_peer_count);
|
||||
qdf_event_destroy(&iface->fw_peer_delete_completion);
|
||||
|
||||
VDEV_DETACH:
|
||||
wma_cdp_vdev_detach(soc, wma_handle, vdev_id);
|
||||
}
|
||||
|
||||
#define WMA_WAIT_PEER_DELETE_COMPLETION_TIMEOUT (WMA_VDEV_STOP_REQUEST_TIMEOUT+ 1000)
|
||||
|
||||
/**
|
||||
* wma_vdev_wait_for_peer_delete_completion(): wait for all peers of the vdev
|
||||
* to be deleted except vdev type is P2P device.
|
||||
* @wma_handle: wma handle
|
||||
* @vdev_id: vdev id
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void wma_vdev_wait_for_peer_delete_completion(tp_wma_handle wma_handle,
|
||||
uint8_t vdev_id)
|
||||
{
|
||||
struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id];
|
||||
|
||||
/* Do NOT wait when SSR is in progress
|
||||
* since all WMI commands will be ignored and not sent to FW
|
||||
*/
|
||||
if (cds_is_driver_recovering()) {
|
||||
WMA_LOGD("%s: SSR is in progress", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!iface || !iface->vdev_active) {
|
||||
WMA_LOGE("%s: iface of vdev-%d is not available",
|
||||
__func__, vdev_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For P2P Device, firstly it will delete the last peer in
|
||||
* wma vdev detach, so not wait before deliver
|
||||
* WMA_DEL_STA_SELF_REQ. Secondly, no throughput case run on
|
||||
* P2P device, and no need to take care the case which no
|
||||
* vdev stop response from FW.
|
||||
*/
|
||||
if (((iface->type == WMI_VDEV_TYPE_AP) &&
|
||||
(iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) ||
|
||||
(cds_is_fw_down())) {
|
||||
WMA_LOGD("%s: type %d P2P devices or firmware is down, do not wait",
|
||||
__func__, iface->type);
|
||||
return;
|
||||
}
|
||||
|
||||
qdf_wait_for_event_completion(&iface->fw_peer_delete_completion,
|
||||
WMA_WAIT_PEER_DELETE_COMPLETION_TIMEOUT);
|
||||
}
|
||||
|
||||
static bool wma_vdev_uses_self_peer(uint32_t vdev_type, uint32_t vdev_subtype)
|
||||
{
|
||||
switch (vdev_type) {
|
||||
@ -1518,12 +1465,6 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
|
||||
__func__, qdf_status);
|
||||
/* Clear default bit and set to NOT_START_UNMAP */
|
||||
bitmap = 1 << CDP_PEER_DO_NOT_START_UNMAP_TIMER;
|
||||
} else {
|
||||
qdf_atomic_dec(&wma->interfaces[vdev_id].fw_peer_count);
|
||||
WMA_LOGD("%s: vdev-%d fw_peer_count %d", __func__, vdev_id,
|
||||
qdf_atomic_read(&wma->interfaces[vdev_id].fw_peer_count));
|
||||
if (qdf_atomic_read(&wma->interfaces[vdev_id].fw_peer_count) == 0)
|
||||
qdf_event_set(&wma->interfaces[vdev_id].fw_peer_delete_completion);
|
||||
}
|
||||
|
||||
peer_detach:
|
||||
@ -1784,11 +1725,6 @@ QDF_STATUS wma_create_peer(tp_wma_handle wma, struct cdp_pdev *pdev,
|
||||
1 << CDP_PEER_DO_NOT_START_UNMAP_TIMER);
|
||||
wlan_objmgr_peer_obj_delete(obj_peer);
|
||||
goto err;
|
||||
} else {
|
||||
qdf_atomic_inc(&wma->interfaces[vdev_id].fw_peer_count);
|
||||
WMA_LOGD("%s: vdev-%d fw_peer_count %d", __func__, vdev_id,
|
||||
qdf_atomic_read(&wma->interfaces[vdev_id].fw_peer_count));
|
||||
qdf_event_reset(&wma->interfaces[vdev_id].fw_peer_delete_completion);
|
||||
}
|
||||
|
||||
WMA_LOGD("%s: Created peer %pK with peer_addr %pM vdev_id %d, peer_count - %d",
|
||||
@ -2519,15 +2455,6 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
|
||||
self_sta_req->sub_type;
|
||||
qdf_atomic_init(&wma_handle->interfaces
|
||||
[self_sta_req->session_id].bss_status);
|
||||
qdf_atomic_init(&wma_handle->interfaces
|
||||
[self_sta_req->session_id].fw_peer_count);
|
||||
status = qdf_event_create(&wma_handle->interfaces
|
||||
[self_sta_req->session_id].fw_peer_delete_completion);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
WMA_LOGE("%s: Failed to create fw_peer_delete_completion", __func__);
|
||||
goto end;
|
||||
}
|
||||
qdf_event_set(&wma_handle->interfaces[vdev_id].fw_peer_delete_completion);
|
||||
|
||||
if (wma_vdev_uses_self_peer(self_sta_req->type,
|
||||
self_sta_req->sub_type)) {
|
||||
@ -5710,10 +5637,6 @@ void wma_delete_bss_ho_fail(tp_wma_handle wma, tpDeleteBssParams params)
|
||||
}
|
||||
iface->peer_count--;
|
||||
|
||||
WMA_LOGD("%s: Reset FW peer count", __func__);
|
||||
qdf_atomic_init(&iface->fw_peer_count);
|
||||
qdf_event_set(&iface->fw_peer_delete_completion);
|
||||
|
||||
WMA_LOGI("%s: Removed peer %pK with peer_addr %pM vdevid %d peer_count %d",
|
||||
__func__, peer, params->bssid, params->smesessionId,
|
||||
iface->peer_count);
|
||||
|
Loading…
Reference in New Issue
Block a user