qcacld-3.0: Fix error handling in eWNI_SME_ADD_STA_SELF_RSP

When peer creation fails in wma_create_peer, vdev delete is sent
to the fw and then eWNI_SME_ADD_STA_SELF_RSP is sent to sme.
Here three error cases needs to be handled:
1. The vdev deletion has happened, but the cdp_detach_peer is
not done. So the data path peer remains. Also the vdev_active
flag that was set after vdev creation was not unset.
2. The eWNI_SME_ADD_STA_SELF_RSP msg handler
csr_process_add_sta_session_rsp invokes csr_roam_session_opened
which signals HDD that vdev is created successfully and hdd
calls hdd_vdev_ready and vdev related parameter set commands are
sent to FW for the deleted vdev.
3. Vdev delete is not sent for objmgr peer creation failure in
case of VDEV_TYPE_STA and release vdev object ref count.

Add cdp_vdev_detach() calls during error case and set the
vdev_active flag to false. Handle releasing vdev object ref
count in all needed error case flows.
Propagate the error in wma_vdev_attach() through
csr_roam_session_opened() to HDD and abort the vdev create.

Change-Id: Iec97122d011098fae7ae2a59864fbe8ca8a0980e
CRs-Fixed: 2322212
This commit is contained in:
Pragaspathi Thilagaraj 2018-09-26 15:52:56 +05:30
commit 3551caa95b
5 changed files with 112 additions and 83 deletions

View file

