Browse Source

qcacmn: Fix incompatible function pointer assignment

Fix incompatible function pointer assignment.
Define a wrapper around mc timer callbacks to
make them compatible with standard scheduler
message callback function signatures.

Change-Id: I07829680d1758ccbd53e8b1fe10b0e30e100a2c6
CRs-Fixed: 3305719
sandhu 2 years ago
parent
commit
901120c066

+ 31 - 0
scheduler/inc/scheduler_api.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -96,6 +97,36 @@ struct scheduler_msg {
 #endif /* WLAN_SCHED_HISTORY_SIZE */
 };
 
+struct sched_qdf_mc_timer_cb_wrapper;
+
+/**
+ * scheduler_qdf_mc_timer_init() - initialize and fill callback and data
+ * @timer_callback: callback to timer
+ * @data: data pointer
+ *
+ * Return: return pointer to struct sched_qdf_mc_timer_cb_wrapper
+ */
+struct sched_qdf_mc_timer_cb_wrapper *scheduler_qdf_mc_timer_init(
+		qdf_mc_timer_callback_t timer_callback,
+		void *data);
+
+/**
+ * scheduler_qdf_mc_timer_callback_t_wrapper() - wrapper for mc timer callbacks
+ * @wrapper_ptr: wrapper ptr
+ *
+ * Return: return void ptr
+ */
+void *scheduler_qdf_mc_timer_deinit_return_data_ptr(
+		struct sched_qdf_mc_timer_cb_wrapper *wrapper_ptr);
+
+/**
+ * scheduler_qdf_mc_timer_callback_t_wrapper() - wrapper for mc timer callbacks
+ * @msg: message pointer
+ *
+ * Return: None
+ */
+QDF_STATUS scheduler_qdf_mc_timer_callback_t_wrapper(struct scheduler_msg *msg);
+
 /**
  * sched_history_print() - print scheduler history
  *

+ 83 - 18
scheduler/src/scheduler_api.c

@@ -23,6 +23,11 @@
 #include <qdf_module.h>
 #include <qdf_platform.h>
 
+struct sched_qdf_mc_timer_cb_wrapper {
+	qdf_mc_timer_callback_t timer_callback;
+	void *data;
+};
+
 QDF_STATUS scheduler_disable(void)
 {
 	struct scheduler_ctx *sched_ctx;
@@ -454,10 +459,68 @@ QDF_STATUS scheduler_os_if_mq_handler(struct scheduler_msg *msg)
 	return QDF_STATUS_SUCCESS;
 }
 
+struct sched_qdf_mc_timer_cb_wrapper *scheduler_qdf_mc_timer_init(
+		qdf_mc_timer_callback_t timer_callback,
+		void *data)
+{
+	struct sched_qdf_mc_timer_cb_wrapper *wrapper_ptr;
+
+	wrapper_ptr = qdf_mem_malloc(sizeof(*wrapper_ptr));
+	if (!wrapper_ptr)
+		return NULL;
+
+	wrapper_ptr->timer_callback = timer_callback;
+	wrapper_ptr->data = data;
+	return wrapper_ptr;
+}
+
+void *scheduler_qdf_mc_timer_deinit_return_data_ptr(
+		struct sched_qdf_mc_timer_cb_wrapper *wrapper_ptr)
+{
+	void *data_ptr;
+
+	if (!wrapper_ptr) {
+		sched_err("pointer to wrapper ptr is NULL");
+		return NULL;
+	}
+
+	data_ptr = wrapper_ptr->data;
+	qdf_mem_free(wrapper_ptr);
+	return data_ptr;
+}
+
+QDF_STATUS scheduler_qdf_mc_timer_callback_t_wrapper(struct scheduler_msg *msg)
+{
+	struct sched_qdf_mc_timer_cb_wrapper *mc_timer_wrapper;
+	qdf_mc_timer_callback_t timer_cb;
+
+	mc_timer_wrapper = msg->bodyptr;
+	if (!mc_timer_wrapper) {
+		sched_err("NULL mc_timer_wrapper from msg body");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	timer_cb = mc_timer_wrapper->timer_callback;
+
+	QDF_BUG(timer_cb);
+	if (!timer_cb)
+		goto sched_qdf_mc_timer_err;
+
+	timer_cb(mc_timer_wrapper->data);
+
+	qdf_mem_free(mc_timer_wrapper);
+	return QDF_STATUS_SUCCESS;
+
+sched_qdf_mc_timer_err:
+	sched_err("failed to get timer cb is NULL");
+	qdf_mem_free(mc_timer_wrapper);
+	return QDF_STATUS_E_FAILURE;
+}
+
 QDF_STATUS scheduler_timer_q_mq_handler(struct scheduler_msg *msg)
 {
 	struct scheduler_ctx *sched_ctx = scheduler_get_context();
-	qdf_mc_timer_callback_t timer_callback;
+	scheduler_msg_process_fn_t sched_mc_timer_callback;
 
 	QDF_BUG(msg);
 	if (!msg)
@@ -471,17 +534,12 @@ QDF_STATUS scheduler_timer_q_mq_handler(struct scheduler_msg *msg)
 	if (msg->reserved != SYS_MSG_COOKIE || msg->type != SYS_MSG_ID_MC_TIMER)
 		return sched_ctx->legacy_sys_handler(msg);
 
-	/* scheduler_msg_process_fn_t and qdf_mc_timer_callback_t have
-	 * different parameters and return type
-	 */
-	timer_callback = (qdf_mc_timer_callback_t)msg->callback;
-	QDF_BUG(timer_callback);
-	if (!timer_callback)
+	sched_mc_timer_callback = msg->callback;
+	QDF_BUG(sched_mc_timer_callback);
+	if (!sched_mc_timer_callback)
 		return QDF_STATUS_E_FAILURE;
 
