summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/utils/host_diag_log/inc/host_diag_core_event.h4
-rw-r--r--core/wma/inc/wma.h10
-rw-r--r--core/wma/inc/wma_if.h10
-rw-r--r--core/wma/inc/wma_internal.h6
-rw-r--r--core/wma/src/wma_dev_if.c455
-rw-r--r--core/wma/src/wma_main.c16
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,