@ -2742,7 +2742,8 @@ static inline int wlan_hdd_nl_init(struct hdd_context *hdd_ctx)
return nl_srv_init(hdd_ctx->wiphy);
}
#endif
QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id);
QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id,
QDF_STATUS qdf_status);
QDF_STATUS hdd_sme_close_session_callback(uint8_t session_id);
int hdd_reassoc(struct hdd_adapter *adapter, const uint8_t *bssid,

View file

@ -3913,7 +3913,8 @@ static QDF_STATUS hdd_register_interface(struct hdd_adapter *adapter, bool rtnl_
return QDF_STATUS_SUCCESS;
}
QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id)
QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id,
QDF_STATUS qdf_status)
{
struct hdd_adapter *adapter;
struct hdd_context *hdd_ctx;
@ -3929,7 +3930,10 @@ QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id)
hdd_err("NULL adapter for %d", session_id);
return QDF_STATUS_E_INVAL;
}
set_bit(SME_SESSION_OPENED, &adapter->event_flags);
if (qdf_status == QDF_STATUS_SUCCESS)
set_bit(SME_SESSION_OPENED, &adapter->event_flags);
qdf_event_set(&adapter->qdf_session_open_event);
hdd_debug("session %d opened", adapter->session_id);
@ -4152,6 +4156,12 @@ int hdd_vdev_create(struct hdd_adapter *adapter,
goto hdd_vdev_destroy_procedure;
}
if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
hdd_err("Session failed to open due to vdev create failure");
errno = -EINVAL;
goto objmgr_vdev_destroy_procedure;
}
/* firmware ready for component communication, raise vdev_ready event */
errno = hdd_vdev_ready(adapter);
if (errno) {

View file

@ -1599,7 +1599,8 @@ typedef QDF_STATUS (*csr_roam_complete_cb)(void *context,
uint32_t roam_id,
eRoamCmdStatus roam_status,
eCsrRoamResult roam_result);
typedef QDF_STATUS (*csr_session_open_cb)(uint8_t session_id);
typedef QDF_STATUS (*csr_session_open_cb)(uint8_t session_id,
QDF_STATUS qdf_status);
typedef QDF_STATUS (*csr_session_close_cb)(uint8_t session_id);
#define CSR_IS_START_IBSS(pProfile) (eCSR_BSS_TYPE_START_IBSS == \

View file

@ -4071,7 +4071,7 @@ QDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId,
uint32_t roamId,
eRoamCmdStatus u1, eCsrRoamResult u2)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS ret, status = QDF_STATUS_SUCCESS;
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
WLAN_HOST_DIAG_EVENT_DEF(connectionStatus,
@ -4147,10 +4147,12 @@ QDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId,
&& (u2 == eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS)) {
pSession->connectedProfile.operationChannel =
roam_info->channelChangeRespEvent->newChannelNumber;
} else if ((u1 == eCSR_ROAM_SESSION_OPENED) &&
(u2 == eCSR_ROAM_RESULT_NONE)) {
} else if (u1 == eCSR_ROAM_SESSION_OPENED) {
ret = (u2 == eCSR_ROAM_RESULT_SUCCESS) ?
QDF_STATUS_SUCCESS : QDF_STATUS_E_FAILURE;
if (pSession->session_open_cb)
pSession->session_open_cb(sessionId);
pSession->session_open_cb(sessionId, ret);
else
sme_err("session_open_cb is not registered");
}
@ -16943,16 +16945,23 @@ QDF_STATUS csr_reassoc(tpAniSirGlobal pMac, uint32_t sessionId,
}
static QDF_STATUS csr_roam_session_opened(tpAniSirGlobal pMac,
QDF_STATUS qdf_status,
uint32_t sessionId)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_roam_info roamInfo;
struct csr_roam_info roam_info;
qdf_mem_set(&roamInfo, sizeof(struct csr_roam_info), 0);
status = csr_roam_call_callback(pMac, sessionId, &roamInfo, 0,
eCSR_ROAM_SESSION_OPENED,
eCSR_ROAM_RESULT_NONE);
qdf_mem_set(&roam_info, sizeof(struct csr_roam_info), 0);
if (QDF_IS_STATUS_ERROR(qdf_status)) {
status = csr_roam_call_callback(pMac, sessionId, &roam_info, 0,
eCSR_ROAM_SESSION_OPENED,
eCSR_ROAM_RESULT_FAILURE);
} else {
status = csr_roam_call_callback(pMac, sessionId, &roam_info, 0,
eCSR_ROAM_SESSION_OPENED,
eCSR_ROAM_RESULT_SUCCESS);
}
return status;
}
@ -16969,26 +16978,31 @@ QDF_STATUS csr_process_add_sta_session_rsp(tpAniSirGlobal pMac, uint8_t *pMsg)
rsp = (struct add_sta_self_params *) pMsg;
sme_debug("Add Sta self rsp status = %d", rsp->status);
if (QDF_STATUS_SUCCESS == rsp->status &&
(WMI_VDEV_TYPE_STA == rsp->type ||
(WMI_VDEV_TYPE_AP == rsp->type &&
WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == rsp->sub_type))) {
sme_debug("send SET IE msg to PE");
msg = qdf_mem_malloc(sizeof(*msg));
if (NULL == msg) {
sme_err("Memory allocation failed");
return QDF_STATUS_E_NOMEM;
}
if (QDF_IS_STATUS_SUCCESS(rsp->status)) {
if ((WMI_VDEV_TYPE_STA == rsp->type ||
(WMI_VDEV_TYPE_AP == rsp->type &&
WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == rsp->sub_type))) {
sme_debug("send SET IE msg to PE");
msg = qdf_mem_malloc(sizeof(*msg));
if (NULL == msg) {
sme_err("Memory allocation failed");
return QDF_STATUS_E_NOMEM;
}
msg->msg_type = eWNI_SME_SET_IE_REQ;
msg->session_id = rsp->session_id;
msg->length = sizeof(*msg);
status = umac_send_mb_message_to_mac(msg);
if (!QDF_IS_STATUS_SUCCESS(status))
sme_err("Failed to send down the set IE req ");
msg->msg_type = eWNI_SME_SET_IE_REQ;
msg->session_id = rsp->session_id;
msg->length = sizeof(*msg);
status = umac_send_mb_message_to_mac(msg);
if (!QDF_IS_STATUS_SUCCESS(status))
sme_err("Failed to send down the set IE req ");
}
}
csr_roam_session_opened(pMac, rsp->session_id);
csr_roam_session_opened(pMac, rsp->status, rsp->session_id);
if (QDF_IS_STATUS_ERROR(rsp->status))
csr_cleanup_session(pMac, rsp->session_id);
return QDF_STATUS_SUCCESS;
}

View file