-	timer_callback(msg->bodyptr);
-
-	return QDF_STATUS_SUCCESS;
+	return sched_mc_timer_callback(msg);
 }
 
 QDF_STATUS scheduler_mlme_mq_handler(struct scheduler_msg *msg)
@@ -587,8 +645,9 @@ QDF_STATUS scheduler_deregister_sys_legacy_handler(void)
 	return QDF_STATUS_SUCCESS;
 }
 
-static QDF_STATUS scheduler_msg_flush_noop(struct scheduler_msg *msg)
+static QDF_STATUS scheduler_msg_flush_mc(struct scheduler_msg *msg)
 {
+	scheduler_qdf_mc_timer_deinit_return_data_ptr(msg->bodyptr);
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -596,7 +655,7 @@ void scheduler_mc_timer_callback(qdf_mc_timer_t *timer)
 {
 	struct scheduler_msg msg = {0};
 	QDF_STATUS status;
-
+	struct sched_qdf_mc_timer_cb_wrapper *mc_timer_wrapper;
 	qdf_mc_timer_callback_t callback = NULL;
 	void *user_data = NULL;
 	QDF_TIMER_TYPE type = QDF_TIMER_TYPE_SW;
@@ -666,21 +725,27 @@ void scheduler_mc_timer_callback(qdf_mc_timer_t *timer)
 	if (!callback)
 		return;
 
+	mc_timer_wrapper = scheduler_qdf_mc_timer_init(callback, user_data);
+	if (!mc_timer_wrapper) {
+		sched_err("failed to allocate sched_qdf_mc_timer_cb_wrapper");
+		return;
+	}
+
 	/* serialize to scheduler controller thread */
 	msg.type = SYS_MSG_ID_MC_TIMER;
 	msg.reserved = SYS_MSG_COOKIE;
-	msg.callback = (scheduler_msg_process_fn_t)callback;
-	msg.bodyptr = user_data;
+	msg.callback = scheduler_qdf_mc_timer_callback_t_wrapper;
+	msg.bodyptr = mc_timer_wrapper;
 	msg.bodyval = 0;
-
-	/* bodyptr points to user data, do not free it during msg flush */
-	msg.flush_callback = scheduler_msg_flush_noop;
+	msg.flush_callback = scheduler_msg_flush_mc;
 
 	status = scheduler_post_message(QDF_MODULE_ID_SCHEDULER,
 					QDF_MODULE_ID_SCHEDULER,
 					QDF_MODULE_ID_SYS, &msg);
-	if (QDF_IS_STATUS_ERROR(status))
+	if (QDF_IS_STATUS_ERROR(status)) {
 		sched_err("Could not enqueue timer to timer queue");
+		qdf_mem_free(mc_timer_wrapper);
+	}
 }
 
 QDF_STATUS scheduler_get_queue_size(QDF_MODULE_ID qid, uint32_t *size)

+ 16 - 12
target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c

@@ -194,7 +194,7 @@ void target_if_vdev_mgr_rsp_timer_cb(void *arg)
 }
 
 #ifdef SERIALIZE_VDEV_RESP
