瀏覽代碼

qcacmn: implement mlo manager APIs for mlo link set active cmd

Add interface for sending mlo link set active cmd and
register the response handler.

Change-Id: Icd7cf3294cddec1aa4a417e29a22fcd6fbea0dfb
CRs-Fixed: 3036846
Yu Wang 3 年之前
父節點
當前提交
f13b79ec7f

+ 29 - 0
init_deinit/dispatcher/src/dispatcher_init_deinit.c

@@ -962,6 +962,28 @@ dispatcher_coex_psoc_close(struct wlan_objmgr_psoc *psoc)
 }
 #endif /* FEATURE_COEX */
 
+#ifdef WLAN_FEATURE_11BE_MLO
+static QDF_STATUS mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_mlo_mgr_psoc_enable(psoc);
+}
+
+static QDF_STATUS mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_mlo_mgr_psoc_disable(psoc);
+}
+#else
+static QDF_STATUS mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static QDF_STATUS mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 QDF_STATUS dispatcher_init(void)
 {
 	if (QDF_STATUS_SUCCESS != wlan_objmgr_global_obj_init())
@@ -1343,8 +1365,13 @@ QDF_STATUS dispatcher_psoc_enable(struct wlan_objmgr_psoc *psoc)
 	if (QDF_STATUS_SUCCESS != wlan_mgmt_txrx_psoc_enable(psoc))
 		goto mgmt_txrx_psoc_enable_fail;
 
+	if (QDF_STATUS_SUCCESS != mlo_mgr_psoc_enable(psoc))
+		goto mlo_mgr_psoc_enable_fail;
+
 	return QDF_STATUS_SUCCESS;
 
+mlo_mgr_psoc_enable_fail:
+	wlan_mgmt_txrx_psoc_disable(psoc);
 mgmt_txrx_psoc_enable_fail:
 	spectral_psoc_disable(psoc);
 spectral_psoc_enable_fail:
@@ -1380,6 +1407,8 @@ QDF_STATUS dispatcher_psoc_disable(struct wlan_objmgr_psoc *psoc)
 {
 	QDF_STATUS status;
 
+	QDF_BUG(QDF_STATUS_SUCCESS == mlo_mgr_psoc_disable(psoc));
+
 	QDF_BUG(QDF_STATUS_SUCCESS == wlan_mgmt_txrx_psoc_disable(psoc));
 
 	QDF_BUG(QDF_STATUS_SUCCESS == wlan_mlme_psoc_disable(psoc));

+ 2 - 2
target_if/mlo_mgr/src/target_if_mlo_mgr.c

@@ -196,9 +196,9 @@ target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	mlo_tx_ops->mlo_attach =
+	mlo_tx_ops->register_events =
 		target_if_mlo_register_event_handler;
-	mlo_tx_ops->mlo_detach =
+	mlo_tx_ops->unregister_events =
 		target_if_mlo_unregister_event_handler;
 	mlo_tx_ops->link_set_active = target_if_mlo_link_set_active;
 

+ 3 - 0
umac/cmn_services/serialization/inc/wlan_serialization_api.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021 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
@@ -192,6 +193,7 @@ typedef QDF_STATUS (*wlan_ser_umac_cmd_cb)(void *umac_cmd);
  * @WLAN_SER_CMD_PDEV_CSA_RESTART: Cmd to CSA restart all AP VDEVs of a PDEV
  * @WLAN_SER_CMD_GET_DISCONNECT_STATS: Cmd to get peer stats on disconnection
  * @WLAN_SER_CMD_VDEV_ROAM: Cmd to roam a STA VDEV
+ * @WLAN_SER_CMD_SET_MLO_LINK: Cmd to force mlo link active/inactive
  */
 enum wlan_serialization_cmd_type {
 	/* all scan command before non-scan */
@@ -225,6 +227,7 @@ enum wlan_serialization_cmd_type {
 	WLAN_SER_CMD_PDEV_CSA_RESTART,
 	WLAN_SER_CMD_GET_DISCONNECT_STATS,
 	WLAN_SER_CMD_VDEV_ROAM,
+	WLAN_SER_CMD_SET_MLO_LINK,
 	WLAN_SER_CMD_MAX
 };
 

+ 4 - 4
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -1268,13 +1268,13 @@ struct wlan_lmac_if_son_rx_ops {
 #ifdef WLAN_FEATURE_11BE_MLO
 /**
  * struct wlan_lmac_if_mlo_tx_ops - south bound tx function pointers for mlo
- * @mlo_attach: function to register event handlers with FW
- * @mlo_detach: function to de-register event handlers with FW
+ * @register_events: function to register event handlers with FW
+ * @unregister_events: function to de-register event handlers with FW
  * @link_set_active: function to send mlo link set active command to FW
  */
 struct wlan_lmac_if_mlo_tx_ops {
-	QDF_STATUS (*mlo_attach)(struct wlan_objmgr_psoc *psoc);
-	QDF_STATUS (*mlo_detach)(struct wlan_objmgr_psoc *psoc);
+	QDF_STATUS (*register_events)(struct wlan_objmgr_psoc *psoc);
+	QDF_STATUS (*unregister_events)(struct wlan_objmgr_psoc *psoc);
 	QDF_STATUS (*link_set_active)(struct wlan_objmgr_psoc *psoc,
 		struct mlo_link_set_active_param *param);
 };

+ 2 - 0
umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c

@@ -786,6 +786,8 @@ static void
 wlan_lmac_if_mlo_mgr_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
 {
 	/* register handler for received mlo related events */
+	rx_ops->mlo_rx_ops.process_link_set_active_resp =
+		mlo_process_link_set_active_resp;
 }
 #else
 static void

+ 20 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_cmn.h

@@ -313,4 +313,24 @@ uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev)
 }
 #endif/*WLAN_MLO_MULTI_CHIP*/
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * mlo_process_link_set_active_resp() - handler for mlo link set active response
+ * @psoc: psoc pointer
+ * @event: pointer to mlo link set active response
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+mlo_process_link_set_active_resp(struct wlan_objmgr_psoc *psoc,
+				 struct mlo_link_set_active_resp *event);
+
+/**
+ * mlo_ser_set_link_req() - add mlo link set active cmd to serialization
+ * @req: mlo link set active request
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS mlo_ser_set_link_req(struct mlo_link_set_active_req *req);
+#endif
 #endif

+ 20 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_main.h

@@ -28,6 +28,7 @@
 
 #ifdef WLAN_FEATURE_11BE_MLO
 #include <wlan_mlo_mgr_public_structs.h>
+
 /**
  * wlan_mlo_mgr_init() - Initialize the MLO data structures
  *
@@ -628,6 +629,25 @@ void copied_conn_req_lock_release(struct wlan_mlo_sta *sta_ctx)
 }
 #endif /* WLAN_MLO_USE_SPINLOCK */
 
+/**
+ * wlan_mlo_mgr_psoc_enable() - MLO psoc enable handler
+ * @psoc: psoc pointer
+ *
+ * API to execute operations on psoc enable
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_mlo_mgr_psoc_disable() - MLO psoc disable handler
+ * @psoc: psoc pointer
+ *
+ * API to execute operations on psoc disable
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc);
 #else
 static inline QDF_STATUS wlan_mlo_mgr_init(void)
 {

+ 23 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -510,4 +510,27 @@ struct mlo_link_set_active_param {
 	struct mlo_link_num_param link_num[MLO_LINK_NUM_SZ];
 	uint32_t vdev_bitmap[MLO_VDEV_BITMAP_SZ];
 };
+
+/*
+ * struct mlo_link_set_active_ctx - Context for MLO link set active request
+ * @vdev: pointer to vdev on which the request issued
+ * @cb: callback function for MLO link set active request
+ * @cb_arg: callback context
+ */
+struct mlo_link_set_active_ctx {
+	struct wlan_objmgr_vdev *vdev;
+	void (*set_mlo_link_cb)(struct wlan_objmgr_vdev *vdev, void *arg,
+				struct mlo_link_set_active_resp *evt);
+	void *cb_arg;
+};
+
+/*
+ * struct mlo_link_set_active_req - MLO link set active request
+ * @ctx: context for MLO link set active request
+ * @param: MLO link set active params
+ */
+struct mlo_link_set_active_req {
+	struct mlo_link_set_active_ctx ctx;
+	struct mlo_link_set_active_param param;
+};
 #endif

+ 215 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_cmn.c

@@ -23,6 +23,8 @@
 #ifdef WLAN_MLO_MULTI_CHIP
 #include "wlan_lmac_if_def.h"
 #endif
+#include "wlan_serialization_api.h"
+#include <target_if_mlo_mgr.h>
 
 void mlo_get_link_information(struct qdf_mac_addr *mld_addr,
 			      struct mlo_link_info *info)
@@ -357,3 +359,216 @@ void mlo_get_ml_vdev_list(struct wlan_objmgr_vdev *vdev,
 	}
 	mlo_dev_lock_release(dev_ctx);
 }
+
+/**
+ * mlo_link_set_active() - send MLO link set active command
+ * @psoc: PSOC object
+ * @param: MLO link set active params
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mlo_link_set_active(struct wlan_objmgr_psoc *psoc,
+		    struct mlo_link_set_active_param *param)
+{
+	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
+
+	if (!psoc) {
+		mlo_err("psoc is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
+	if (!mlo_tx_ops) {
+		mlo_err("tx_ops is null!");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!mlo_tx_ops->link_set_active) {
+		mlo_err("link_set_active function is null!");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	return mlo_tx_ops->link_set_active(psoc, param);
+}
+
+/**
+ * mlo_release_ser_link_set_active_cmd() - relases serialization command for
+ *  forcing MLO link active/inactive
+ * @vdev: Object manager vdev
+ *
+ * Return: None
+ */
+static void
+mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_serialization_queued_cmd_info cmd = {0};
+
+	cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK;
+	cmd.requestor = WLAN_UMAC_COMP_MLO_MGR;
+	cmd.cmd_id = 0;
+	cmd.vdev = vdev;
+
+	mlo_debug("release serialization command");
+	wlan_serialization_remove_cmd(&cmd);
+}
+
+/**
+ * mlo_link_set_active_resp_vdev_handler() - vdev handler for mlo link set
+ * active response event.
+ * @psoc: psoc object
+ * @obj: vdev object
+ * @arg: mlo link set active response
+ *
+ * Return: None
+ */
+static void
+mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc *psoc,
+				      void *obj, void *arg)
+{
+	struct mlo_link_set_active_req *req;
+	struct wlan_objmgr_vdev *vdev = obj;
+	struct mlo_link_set_active_resp *event = arg;
+
+	req = wlan_serialization_get_active_cmd(wlan_vdev_get_psoc(vdev),
+						wlan_vdev_get_id(vdev),
+						WLAN_SER_CMD_SET_MLO_LINK);
+	if (!req)
+		return;
+
+	if (req->ctx.set_mlo_link_cb)
+		req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, event);
+
+	mlo_release_ser_link_set_active_cmd(vdev);
+}
+
+QDF_STATUS
+mlo_process_link_set_active_resp(struct wlan_objmgr_psoc *psoc,
+				 struct mlo_link_set_active_resp *event)
+{
+	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
+				     mlo_link_set_active_resp_vdev_handler,
+				     event, true, WLAN_MLO_MGR_ID);
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * mlo_ser_set_link_cb() - Serialization callback function
+ * @cmd: Serialization command info
+ * @reason: Serialization reason for callback execution
+ *
+ * Return: Status of callback execution
+ */
+static QDF_STATUS
+mlo_ser_set_link_cb(struct wlan_serialization_command *cmd,
+		    enum wlan_serialization_cb_reason reason)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_psoc *psoc;
+	struct mlo_link_set_active_req *req;
+	struct mlo_mgr_context *mlo_ctx;
+
+	if (!cmd || !cmd->vdev)
+		return QDF_STATUS_E_FAILURE;
+
+	mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	if (!mlo_ctx)
+		return QDF_STATUS_E_FAILURE;
+
+	psoc = wlan_vdev_get_psoc(cmd->vdev);
+	if (!psoc) {
+		mlo_err("psoc is NULL, reason: %d", reason);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	req = cmd->umac_cmd;
+	if (!req)
+		return QDF_STATUS_E_INVAL;
+
+	vdev = cmd->vdev;
+	switch (reason) {
+	case WLAN_SER_CB_ACTIVATE_CMD:
+		status = mlo_link_set_active(psoc, &req->param);
+		break;
+	case WLAN_SER_CB_CANCEL_CMD:
+	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
+		mlo_err("vdev %d command not execute: %d",
+			wlan_vdev_get_id(vdev), reason);
+		if (req->ctx.set_mlo_link_cb)
+			req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, NULL);
+		break;
+	case WLAN_SER_CB_RELEASE_MEM_CMD:
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
+		qdf_mem_free(req);
+		break;
+	default:
+		QDF_ASSERT(0);
+		status = QDF_STATUS_E_INVAL;
+		break;
+	}
+
+	return status;
+}
+
+#define MLO_SER_CMD_TIMEOUT_MS 5000
+QDF_STATUS mlo_ser_set_link_req(struct mlo_link_set_active_req *req)
+{
+	struct wlan_serialization_command cmd = {0, };
+	enum wlan_serialization_status ser_cmd_status;
+	QDF_STATUS status;
+	void *umac_cmd;
+	struct wlan_objmgr_vdev *vdev;
+
+	if (!req)
+		return QDF_STATUS_E_INVAL;
+
+	vdev = req->ctx.vdev;
+	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLO_MGR_ID);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mlo_err("vdev %d unable to get reference",
+			wlan_vdev_get_id(vdev));
+		return status;
+	}
+
+	umac_cmd = qdf_mem_malloc(sizeof(*req));
+	if (!umac_cmd) {
+		status = QDF_STATUS_E_NOMEM;
+		goto out;
+	}
+	qdf_mem_copy(umac_cmd, req, sizeof(*req));
+
+	cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK;
+	cmd.cmd_id = 0;
+	cmd.cmd_cb = mlo_ser_set_link_cb;
+	cmd.source = WLAN_UMAC_COMP_MLO_MGR;
+	cmd.is_high_priority = false;
+	cmd.cmd_timeout_duration = MLO_SER_CMD_TIMEOUT_MS;
+	cmd.vdev = vdev;
+	cmd.is_blocking = true;
+	cmd.umac_cmd = umac_cmd;
+
+	ser_cmd_status = wlan_serialization_request(&cmd);
+	switch (ser_cmd_status) {
+	case WLAN_SER_CMD_PENDING:
+		/* command moved to pending list.Do nothing */
+		break;
+	case WLAN_SER_CMD_ACTIVE:
+		/* command moved to active list. Do nothing */
+		break;
+	default:
+		mlo_err("vdev %d ser cmd status %d",
+			wlan_vdev_get_id(vdev), ser_cmd_status);
+		status = QDF_STATUS_E_FAILURE;
+	}
+
+out:
+	if (QDF_IS_STATUS_SUCCESS(status))
+		return status;
+
+	if (umac_cmd)
+		qdf_mem_free(umac_cmd);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
+
+	return status;
+}

+ 47 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_main.c

@@ -27,6 +27,7 @@
 #include <wlan_mlo_mgr_peer.h>
 #include <wlan_cm_public_struct.h>
 #include "wlan_mlo_mgr_msgq.h"
+#include <target_if_mlo_mgr.h>
 
 static void mlo_global_ctx_deinit(void)
 {
@@ -75,6 +76,52 @@ static void mlo_global_ctx_init(void)
 	mlo_msgq_init();
 }
 
+QDF_STATUS wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
+
+	if (!psoc) {
+		mlo_err("psoc is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
+	if (!mlo_tx_ops) {
+		mlo_err("tx_ops is null!");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!mlo_tx_ops->register_events) {
+		mlo_err("register_events function is null!");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	return mlo_tx_ops->register_events(psoc);
+}
+
+QDF_STATUS wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
+
+	if (!psoc) {
+		mlo_err("psoc is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
+	if (!mlo_tx_ops) {
+		mlo_err("tx_ops is null!");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!mlo_tx_ops->unregister_events) {
+		mlo_err("unregister_events function is null!");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	return mlo_tx_ops->unregister_events(psoc);
+}
+
 QDF_STATUS wlan_mlo_mgr_init(void)
 {
 	QDF_STATUS status;