@ -2366,12 +2366,13 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
params.nss_5g = self_sta_req->nss_5g;
/* Create a vdev in target */
status = wmi_unified_vdev_create_send(wma_handle->wmi_handle,
self_sta_req->self_mac_addr,
&params);
if (QDF_IS_STATUS_ERROR(status)) {
ret = wmi_unified_vdev_create_send(wma_handle->wmi_handle,
self_sta_req->self_mac_addr,
&params);
if (QDF_IS_STATUS_ERROR(ret)) {
WMA_LOGE("%s: Unable to add an interface for ath_dev",
__func__);
status = QDF_STATUS_E_FAILURE;
goto end;
}
@ -2389,7 +2390,7 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
self_sta_req->self_mac_addr,
vdev_id, txrx_vdev_type);
WMA_LOGD("vdev_id %hu, txrx_vdev_handle = %pK", self_sta_req->session_id,
WMA_LOGD("vdev_id %hu, txrx_vdev_handle = %pK", vdev_id,
txrx_vdev_handle);
if (!txrx_vdev_handle) {
@ -2404,6 +2405,17 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
wma_handle->interfaces[vdev_id].handle = txrx_vdev_handle;
wma_vdev_update_pause_bitmap(vdev_id, 0);
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma_handle->psoc, vdev_id,
WLAN_LEGACY_WMA_ID);
if (!vdev) {
WMA_LOGE(FL("vdev obj is NULL for vdev_id: %u"), vdev_id);
status = QDF_STATUS_E_FAILURE;
wma_handle->interfaces[vdev_id].vdev_active = false;
wmi_unified_vdev_delete_send(wma_handle->wmi_handle, vdev_id);
goto end;
}
wma_handle->interfaces[vdev_id].vdev = vdev;
wma_handle->interfaces[vdev_id].ptrn_match_enable =
wma_handle->ptrn_match_enable_all_vdev ? true : false;
@ -2436,9 +2448,9 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
tx_rx_aggregation_size.vdev_id = self_sta_req->session_id;
tx_rx_aggregation_size.aggr_type = WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU;
status = wma_set_tx_rx_aggregation_size(&tx_rx_aggregation_size);
if (status != QDF_STATUS_SUCCESS)
WMA_LOGE("failed to set aggregation sizes(err=%d)", status);
ret = wma_set_tx_rx_aggregation_size(&tx_rx_aggregation_size);
if (QDF_IS_STATUS_ERROR(ret))
WMA_LOGE("failed to set aggregation sizes(err=%d)", ret);
tx_rx_aggregation_size.tx_aggregation_size_be =
self_sta_req->tx_aggregation_size_be;
@ -2462,11 +2474,10 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
switch (self_sta_req->type) {
case WMI_VDEV_TYPE_STA:
status = wma_set_tx_rx_aggregation_size_per_ac(
ret = wma_set_tx_rx_aggregation_size_per_ac(
&tx_rx_aggregation_size);
if (status != QDF_STATUS_SUCCESS)
WMA_LOGE("failed to set aggr sizes per ac(err=%d)",
status);
if (QDF_IS_STATUS_ERROR(ret))
WMA_LOGE("set aggr sizes per ac(err=%d) failed", ret);
cfg_val = mac->mlme_cfg->sta.sta_keep_alive_period;
wma_set_sta_keep_alive(wma_handle,
@ -2477,57 +2488,59 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
/* offload STA SA query related params to fwr */
if (wmi_service_enabled(wma_handle->wmi_handle,
wmi_service_sta_pmf_offload)) {
wma_set_sta_sa_query_param(wma_handle,
self_sta_req->session_id);
wma_set_sta_sa_query_param(wma_handle, vdev_id);
}
status = wma_set_sw_retry_threshold(
&tx_aggr_sw_retry_threshold);
if (status != QDF_STATUS_SUCCESS)
WMA_LOGE("failed to set retry threshold(err=%d)",
status);
ret = wma_set_sw_retry_threshold(&tx_aggr_sw_retry_threshold);
if (QDF_IS_STATUS_ERROR(ret))
WMA_LOGE("failed to set retry threshold(err=%d)", ret);
break;
}
wma_handle->interfaces[self_sta_req->session_id].type =
self_sta_req->type;
wma_handle->interfaces[self_sta_req->session_id].sub_type =
self_sta_req->sub_type;
qdf_atomic_init(&wma_handle->interfaces
[self_sta_req->session_id].bss_status);
wma_handle->interfaces[vdev_id].type = self_sta_req->type;
wma_handle->interfaces[vdev_id].sub_type = self_sta_req->sub_type;
qdf_atomic_init(&wma_handle->interfaces[vdev_id].bss_status);
if (wma_vdev_uses_self_peer(self_sta_req->type,
self_sta_req->sub_type)) {
status = wma_create_peer(wma_handle, txrx_pdev,
txrx_vdev_handle,
self_sta_req->self_mac_addr,
WMI_PEER_TYPE_DEFAULT,
self_sta_req->session_id, false);
if (status != QDF_STATUS_SUCCESS) {
ret = wma_create_peer(wma_handle, txrx_pdev, txrx_vdev_handle,
self_sta_req->self_mac_addr,
WMI_PEER_TYPE_DEFAULT,
self_sta_req->session_id, false);
if (QDF_IS_STATUS_ERROR(ret)) {
WMA_LOGE("%s: Failed to create peer", __func__);
status = QDF_STATUS_E_FAILURE;
wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
wmi_unified_vdev_delete_send(wma_handle->wmi_handle,
self_sta_req->session_id);
wma_handle->interfaces[vdev_id].vdev_active = false;
wma_cdp_vdev_detach(soc, wma_handle, vdev_id);
wma_handle->interfaces[vdev_id].vdev = NULL;
goto end;
}
} else if (self_sta_req->type == WMI_VDEV_TYPE_STA) {
obj_peer = wma_create_objmgr_peer(wma_handle,
vdev_id,
obj_peer = wma_create_objmgr_peer(wma_handle, vdev_id,
self_sta_req->self_mac_addr,
WMI_PEER_TYPE_DEFAULT);
if (!obj_peer) {
WMA_LOGE("%s: Failed to create obj mgr peer for self sta",
__func__);
status = QDF_STATUS_E_FAILURE;
wmi_unified_vdev_delete_send(wma_handle->wmi_handle,
self_sta_req->session_id);
wma_handle->interfaces[vdev_id].vdev_active = false;
wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
wma_handle->interfaces[vdev_id].vdev = NULL;
wma_cdp_vdev_detach(soc, wma_handle, vdev_id);
goto end;
}
}
WMA_LOGD("Setting WMI_VDEV_PARAM_DISCONNECT_TH: %d",
self_sta_req->pkt_err_disconn_th);
ret = wma_vdev_set_param(wma_handle->wmi_handle,
self_sta_req->session_id,
WMI_VDEV_PARAM_DISCONNECT_TH,
self_sta_req->pkt_err_disconn_th);
self_sta_req->pkt_err_disconn_th);
ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
WMI_VDEV_PARAM_DISCONNECT_TH,
self_sta_req->pkt_err_disconn_th);
if (ret)
WMA_LOGE("Failed to set WMI_VDEV_PARAM_DISCONNECT_TH");
@ -2538,8 +2551,7 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
if (QDF_IS_STATUS_ERROR(ret))
WMA_LOGE("Failed to set WMI VDEV MCC_RTSCTS_PROTECTION_ENABLE");
ret = wma_vdev_set_param(wma_handle->wmi_handle,
self_sta_req->session_id,
ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
WMI_VDEV_PARAM_MCC_BROADCAST_PROBE_ENABLE,
mac->roam.configParam.mcc_bcast_prob_resp_enable);
if (QDF_IS_STATUS_ERROR(ret))
@ -2655,7 +2667,7 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
WMA_LOGD("%s: setting ini value for WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED: %d",
__func__, cfg_val);
ret = wma_set_enable_disable_mcc_adaptive_scheduler(cfg_val);
if (ret != QDF_STATUS_SUCCESS) {
if (QDF_IS_STATUS_ERROR(ret)) {
WMA_LOGE("Failed to set WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED");
}
} else {
@ -2663,21 +2675,12 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
}
if (self_sta_req->type == WMI_VDEV_TYPE_STA) {
status = wma_config_active_apf_mode(wma_handle,
self_sta_req->session_id);
if (QDF_IS_STATUS_ERROR(status))
ret = wma_config_active_apf_mode(wma_handle,
self_sta_req->session_id);
if (QDF_IS_STATUS_ERROR(ret))
WMA_LOGE("Failed to configure active APF mode");
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma_handle->psoc,
vdev_id,
WLAN_LEGACY_WMA_ID);
if (!vdev) {
WMA_LOGE(FL("vdev obj is NULL for vdev_id: %u"), vdev_id);
status = QDF_STATUS_E_FAILURE;
} else {
wma_handle->interfaces[vdev_id].vdev = vdev;
}
end:
self_sta_req->status = status;