-static QDF_STATUS target_if_vdev_mgr_rsp_flush_cb(struct scheduler_msg *msg)
+static QDF_STATUS target_if_vdev_mgr_rsp_flush_cb_mc(struct scheduler_msg *msg)
 {
 	struct vdev_response_timer *vdev_rsp;
 	struct wlan_objmgr_psoc *psoc;
@@ -204,7 +204,7 @@ static QDF_STATUS target_if_vdev_mgr_rsp_flush_cb(struct scheduler_msg *msg)
 		return QDF_STATUS_E_INVAL;
 	}
 
-	vdev_rsp = msg->bodyptr;
+	vdev_rsp = scheduler_qdf_mc_timer_deinit_return_data_ptr(msg->bodyptr);
 	if (!vdev_rsp) {
 		mlme_err("vdev response timer is NULL");
 		return QDF_STATUS_E_INVAL;
@@ -228,6 +228,7 @@ target_if_vdev_mgr_rsp_cb_mc_ctx(void *arg)
 	struct scheduler_msg msg = {0};
 	struct vdev_response_timer *vdev_rsp = arg;
 	struct wlan_objmgr_psoc *psoc;
+	struct sched_qdf_mc_timer_cb_wrapper *mc_timer_wrapper;
 
 	psoc = vdev_rsp->psoc;
 	if (!psoc) {
@@ -238,17 +239,19 @@ target_if_vdev_mgr_rsp_cb_mc_ctx(void *arg)
 	msg.type = SYS_MSG_ID_MC_TIMER;
 	msg.reserved = SYS_MSG_COOKIE;
 
-	/* msg.callback will explicitly cast back to qdf_mc_timer_callback_t
-	 * in scheduler_timer_q_mq_handler.
-	 * but in future we do not want to introduce more this kind of
-	 * typecast by properly using QDF MC timer for MCC from get go in
-	 * common code.
-	 */
-	msg.callback =
-		(scheduler_msg_process_fn_t)target_if_vdev_mgr_rsp_timer_cb;
-	msg.bodyptr = arg;
+	mc_timer_wrapper = scheduler_qdf_mc_timer_init(
+			target_if_vdev_mgr_rsp_timer_cb,
+			arg);
+
+	if (!mc_timer_wrapper) {
+		mlme_err("failed to allocate sched_qdf_mc_timer_cb_wrapper");
+		return;
+	}
+
+	msg.callback = scheduler_qdf_mc_timer_callback_t_wrapper;
+	msg.bodyptr = mc_timer_wrapper;
 	msg.bodyval = 0;
-	msg.flush_callback = target_if_vdev_mgr_rsp_flush_cb;
+	msg.flush_callback = target_if_vdev_mgr_rsp_flush_cb_mc;
 
 	if (scheduler_post_message(QDF_MODULE_ID_TARGET_IF,
 				   QDF_MODULE_ID_TARGET_IF,
@@ -257,6 +260,7 @@ target_if_vdev_mgr_rsp_cb_mc_ctx(void *arg)
 		return;
 
 	mlme_err("Could not enqueue timer to timer queue");
+	qdf_mem_free(mc_timer_wrapper);
 	if (psoc)
 		wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID);
 }

+ 23 - 12
umac/cmn_services/serialization/src/wlan_serialization_internal.c

@@ -594,9 +594,15 @@ free:
 	qdf_mem_free(timeout_cmd);
 }
 
-static QDF_STATUS wlan_serialization_mc_flush_noop(struct scheduler_msg *msg)
+static QDF_STATUS wlan_serialization_mc_flush(struct scheduler_msg *msg)
 {
-	struct wlan_serialization_command *timeout_cmd = msg->bodyptr;
+	struct wlan_serialization_command *timeout_cmd =
+		scheduler_qdf_mc_timer_deinit_return_data_ptr(msg->bodyptr);
+
+	if (!timeout_cmd) {
+		ser_err("Error failed to release reference for vdev objmgr");
+		return QDF_STATUS_E_FAILURE;
+	}
 
 	wlan_objmgr_vdev_release_ref(timeout_cmd->vdev, WLAN_SERIALIZATION_ID);
 	qdf_mem_free(timeout_cmd);
@@ -609,6 +615,7 @@ wlan_serialization_timer_cb_mc_ctx(struct wlan_serialization_command *cmd)
 {
 	struct scheduler_msg msg = {0};
 	struct wlan_serialization_command *timeout_cmd;
+	struct sched_qdf_mc_timer_cb_wrapper *mc_timer_wrapper;
 	QDF_STATUS status;
 
 	msg.type = SYS_MSG_ID_MC_TIMER;
@@ -629,17 +636,19 @@ wlan_serialization_timer_cb_mc_ctx(struct wlan_serialization_command *cmd)
 
 	qdf_mem_copy(timeout_cmd, cmd, sizeof(*timeout_cmd));
 
-	/* msg.callback will explicitly cast back to qdf_mc_timer_callback_t
-	 * in scheduler_timer_q_mq_handler.
-	 * but in future we do not want to introduce more this kind of
-	 * typecast by properly using QDF MC timer for MCC from get go in
-	 * common code.
-	 */
-	msg.callback =
-		(scheduler_msg_process_fn_t)wlan_serialization_generic_timer_cb;
-	msg.bodyptr = timeout_cmd;
+	mc_timer_wrapper =
+		scheduler_qdf_mc_timer_init(wlan_serialization_generic_timer_cb,
+					    timeout_cmd);
+
+	if (!mc_timer_wrapper) {
+		ser_err("failed to allocate sched_qdf_mc_timer_cb_wrapper");
+		goto failed_mc_allocation;
+	}
+
+	msg.callback = scheduler_qdf_mc_timer_callback_t_wrapper;
+	msg.bodyptr = mc_timer_wrapper;
 	msg.bodyval = 0;
-	msg.flush_callback = wlan_serialization_mc_flush_noop;
+	msg.flush_callback = wlan_serialization_mc_flush;
 
 	if (scheduler_post_message(QDF_MODULE_ID_SERIALIZATION,
 				   QDF_MODULE_ID_SERIALIZATION,
@@ -648,6 +657,8 @@ wlan_serialization_timer_cb_mc_ctx(struct wlan_serialization_command *cmd)
 		return;
 
 	ser_err("Could not enqueue timer to timer queue");
+	qdf_mem_free(mc_timer_wrapper);
+failed_mc_allocation:
 	/* free mem and release ref on error */
 	wlan_objmgr_vdev_release_ref(timeout_cmd->vdev, WLAN_SERIALIZATION_ID);
 	qdf_mem_free(timeout_cmd);