qcacld-3.0: Handle failure of self peer remove in SSR

When SSR is in progress, when trying to remove self peer, if
wma_remove_peer() is failed then wma_vdev_detach() doesn't send del sta
response and wma_self_peer_remove() can still proceed to start vdev
hold request timer. This can lead to skip of vdev reference count
release by wma acquired during vdev attach.

To address this, release vdev reference count when self peer remove is
failed and when del self sta request is timed-out.

Change-Id: I2703261a848983b10798cb8ec74d1cec5a393ce5
CRs-Fixed: 2342453
This commit is contained in:
Rajeev Kumar Sirasanagandla 2018-10-25 21:10:34 +05:30 committed by nshrivas
parent c163f9ed3e
commit e5787e2440
3 changed files with 38 additions and 29 deletions

View File

@ -1928,9 +1928,9 @@ void wma_process_set_pdev_ht_ie_req(tp_wma_handle wma,
void wma_process_set_pdev_vht_ie_req(tp_wma_handle wma,
struct set_ie_param *ie_params);
void wma_remove_peer(tp_wma_handle wma, u_int8_t *bssid,
u_int8_t vdev_id, void *peer,
bool roam_synch_in_progress);
QDF_STATUS wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
uint8_t vdev_id, void *peer,
bool roam_synch_in_progress);
QDF_STATUS wma_create_peer(tp_wma_handle wma, struct cdp_pdev *pdev,
struct cdp_vdev *vdev, uint8_t peer_addr[6],

View File

@ -598,9 +598,10 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info,
QDF_STATUS wma_vdev_set_param(wmi_unified_t wmi_handle, uint32_t if_id,
uint32_t param_id, uint32_t param_value);
void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
uint8_t vdev_id, void *peer,
bool roam_synch_in_progress);
QDF_STATUS wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
uint8_t vdev_id, void *peer,
bool roam_synch_in_progress);
QDF_STATUS wma_create_peer(tp_wma_handle wma, struct cdp_pdev *pdev,
struct cdp_vdev *vdev,

View File

@ -527,9 +527,14 @@ static QDF_STATUS wma_self_peer_remove(tp_wma_handle wma_handle,
qdf_status = QDF_STATUS_E_FAULT;
goto error;
}
wma_remove_peer(wma_handle,
del_sta_self_req_param->self_mac_addr,
vdev_id, peer, false);
qdf_status = wma_remove_peer(wma_handle,
del_sta_self_req_param->self_mac_addr,
vdev_id, peer, false);
if (QDF_IS_STATUS_ERROR(qdf_status)) {
WMA_LOGE(FL("wma_remove_peer is failed"));
goto error;
}
if (wmi_service_enabled(wma_handle->wmi_handle,
wmi_service_sync_delete_cmds)) {
@ -847,15 +852,15 @@ QDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle,
if ((status != QDF_STATUS_SUCCESS) && generateRsp) {
WMA_LOGE("can't remove selfpeer, send rsp session: %d",
vdev_id);
if (!cds_is_driver_unloading()) {
WMA_LOGE("Trigger recovery for session: %d",
status = wma_handle_vdev_detach(wma_handle,
pdel_sta_self_req_param,
generateRsp);
if (QDF_IS_STATUS_ERROR(status)) {
WMA_LOGE("Trigger recovery for vdev %d",
vdev_id);
goto send_fail_rsp;
} else {
WMA_LOGE("driver unload, free mem vdev_id: %d",
vdev_id);
goto send_rsp;
cds_trigger_recovery(QDF_REASON_UNSPECIFIED);
}
return status;
} else if (status != QDF_STATUS_SUCCESS) {
WMA_LOGE("can't remove selfpeer, free msg session: %d",
vdev_id);
@ -1442,11 +1447,11 @@ QDF_STATUS wma_set_peer_param(void *wma_ctx, uint8_t *peer_addr,
* @peer: peer ptr
* @roam_synch_in_progress: roam in progress flag
*
* Return: none
* Return: QDF_STATUS
*/
void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
uint8_t vdev_id, void *peer,
bool roam_synch_in_progress)
QDF_STATUS wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
uint8_t vdev_id, void *peer,
bool roam_synch_in_progress)
{
#define PEER_ALL_TID_BITMASK 0xffffffff
uint32_t peer_tid_bitmap = PEER_ALL_TID_BITMASK;
@ -1457,7 +1462,7 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
void *vdev;
QDF_STATUS qdf_status;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
uint32_t bitmap = 1 << CDP_PEER_DELETE_NO_SPECIAL;
if (!wma->interfaces[vdev_id].peer_count) {
@ -1465,19 +1470,19 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
__func__, bssid, vdev_id,
wma->interfaces[vdev_id].peer_count);
QDF_BUG(0);
return;
return QDF_STATUS_E_INVAL;
}
if (!soc) {
WMA_LOGE("%s:SOC context is NULL", __func__);
QDF_BUG(0);
return;
return QDF_STATUS_E_INVAL;
}
if (!peer) {
WMA_LOGE("%s: PEER is NULL for vdev_id: %d", __func__, vdev_id);
QDF_BUG(0);
return;
return QDF_STATUS_E_INVAL;
}
peer_mac_addr = cdp_peer_get_peer_mac_addr(soc, peer);
if (peer_mac_addr == NULL) {
@ -1485,14 +1490,14 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
__func__, bssid, vdev_id,
wma->interfaces[vdev_id].peer_count);
QDF_BUG(0);
return;
return QDF_STATUS_E_INVAL;
}
vdev = cdp_get_vdev_from_vdev_id(soc, pdev, vdev_id);
if (!vdev) {
WMA_LOGE("%s vdev is null for peer peer->mac_addr %pM",
__func__, peer_mac_addr);
QDF_BUG(0);
return;
return QDF_STATUS_E_INVAL;
}
cdp_peer_teardown(soc, vdev, peer);
@ -1523,6 +1528,7 @@ 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;
qdf_status = QDF_STATUS_E_FAILURE;
}
peer_detach:
@ -1548,6 +1554,8 @@ peer_detach:
wma->interfaces[vdev_id].peer_count--;
#undef PEER_ALL_TID_BITMASK
return qdf_status;
}
/**
@ -3351,6 +3359,7 @@ void wma_hold_req_timer(void *data)
struct del_sta_self_rsp_params *del_sta;
del_sta = (struct del_sta_self_rsp_params *)tgt_req->user_data;
del_sta->self_sta_param->status = QDF_STATUS_E_TIMEOUT;
WMA_LOGA(FL("wma delete sta p2p request timed out"));
@ -3358,9 +3367,8 @@ void wma_hold_req_timer(void *data)
wma_trigger_recovery_assert_on_fw_timeout(
WMA_DELETE_STA_REQ);
} else {
if (del_sta->generate_rsp)
wma_send_del_sta_self_resp(
del_sta->self_sta_param);
wma_handle_vdev_detach(wma, del_sta->self_sta_param,
del_sta->generate_rsp);
}
qdf_mem_free(tgt_req->user_data);
} else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) &&