diff options
| -rw-r--r-- | core/utils/host_diag_log/inc/host_diag_core_event.h | 4 | ||||
| -rw-r--r-- | core/wma/inc/wma.h | 10 | ||||
| -rw-r--r-- | core/wma/inc/wma_if.h | 10 | ||||
| -rw-r--r-- | core/wma/inc/wma_internal.h | 6 | ||||
| -rw-r--r-- | core/wma/src/wma_dev_if.c | 455 | ||||
| -rw-r--r-- | core/wma/src/wma_main.c | 16 |
6 files changed, 431 insertions, 70 deletions
diff --git a/core/utils/host_diag_log/inc/host_diag_core_event.h b/core/utils/host_diag_log/inc/host_diag_core_event.h index 7962dda35245..623db35d7e3d 100644 --- a/core/utils/host_diag_log/inc/host_diag_core_event.h +++ b/core/utils/host_diag_log/inc/host_diag_core_event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -332,6 +332,7 @@ enum wifi_connectivity_events { * @WIFI_POWER_EVENT_WAKELOCK_PNO: PNO feature related * @WIFI_POWER_EVENT_WAKELOCK_DEL_STA: Deletion of a station * @WIFI_POWER_EVENT_WAKELOCK_DFS: DFS related wakelocks + * @WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP: Firmware response * @WIFI_POWER_EVENT_WAKELOCK_MISC: Miscellaneous wakelocks * * Indicates the reason for which the wakelock was taken/released @@ -353,6 +354,7 @@ enum wake_lock_reason { WIFI_POWER_EVENT_WAKELOCK_PNO, WIFI_POWER_EVENT_WAKELOCK_DEL_STA, WIFI_POWER_EVENT_WAKELOCK_DFS, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP, WIFI_POWER_EVENT_WAKELOCK_MISC, }; diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 626df86d8ae4..f3b3b882b895 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -243,6 +243,11 @@ #define WMA_PEER_ASSOC_CNF_START 0x01 #define WMA_PEER_ASSOC_TIMEOUT (3000) /* 3 seconds */ +#define WMA_DELETE_STA_RSP_START 0x02 +#define WMA_DELETE_STA_TIMEOUT (6000) /* 6 seconds */ + +#define WMA_DEL_P2P_SELF_STA_RSP_START 0x03 + #define WMA_VDEV_START_REQUEST_TIMEOUT (3000) /* 3 seconds */ #define WMA_VDEV_STOP_REQUEST_TIMEOUT (3000) /* 3 seconds */ @@ -300,6 +305,7 @@ #define WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION (5 * 1000) /* in msec */ #endif #define WMA_BMISS_EVENT_WAKE_LOCK_DURATION (4 * 1000) /* in msec */ +#define WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION (3 * 1000) /* in msec */ #define WMA_TXMIC_LEN 8 #define WMA_RXMIC_LEN 8 @@ -1188,6 +1194,8 @@ struct wmi_init_cmd { * handle of other modules. * @saved_wmi_init_cmd: Saved WMI INIT command * @service_ready_ext_evt: Wait event for service ready ext + * @wmi_cmd_rsp_wake_lock: wmi command response wake lock + * @wmi_cmd_rsp_runtime_lock: wmi command response bus lock */ typedef struct { void *wmi_handle; @@ -1373,6 +1381,8 @@ typedef struct { CDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac, roam_offload_synch_ind *roam_synch_data, tpSirBssDescription bss_desc_ptr); + cdf_wake_lock_t wmi_cmd_rsp_wake_lock; + cdf_runtime_lock_t wmi_cmd_rsp_runtime_lock; } t_wma_handle, *tp_wma_handle; /** diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 3c1728b8c60f..1dab6fab4b65 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -1288,6 +1288,16 @@ struct del_sta_self_params { }; /** + * struct del_sta_self_rsp_params - Del Sta Self response params + * @self_sta_param: sta params + * @generate_rsp: generate response to upper layers + */ +struct del_sta_self_rsp_params { + struct del_sta_self_params *self_sta_param; + uint8_t generate_rsp; +}; + +/** * struct tP2pPsParams - P2P powersave related params * @opp_ps: opportunistic power save * @ctWindow: CT window diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index bf8b1dfafb84..d2788103f868 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1169,5 +1169,11 @@ CDF_STATUS wma_process_set_ie_info(tp_wma_handle wma, struct vdev_ie_info *ie_info); int wma_peer_assoc_conf_handler(void *handle, uint8_t *cmd_param_info, uint32_t len); +int wma_vdev_delete_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len); +int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len); +void wma_remove_req(tp_wma_handle wma, uint8_t vdev_id, + uint8_t type); #endif diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index fb57c04b6505..d5d0abf2344c 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -297,6 +297,9 @@ static int wma_unified_vdev_delete_send(wmi_unified_t wmi_handle, uint8_t if_id) * @vdev_id: vdev id * @type: request type * + * Find target request for given vdev id & type of request. + * Remove that request from active list. + * * Return: return target request if found or NULL. */ static struct wma_target_req *wma_find_req(tp_wma_handle wma, @@ -350,6 +353,68 @@ static struct wma_target_req *wma_find_req(tp_wma_handle wma, } /** + * wma_find_remove_req_msgtype() - find and remove request for vdev id + * @wma: wma handle + * @vdev_id: vdev id + * @msg_type: message request type + * + * Find target request for given vdev id & sub type of request. + * Remove the same from active list. + * + * Return: Success if request found, failure other wise + */ +static struct wma_target_req *wma_find_remove_req_msgtype(tp_wma_handle wma, + uint8_t vdev_id, uint32_t msg_type) +{ + struct wma_target_req *req_msg = NULL; + bool found = false; + cdf_list_node_t *node1 = NULL, *node2 = NULL; + CDF_STATUS status; + + cdf_spin_lock_bh(&wma->wma_hold_req_q_lock); + if (CDF_STATUS_SUCCESS != cdf_list_peek_front(&wma->wma_hold_req_queue, + &node2)) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGE(FL("unable to get msg node from request queue")); + return NULL; + } + + do { + node1 = node2; + req_msg = cdf_container_of(node1, struct wma_target_req, node); + if (req_msg->vdev_id != vdev_id) + continue; + if (req_msg->msg_type != msg_type) + continue; + + found = true; + status = cdf_list_remove_node(&wma->wma_hold_req_queue, node1); + if (CDF_STATUS_SUCCESS != status) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGD(FL("Failed to remove request. vdev_id %d type %d"), + vdev_id, msg_type); + return NULL; + } + break; + } while (CDF_STATUS_SUCCESS == + cdf_list_peek_next(&wma->wma_hold_req_queue, node1, + &node2)); + + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + if (!found) { + WMA_LOGE(FL("target request not found for vdev_id %d type %d"), + vdev_id, msg_type); + return NULL; + } + + WMA_LOGD(FL("target request found for vdev id: %d type %d"), + vdev_id, msg_type); + + return req_msg; +} + + +/** * wma_find_vdev_req() - find target request for vdev id * @wma: wma handle * @vdev_id: vdev id @@ -428,21 +493,24 @@ void wma_vdev_detach_callback(void *ctx) return; } param = (struct del_sta_self_params *) iface->del_staself_req; - WMA_LOGD("%s: sending eWNI_SME_DEL_STA_SELF_RSP for vdev %d", + WMA_LOGE("%s: sending eWNI_SME_DEL_STA_SELF_RSP for vdev %d", __func__, param->session_id); - - req_msg = wma_find_vdev_req(wma, param->session_id, - WMA_TARGET_REQ_TYPE_VDEV_DEL); - if (req_msg) { - WMA_LOGD("%s: Found vdev request for vdev id %d", - __func__, param->session_id); - cdf_mc_timer_stop(&req_msg->event_timeout); - cdf_mc_timer_destroy(&req_msg->event_timeout); - cdf_mem_free(req_msg); + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + req_msg = wma_find_vdev_req(wma, param->session_id, + WMA_TARGET_REQ_TYPE_VDEV_DEL); + if (req_msg) { + WMA_LOGD("%s: Found vdev request for vdev id %d", + __func__, param->session_id); + cdf_mc_timer_stop(&req_msg->event_timeout); + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + } } if (iface->addBssStaContext) cdf_mem_free(iface->addBssStaContext); + #if defined WLAN_FEATURE_VOWIFI_11R if (iface->staKeyParams) cdf_mem_free(iface->staKeyParams); @@ -460,93 +528,127 @@ void wma_vdev_detach_callback(void *ctx) } } + /** - * wma_vdev_detach() - send vdev delete command to fw - * @wma_handle: wma handle - * @pdel_sta_self_req_param: del sta params - * @generateRsp: generate Response flag + * wma_self_peer_remove() - Self peer remove handler + * @wma: wma handle + * @del_sta_self_req_param: vdev id + * @generate_vdev_rsp: request type * - * Return: CDF status + * Return: success if peer delete command sent to firmware, else failure. */ -CDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, - struct del_sta_self_params *pdel_sta_self_req_param, - uint8_t generateRsp) + +static CDF_STATUS wma_self_peer_remove(tp_wma_handle wma_handle, + struct del_sta_self_params *del_sta_self_req_param, + uint8_t generate_vdev_rsp) { - CDF_STATUS status = CDF_STATUS_SUCCESS; ol_txrx_peer_handle peer; ol_txrx_pdev_handle pdev; uint8_t peer_id; - uint8_t vdev_id = pdel_sta_self_req_param->session_id; - struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; - struct wma_target_req *msg; - cds_msg_t sme_msg = { 0 }; - - if ((iface->type == WMI_VDEV_TYPE_AP) && - (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) { + uint8_t vdev_id = del_sta_self_req_param->session_id; + struct wma_target_req *msg = NULL; + struct del_sta_self_rsp_params *sta_self_wmi_rsp; - WMA_LOGA("P2P Device: removing self peer %pM", - pdel_sta_self_req_param->self_mac_addr); + WMA_LOGE("P2P Device: removing self peer %pM", + del_sta_self_req_param->self_mac_addr); - pdev = cds_get_context(CDF_MODULE_ID_TXRX); - - if (NULL == pdev) { - WMA_LOGE("%s: Failed to get pdev", __func__); + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); return CDF_STATUS_E_FAULT; - } - - peer = ol_txrx_find_peer_by_addr(pdev, - pdel_sta_self_req_param->self_mac_addr, - &peer_id); - if (!peer) { - WMA_LOGE("%s Failed to find peer %pM", __func__, - pdel_sta_self_req_param->self_mac_addr); - } - wma_remove_peer(wma_handle, - pdel_sta_self_req_param->self_mac_addr, - vdev_id, peer, false); - } - if (cdf_atomic_read(&iface->bss_status) == WMA_BSS_STATUS_STARTED) { - WMA_LOGA("BSS is not yet stopped. Defering vdev(vdev id %x) deletion", - vdev_id); - iface->del_staself_req = pdel_sta_self_req_param; - return status; } - if (!iface->handle) { - WMA_LOGE("handle of vdev_id %d is NULL vdev is already freed", - vdev_id); - cdf_mem_free(pdel_sta_self_req_param); - pdel_sta_self_req_param = NULL; - return status; + peer = ol_txrx_find_peer_by_addr(pdev, + del_sta_self_req_param->self_mac_addr, + &peer_id); + if (!peer) { + WMA_LOGE("%s Failed to find peer %pM", __func__, + del_sta_self_req_param->self_mac_addr); + return CDF_STATUS_SUCCESS; } + wma_remove_peer(wma_handle, + del_sta_self_req_param->self_mac_addr, + vdev_id, peer, false); + + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + sta_self_wmi_rsp = + cdf_mem_malloc(sizeof(struct del_sta_self_rsp_params)); + if (sta_self_wmi_rsp == NULL) { + WMA_LOGP(FL("Failed to allocate memory")); + return CDF_STATUS_E_NOMEM; + } + sta_self_wmi_rsp->self_sta_param = del_sta_self_req_param; + sta_self_wmi_rsp->generate_rsp = generate_vdev_rsp; + msg = wma_fill_hold_req(wma_handle, vdev_id, + WMA_DELETE_STA_REQ, + WMA_DEL_P2P_SELF_STA_RSP_START, + sta_self_wmi_rsp, + WMA_DELETE_STA_TIMEOUT); + if (!msg) { + WMA_LOGP(FL("Failed to allocate request for vdev_id %d"), + vdev_id); + wma_remove_req(wma_handle, vdev_id, + WMA_DEL_P2P_SELF_STA_RSP_START); + return CDF_STATUS_E_FAILURE; + } + } + return CDF_STATUS_SUCCESS; +} +static CDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle, + struct del_sta_self_params *del_sta_self_req_param, + uint8_t generate_rsp) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t vdev_id = del_sta_self_req_param->session_id; + struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + struct wma_target_req *msg = NULL; + cds_msg_t sme_msg = { 0 }; - /* remove the interface from ath_dev */ if (wma_unified_vdev_delete_send(wma_handle->wmi_handle, vdev_id)) { - WMA_LOGE("Unable to remove an interface for ath_dev."); + WMA_LOGE("Unable to remove an interface"); status = CDF_STATUS_E_FAILURE; goto out; } - WMA_LOGD("vdev_id:%hu vdev_hdl:%p", vdev_id, iface->handle); - if (!generateRsp) { + WMA_LOGE("vdev_id:%hu vdev_hdl:%p", vdev_id, iface->handle); + if (!generate_rsp) { WMA_LOGE("Call txrx detach w/o callback for vdev %d", vdev_id); ol_txrx_vdev_detach(iface->handle, NULL, NULL); goto out; } - iface->del_staself_req = pdel_sta_self_req_param; + iface->del_staself_req = del_sta_self_req_param; msg = wma_fill_vdev_req(wma_handle, vdev_id, WMA_DEL_STA_SELF_REQ, - WMA_TARGET_REQ_TYPE_VDEV_DEL, iface, 2000); + WMA_TARGET_REQ_TYPE_VDEV_DEL, iface, 6000); if (!msg) { WMA_LOGE("%s: Failed to fill vdev request for vdev_id %d", __func__, vdev_id); status = CDF_STATUS_E_NOMEM; goto out; } + + /* Acquire wake lock only when you expect a response from firmware */ + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + cdf_wake_lock_timeout_acquire( + &wma_handle->wmi_cmd_rsp_wake_lock, + WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_prevent_suspend( + wma_handle->wmi_cmd_rsp_runtime_lock); + } WMA_LOGD("Call txrx detach with callback for vdev %d", vdev_id); ol_txrx_vdev_detach(iface->handle, NULL, NULL); - wma_vdev_detach_callback(iface); + + /* + * send the response immediately if WMI_SERVICE_SYNC_DELETE_CMDS + * service is not supported by firmware + */ + if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) + wma_vdev_detach_callback(iface); return status; out: if (iface->addBssStaContext) @@ -556,20 +658,67 @@ out: cdf_mem_free(iface->staKeyParams); #endif /* WLAN_FEATURE_VOWIFI_11R */ cdf_mem_zero(iface, sizeof(*iface)); - pdel_sta_self_req_param->status = status; - if (generateRsp) { + del_sta_self_req_param->status = status; + if (generate_rsp) { sme_msg.type = eWNI_SME_DEL_STA_SELF_RSP; - sme_msg.bodyptr = pdel_sta_self_req_param; + sme_msg.bodyptr = del_sta_self_req_param; sme_msg.bodyval = 0; status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); if (!CDF_IS_STATUS_SUCCESS(status)) { - WMA_LOGE("Failed to post eWNI_SME_ADD_STA_SELF_RSP"); - cdf_mem_free(pdel_sta_self_req_param); + WMA_LOGE("Failed to post eWNI_SME_DEL_STA_SELF_RSP"); + cdf_mem_free(del_sta_self_req_param); } } return status; } +/** + * wma_vdev_detach() - send vdev delete command to fw + * @wma_handle: wma handle + * @pdel_sta_self_req_param: del sta params + * @generateRsp: generate Response flag + * + * Return: CDF status + */ +CDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, + struct del_sta_self_params *pdel_sta_self_req_param, + uint8_t generateRsp) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t vdev_id = pdel_sta_self_req_param->session_id; + struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + + if (cdf_atomic_read(&iface->bss_status) == WMA_BSS_STATUS_STARTED) { + WMA_LOGA("BSS is not yet stopped. Defering vdev(vdev id %x) deletion", + vdev_id); + iface->del_staself_req = pdel_sta_self_req_param; + return status; + } + + if (!iface->handle) { + WMA_LOGE("handle of vdev_id %d is NULL vdev is already freed", + vdev_id); + cdf_mem_free(pdel_sta_self_req_param); + pdel_sta_self_req_param = NULL; + return status; + } + + /* P2P Device */ + if ((iface->type == WMI_VDEV_TYPE_AP) && + (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) { + wma_self_peer_remove(wma_handle, pdel_sta_self_req_param, + generateRsp); + if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) + status = wma_handle_vdev_detach(wma_handle, + pdel_sta_self_req_param, generateRsp); + } else { /* other than P2P */ + status = wma_handle_vdev_detach(wma_handle, + pdel_sta_self_req_param, generateRsp); + } + + return status; +} /** * wmi_unified_peer_delete_send() - send PEER delete command to fw @@ -2276,6 +2425,123 @@ free_req_msg: } /** + * wma_vdev_delete_handler() - vdev delete response handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_vdev_delete_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *param_buf; + wmi_vdev_delete_cmd_fixed_param *event; + struct wma_target_req *req_msg; + int status = 0; + + param_buf = (WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid vdev delete event buffer"); + return -EINVAL; + } + + event = (wmi_vdev_delete_cmd_fixed_param *)param_buf->fixed_param; + if (!event) { + WMA_LOGE("Invalid vdev delete event buffer"); + return -EINVAL; + } + + WMA_LOGE("%s Vdev delete resp vdev id %d", __func__, event->vdev_id); + req_msg = wma_find_vdev_req(wma, event->vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_DEL); + if (!req_msg) { + WMA_LOGD(FL("Vdev delete resp is not handled! vdev id %d"), + event->vdev_id); + return -EINVAL; + } + cdf_wake_lock_release(&wma->wmi_cmd_rsp_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_allow_suspend(wma->wmi_cmd_rsp_runtime_lock); + /* Send response to upper layers */ + wma_vdev_detach_callback(req_msg->user_data); + cdf_mc_timer_stop(&req_msg->event_timeout); + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + + return status; +} + +/** + * wma_peer_delete_handler() - peer delete response handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_PEER_DELETE_RESP_EVENTID_param_tlvs *param_buf; + wmi_peer_delete_cmd_fixed_param *event; + struct wma_target_req *req_msg; + tDeleteStaParams *del_sta; + uint8_t macaddr[IEEE80211_ADDR_LEN]; + int status = 0; + + param_buf = (WMI_PEER_DELETE_RESP_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid vdev delete event buffer"); + return -EINVAL; + } + + event = (wmi_peer_delete_cmd_fixed_param *)param_buf->fixed_param; + if (!event) { + WMA_LOGE("Invalid vdev delete event buffer"); + return -EINVAL; + } + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->peer_macaddr, macaddr); + WMA_LOGE(FL("Peer Delete Response, vdev %d Peer %pM"), + event->vdev_id, macaddr); + req_msg = wma_find_remove_req_msgtype(wma, event->vdev_id, + WMA_DELETE_STA_REQ); + if (!req_msg) { + WMA_LOGD("Peer Delete response is not handled"); + return -EINVAL; + } + + cdf_wake_lock_release(&wma->wmi_cmd_rsp_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_allow_suspend(wma->wmi_cmd_rsp_runtime_lock); + /* Cleanup timeout handler */ + cdf_mc_timer_stop(&req_msg->event_timeout); + cdf_mc_timer_destroy(&req_msg->event_timeout); + + if (req_msg->type == WMA_DELETE_STA_RSP_START) { + del_sta = req_msg->user_data; + if (del_sta->respReqd) { + WMA_LOGD(FL("Sending peer del rsp to umac")); + wma_send_msg(wma, WMA_DELETE_STA_RSP, + (void *)del_sta, CDF_STATUS_SUCCESS); + } + } else if (req_msg->type == WMA_DEL_P2P_SELF_STA_RSP_START) { + struct del_sta_self_rsp_params *data; + data = (struct del_sta_self_rsp_params *)req_msg->user_data; + WMA_LOGD(FL("Calling vdev detach handler")); + wma_handle_vdev_detach(wma, data->self_sta_param, + data->generate_rsp); + cdf_mem_free(data); + } + cdf_mem_free(req_msg); + return status; +} + + +/** * wma_hold_req_timer() - wma hold request timeout function * @data: target request params * @@ -2310,6 +2576,24 @@ void wma_hold_req_timer(void *data) WMA_LOGD(FL("Sending add sta rsp to umac (mac:%pM, status:%d)"), params->staMac, params->status); wma_send_msg(wma, WMA_ADD_STA_RSP, (void *)params, 0); + } else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) && + (tgt_req->type == WMA_DELETE_STA_RSP_START)) { + tpDeleteStaParams params = + (tpDeleteStaParams) tgt_req->user_data; + params->status = CDF_STATUS_E_TIMEOUT; + WMA_LOGE(FL("WMA_DEL_STA_REQ timed out")); + WMA_LOGP(FL("Sending del sta rsp to umac (mac:%pM, status:%d)"), + params->staMac, params->status); + /* + * Assert in development build only. + * Send response in production builds. + */ + CDF_ASSERT(0); + wma_send_msg(wma, WMA_DELETE_STA_RSP, (void *)params, 0); + } else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) && + (tgt_req->type == WMA_DEL_P2P_SELF_STA_RSP_START)) { + WMA_LOGA(FL("wma delete sta p2p request timed out")); + CDF_ASSERT(0); } free_tgt_req: cdf_mc_timer_destroy(&tgt_req->event_timeout); @@ -2342,6 +2626,7 @@ struct wma_target_req *wma_fill_hold_req(tp_wma_handle wma, } WMA_LOGE(FL("vdev_id %d msg %d type %d"), vdev_id, msg_type, type); + req->vdev_id = vdev_id; req->msg_type = msg_type; req->type = type; @@ -2532,7 +2817,15 @@ void wma_vdev_resp_timer(void *data) struct del_sta_self_params *params = (struct del_sta_self_params *) iface->del_staself_req; + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + cdf_wake_lock_release(&wma->wmi_cmd_rsp_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_allow_suspend( + wma->wmi_cmd_rsp_runtime_lock); + } params->status = CDF_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WMA_DEL_STA_SELF_REQ timedout", __func__); sme_msg.type = eWNI_SME_DEL_STA_SELF_RSP; sme_msg.bodyptr = iface->del_staself_req; @@ -4056,6 +4349,7 @@ static void wma_delete_sta_req_ap_mode(tp_wma_handle wma, { ol_txrx_pdev_handle pdev; struct ol_txrx_peer_t *peer; + struct wma_target_req *msg; pdev = cds_get_context(CDF_MODULE_ID_TXRX); @@ -4077,6 +4371,31 @@ static void wma_delete_sta_req_ap_mode(tp_wma_handle wma, false); del_sta->status = CDF_STATUS_SUCCESS; + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + msg = wma_fill_hold_req(wma, del_sta->smesessionId, + WMA_DELETE_STA_REQ, + WMA_DELETE_STA_RSP_START, del_sta, + WMA_DELETE_STA_TIMEOUT); + if (!msg) { + WMA_LOGP(FL("Failed to allocate request. vdev_id %d"), + del_sta->smesessionId); + wma_remove_req(wma, del_sta->smesessionId, + WMA_DELETE_STA_RSP_START); + del_sta->status = CDF_STATUS_E_NOMEM; + goto send_del_rsp; + } + /* + * Acquire wake lock and bus lock till + * firmware sends the response + */ + cdf_wake_lock_timeout_acquire(&wma->wmi_cmd_rsp_wake_lock, + WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_prevent_suspend(wma->wmi_cmd_rsp_runtime_lock); + return; + } + send_del_rsp: if (del_sta->respReqd) { WMA_LOGD("%s: Sending del rsp to umac (status: %d)", diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 5ca415c0ccf0..a83f89558d03 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1937,14 +1937,26 @@ CDF_STATUS wma_open(void *cds_context, WMI_RSSI_BREACH_EVENTID, wma_rssi_breached_event_handler); + cdf_wake_lock_init(&wma_handle->wmi_cmd_rsp_wake_lock, + "wlan_fw_rsp_wakelock"); + wma_handle->wmi_cmd_rsp_runtime_lock = + cdf_runtime_lock_init("wlan_fw_rsp_runtime_lock"); + /* Register peer assoc conf event handler */ wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_PEER_ASSOC_CONF_EVENTID, wma_peer_assoc_conf_handler); - + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_VDEV_DELETE_RESP_EVENTID, + wma_vdev_delete_handler); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_DELETE_RESP_EVENTID, + wma_peer_delete_handler); return CDF_STATUS_SUCCESS; err_dbglog_init: + cdf_wake_lock_destroy(&wma_handle->wmi_cmd_rsp_wake_lock); + cdf_runtime_lock_deinit(wma_handle->wmi_cmd_rsp_runtime_lock); cdf_spinlock_destroy(&wma_handle->vdev_respq_lock); cdf_spinlock_destroy(&wma_handle->wma_hold_req_q_lock); err_event_init: @@ -3094,6 +3106,8 @@ CDF_STATUS wma_close(void *cds_ctx) cdf_event_destroy(&wma_handle->recovery_event); wma_cleanup_vdev_resp(wma_handle); wma_cleanup_hold_req(wma_handle); + cdf_wake_lock_destroy(&wma_handle->wmi_cmd_rsp_wake_lock); + cdf_runtime_lock_deinit(wma_handle->wmi_cmd_rsp_runtime_lock); for (idx = 0; idx < wma_handle->num_mem_chunks; ++idx) { cdf_os_mem_free_consistent(wma_handle->cdf_dev, wma_handle->mem_chunks[idx].len, |
