Эх сурвалжийг харах

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
Sandeep Puligilla 5 жил өмнө
parent
commit
9304a97961

+ 13 - 2
wmi/inc/wmi_unified_api.h

@@ -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_ */

+ 11 - 0
wmi/inc/wmi_unified_priv.h

@@ -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

+ 128 - 27
wmi/src/wmi_unified.c

@@ -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);