qcacmn: Add WMI scheduler thread context execution

Add WMI scheduler thread context execution framework
to process firmware events in the common project.

Change-Id: If56a4767ee9428d2f93d54ccbf5a8bb17e89e0f4
CRs-Fixed: 2554727
This commit is contained in:
Sandeep Puligilla
2019-06-27 20:46:59 -07:00
committed by nshrivas
parent 11f5a63a6c
commit 9304a97961
3 changed files with 152 additions and 29 deletions

View File

@@ -151,11 +151,14 @@ enum wmi_target_type {
* enum wmi_rx_exec_ctx - wmi rx execution context
* @WMI_RX_WORK_CTX: work queue context execution provided by WMI layer
* @WMI_RX_UMAC_CTX: execution context provided by umac layer
* @WMI_RX_SERIALIZER_CTX: Execution context is serialized thread context
*
*/
enum wmi_rx_exec_ctx {
WMI_RX_WORK_CTX,
WMI_RX_UMAC_CTX
WMI_RX_UMAC_CTX,
WMI_RX_TASKLET_CTX = WMI_RX_UMAC_CTX,
WMI_RX_SERIALIZER_CTX = 2
};
/**
@@ -3628,7 +3631,6 @@ wmi_unified_send_peer_cfr_capture_cmd(wmi_unified_t wmi_handle,
QDF_STATUS
wmi_extract_cfr_peer_tx_event_param(wmi_unified_t wmi_handle, void *evt_buf,
wmi_cfr_peer_tx_event_param *peer_tx_event);
#endif /* WLAN_CFR_ENABLE */
#ifdef WIFI_POS_CONVERGED
@@ -3644,4 +3646,13 @@ QDF_STATUS
wmi_extract_oem_response_param(wmi_unified_t wmi_hdl, void *resp_buf,
struct wmi_oem_response_param *oem_resp_param);
#endif /* WIFI_POS_CONVERGED */
/**
* wmi_critical_events_in_flight() - get the number of critical events in flight
*
* @wmi_hdl: WMI handle
*
* Return: the number of critical events in flight.
*/
uint32_t wmi_critical_events_in_flight(struct wmi_unified *wmi);
#endif /* _WMI_UNIFIED_API_H_ */

View File

@@ -2127,6 +2127,7 @@ struct wmi_unified {
struct wmi_soc *soc;
uint16_t wmi_max_cmds;
struct dentry *debugfs_de[NUM_DEBUG_INFOS];
qdf_atomic_t critical_events_in_flight;
#ifdef WMI_EXT_DBG
int wmi_ext_dbg_msg_queue_size;
qdf_list_t wmi_ext_dbg_msg_queue;
@@ -2172,6 +2173,16 @@ struct wmi_soc {
#endif /*WMI_INTERFACE_EVENT_LOGGING */
};
/**
* struct wmi_process_fw_event_params - fw event parameters
* @wmi_handle: wmi handle
* @evt_buf: event buffer
*/
struct wmi_process_fw_event_params {
void *wmi_handle;
void *evt_buf;
};
/**
* wmi_mtrace() - Wrappper function for qdf_mtrace api
* @message_id: 32-Bit Wmi message ID

View File

@@ -34,7 +34,7 @@
#endif
#include <linux/debugfs.h>
#include <target_if.h>
#ifdef WMI_EXT_DBG
#include "qdf_atomic.h"
@@ -2083,29 +2083,6 @@ int wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle,
}
qdf_export_symbol(wmi_unified_unregister_event_handler);
/**
* wmi_process_fw_event_default_ctx() - process in default caller context
* @wmi_handle: handle to wmi
* @htc_packet: pointer to htc packet
* @exec_ctx: execution context for wmi fw event
*
* Event process by below function will be in default caller context.
* wmi internally provides rx work thread processing context.
*
* Return: none
*/
static void wmi_process_fw_event_default_ctx(struct wmi_unified *wmi_handle,
HTC_PACKET *htc_packet, uint8_t exec_ctx)
{
wmi_buf_t evt_buf;
evt_buf = (wmi_buf_t) htc_packet->pPktContext;
wmi_handle->rx_ops.wma_process_fw_event_handler_cbk
(wmi_handle->scn_handle, evt_buf, exec_ctx);
return;
}
void wmi_process_fw_event_worker_thread_ctx(struct wmi_unified *wmi_handle,
void *evt_buf)
{
@@ -2121,6 +2098,129 @@ void wmi_process_fw_event_worker_thread_ctx(struct wmi_unified *wmi_handle,
qdf_export_symbol(wmi_process_fw_event_worker_thread_ctx);
uint32_t wmi_critical_events_in_flight(struct wmi_unified *wmi)
{
return qdf_atomic_read(&wmi->critical_events_in_flight);
}
static bool
wmi_is_event_critical(struct wmi_unified *wmi_handle, uint32_t event_id)
{
if (wmi_handle->wmi_events[wmi_roam_synch_event_id] == event_id)
return true;
return false;
}
static void wmi_discard_fw_event(struct scheduler_msg *msg)
{
struct wmi_process_fw_event_params *event_param;
if (!msg->bodyptr)
return;
event_param = (struct wmi_process_fw_event_params *)msg->bodyptr;
qdf_nbuf_free(event_param->evt_buf);
qdf_mem_free(msg->bodyptr);
msg->bodyptr = NULL;
msg->bodyval = 0;
msg->type = 0;
}
static int wmi_process_fw_event_handler(struct scheduler_msg *msg)
{
struct wmi_process_fw_event_params *params =
(struct wmi_process_fw_event_params *)msg->bodyptr;
struct wmi_unified *wmi_handle;
uint32_t event_id;
wmi_handle = (struct wmi_unified *)params->wmi_handle;
event_id = WMI_GET_FIELD(qdf_nbuf_data(params->evt_buf),
WMI_CMD_HDR, COMMANDID);
wmi_process_fw_event(wmi_handle, params->evt_buf);
if (wmi_is_event_critical(wmi_handle, event_id))
qdf_atomic_dec(&wmi_handle->critical_events_in_flight);
qdf_mem_free(msg->bodyptr);
return 0;
}
/**
* wmi_process_fw_event_sched_thread_ctx() - common event handler to serialize
* event processing through scheduler thread
* @ctx: wmi context
* @ev: event buffer
* @rx_ctx: rx execution context
*
* Return: 0 on success, errno on failure
*/
static QDF_STATUS
wmi_process_fw_event_sched_thread_ctx(struct wmi_unified *wmi,
void *ev)
{
struct wmi_process_fw_event_params *params_buf;
struct scheduler_msg msg = { 0 };
uint32_t event_id;
struct target_psoc_info *tgt_hdl;
bool is_wmi_ready = false;
struct wlan_objmgr_psoc *psoc;
psoc = target_if_get_psoc_from_scn_hdl(wmi->scn_handle);
if (!psoc) {
target_if_err("psoc is null");
qdf_nbuf_free(ev);
return QDF_STATUS_E_INVAL;
}
tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
if (!tgt_hdl) {
wmi_err("target_psoc_info is null");
qdf_nbuf_free(ev);
return QDF_STATUS_E_INVAL;
}
is_wmi_ready = target_psoc_get_wmi_ready(tgt_hdl);
if (!is_wmi_ready) {
wmi_debug("fw event recvd before ready event processed");
wmi_debug("therefore use worker thread");
wmi_process_fw_event_worker_thread_ctx(wmi, ev);
return QDF_STATUS_E_INVAL;
}
params_buf = qdf_mem_malloc(sizeof(struct wmi_process_fw_event_params));
if (!params_buf) {
wmi_err("malloc failed");
qdf_nbuf_free(ev);
return QDF_STATUS_E_NOMEM;
}
params_buf->wmi_handle = wmi;
params_buf->evt_buf = ev;
event_id = WMI_GET_FIELD(qdf_nbuf_data(params_buf->evt_buf),
WMI_CMD_HDR, COMMANDID);
if (wmi_is_event_critical(wmi, event_id))
qdf_atomic_inc(&wmi->critical_events_in_flight);
msg.bodyptr = params_buf;
msg.bodyval = 0;
msg.callback = wmi_process_fw_event_handler;
msg.flush_callback = wmi_discard_fw_event;
if (QDF_STATUS_SUCCESS !=
scheduler_post_message(QDF_MODULE_ID_TARGET_IF,
QDF_MODULE_ID_TARGET_IF,
QDF_MODULE_ID_TARGET_IF, &msg)) {
qdf_nbuf_free(ev);
qdf_mem_free(params_buf);
return QDF_STATUS_E_FAULT;
}
return QDF_STATUS_SUCCESS;
}
/**
* wmi_get_pdev_ep: Get wmi handle based on endpoint
* @soc: handle to wmi soc
@@ -2235,9 +2335,10 @@ static void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet)
if (exec_ctx == WMI_RX_WORK_CTX) {
wmi_process_fw_event_worker_thread_ctx
(wmi_handle, evt_buf);
} else if (exec_ctx > WMI_RX_WORK_CTX) {
wmi_process_fw_event_default_ctx
(wmi_handle, htc_packet, exec_ctx);
} else if (exec_ctx == WMI_RX_TASKLET_CTX) {
wmi_process_fw_event(wmi_handle, evt_buf);
} else if (exec_ctx == WMI_RX_SERIALIZER_CTX) {
wmi_process_fw_event_sched_thread_ctx(wmi_handle, evt_buf);
} else {
WMI_LOGE("Invalid event context %d", exec_ctx);
qdf_nbuf_free(evt_buf);