ソースを参照

qcacmn: Register MLO get link state event handlers

Register and unregister the MLO get link state WMI event handler.

Change-Id: I7ac0a20949cc435907e433c279f14fd792415824
CRs-Fixed: 3432102
Aasir Rasheed 2 年 前
コミット
ca023bedc9

+ 17 - 1
target_if/mlo_mgr/inc/target_if_mlo_mgr.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 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 above
@@ -108,6 +108,22 @@ target_if_extract_mlo_link_removal_info_mgmt_rx(
 		void *evt_buf,
 		struct mgmt_rx_event_params *rx_event);
 
+/**
+ * target_if_mlo_register_mlo_link_state_info_event -
+ *  Register mlo link state event
+ * @wmi_handle: WMI handle
+ */
+void target_if_mlo_register_mlo_link_state_info_event(
+		struct wmi_unified *wmi_handle);
+
+/**
+ * target_if_mlo_unregister_mlo_link_state_info_event -
+ *  Unregister mlo link state event
+ * @wmi_handle: WMI handle
+ */
+void target_if_mlo_unregister_mlo_link_state_info_event(
+		struct wmi_unified *wmi_handle);
+
 /**
  * target_if_mlo_register_vdev_tid_to_link_map_event() - Register T2LM event
  * handler.

+ 95 - 1
target_if/mlo_mgr/src/target_if_mlo_mgr.c

@@ -236,6 +236,7 @@ target_if_mlo_register_event_handler(struct wlan_objmgr_psoc *psoc)
 	}
 
 	target_if_mlo_register_vdev_tid_to_link_map_event(wmi_handle);
+	target_if_mlo_register_mlo_link_state_info_event(wmi_handle);
 
 	return status;
 }
@@ -270,6 +271,7 @@ target_if_mlo_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
 				     wmi_mlo_link_removal_eventid);
 
 	target_if_mlo_unregister_vdev_tid_to_link_map_event(wmi_handle);
+	target_if_mlo_unregister_mlo_link_state_info_event(wmi_handle);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -365,6 +367,65 @@ void target_if_mlo_unregister_vdev_tid_to_link_map_event(
 			wmi_handle, wmi_mlo_ap_vdev_tid_to_link_map_eventid);
 }
 
+static int target_if_mlo_link_state_info_event_handler(
+		ol_scn_t scn, uint8_t *event_buff, uint32_t len)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wmi_unified *wmi_handle;
+	QDF_STATUS status;
+	struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops;
+	struct ml_link_state_info_event event = {0};
+
+	if (!event_buff) {
+		target_if_err("Received NULL event ptr from FW");
+		return -EINVAL;
+	}
+
+	psoc = target_if_get_psoc_from_scn_hdl(scn);
+	if (!psoc) {
+		target_if_err("PSOC is NULL");
+		return -EINVAL;
+	}
+
+	mlo_rx_ops = target_if_mlo_get_rx_ops(psoc);
+	if (!mlo_rx_ops || !mlo_rx_ops->process_mlo_link_state_info_event) {
+		target_if_err("callback not registered");
+		return -EINVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		target_if_err("wmi_handle is null");
+		return -EINVAL;
+	}
+
+	if (wmi_extract_mlo_link_state_info_event(wmi_handle, event_buff,
+						  &event)) {
+		target_if_err("Failed to extract link status event");
+		return -EINVAL;
+	}
+
+	status = mlo_rx_ops->process_mlo_link_state_info_event(psoc, &event);
+	return qdf_status_to_os_return(status);
+}
+
+void target_if_mlo_register_mlo_link_state_info_event(
+		struct wmi_unified *wmi_handle)
+{
+	wmi_unified_register_event_handler(
+		wmi_handle, wmi_mlo_link_state_info_eventid,
+		target_if_mlo_link_state_info_event_handler,
+		WMI_RX_EXECUTION_CTX);
+}
+
+void  target_if_mlo_unregister_mlo_link_state_info_event(
+		struct wmi_unified *wmi_handle)
+{
+	wmi_unified_unregister_event_handler(
+			wmi_handle,
+			wmi_mlo_link_state_info_eventid);
+}
+
 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
 /**
  * target_if_fill_provisioned_links() - API to fill the provisioned links
@@ -451,6 +512,38 @@ target_if_mlo_send_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev,
 	return status;
 }
 
+static QDF_STATUS
+target_if_request_ml_link_state_info(struct wlan_objmgr_psoc *psoc,
+				     struct mlo_link_state_cmd_params *cmd)
+{
+	struct wmi_unified *wmi_handle = NULL;
+	struct wmi_host_link_state_params params = {0};
+	QDF_STATUS status;
+
+	if (!psoc) {
+		target_if_err("null pdev");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		target_if_err("null wmi handle");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!cmd) {
+		target_if_err("cmd is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	params.vdev_id = cmd->vdev_id;
+	qdf_mem_copy(params.mld_mac, cmd->mld_mac,
+		     QDF_MAC_ADDR_SIZE);
+
+	status = wmi_send_mlo_link_state_request_cmd(wmi_handle, &params);
+	return status;
+}
+
 QDF_STATUS target_if_mlo_send_link_removal_cmd(
 		struct wlan_objmgr_psoc *psoc,
 		const struct mlo_link_removal_cmd_params *param)
@@ -502,7 +595,8 @@ target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
 	mlo_tx_ops->send_tid_to_link_mapping =
 		target_if_mlo_send_tid_to_link_mapping;
 	mlo_tx_ops->send_link_removal_cmd = target_if_mlo_send_link_removal_cmd;
-
+	mlo_tx_ops->request_link_state_info_cmd =
+		target_if_request_ml_link_state_info;
 	return QDF_STATUS_SUCCESS;
 }
 

+ 9 - 0
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -1500,6 +1500,7 @@ struct wlan_lmac_if_son_rx_ops {
  * @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
+ * @request_link_state_info_cmd: function pointer to send link state info
  * @shmem_local_ops: operations specific to WLAN_MLO_GLOBAL_SHMEM_SUPPORT
  * @send_tid_to_link_mapping: function to send T2LM command to FW
  * @send_link_removal_cmd: function to send MLO link removal command to FW
@@ -1509,6 +1510,10 @@ struct wlan_lmac_if_mlo_tx_ops {
 	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);
+	QDF_STATUS (*request_link_state_info_cmd)(
+		struct wlan_objmgr_psoc *psoc,
+		struct mlo_link_state_cmd_params *param);
+
 #ifdef WLAN_MLO_GLOBAL_SHMEM_SUPPORT
 	struct wlan_lmac_if_global_shmem_local_ops shmem_local_ops;
 #endif
@@ -1524,6 +1529,7 @@ struct wlan_lmac_if_mlo_tx_ops {
  * @process_link_set_active_resp: function pointer to rx FW events
  * @process_mlo_vdev_tid_to_link_map_event:  function pointer to rx T2LM event
  * @mlo_link_removal_handler: function pointer for MLO link removal handler
+ * @process_mlo_link_state_info_event: function pointer for mlo link state
  */
 struct wlan_lmac_if_mlo_rx_ops {
 	QDF_STATUS
@@ -1535,6 +1541,9 @@ struct wlan_lmac_if_mlo_rx_ops {
 	QDF_STATUS (*mlo_link_removal_handler)(
 			struct wlan_objmgr_psoc *psoc,
 			struct mlo_link_removal_evt_params *evt_params);
+	QDF_STATUS (*process_mlo_link_state_info_event)(
+			struct wlan_objmgr_psoc *psoc,
+			struct ml_link_state_info_event *event);
 };
 #endif
 

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

@@ -976,6 +976,9 @@ wlan_lmac_if_mlo_mgr_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
 		mlo_process_link_set_active_resp;
 	rx_ops->mlo_rx_ops.process_mlo_vdev_tid_to_link_map_event =
 		wlan_mlo_vdev_tid_to_link_map_event;
+	rx_ops->mlo_rx_ops.process_mlo_link_state_info_event =
+		wlan_handle_ml_link_state_info_event;
+
 }
 #else
 static void

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

@@ -550,5 +550,35 @@ QDF_STATUS
 mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc *psoc,
 			    struct mlo_stats_vdev_params *ml_vdev_info,
 			    uint8_t vdev_id);
+
+/**
+ * typedef get_ml_link_state_cb() - api to handle link state callback
+ * @ev: pointer to event parameter of structure
+ * @cookie: a cookie for request context
+ */
+typedef void (*get_ml_link_state_cb)(struct ml_link_state_info_event *ev,
+				     void *cookie);
+/**
+ * wlan_handle_ml_link_state_info_event() - Event handler for ml link state
+ * @psoc: psoc handler
+ * @event: pointer to event parameter of structure
+ */
+QDF_STATUS
+wlan_handle_ml_link_state_info_event(struct wlan_objmgr_psoc *psoc,
+				     struct ml_link_state_info_event *event);
+/**
+ * mlo_get_link_state_register_resp_cb() - Register link state callback
+ * @vdev: vdev handler
+ * @req: pointer to request parameter of structure
+ */
+QDF_STATUS
+mlo_get_link_state_register_resp_cb(struct wlan_objmgr_vdev *vdev,
+				    struct ml_link_state_cmd_info *req);
+/**
+ * ml_post_get_link_state_msg() - Post get link state msg
+ * @vdev: vdev handler
+ */
+QDF_STATUS ml_post_get_link_state_msg(struct wlan_objmgr_vdev *vdev);
+
 #endif
 #endif

+ 63 - 1
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -252,6 +252,64 @@ struct wlan_mlo_key_mgmt {
 	bool keys_saved;
 };
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * struct mlo_link_state_cmd_params - MLO link state params
+ * @vdev_id: Vdev id
+ * @mld_mac: mld mac address
+ */
+struct mlo_link_state_cmd_params {
+	uint8_t vdev_id;
+	uint8_t mld_mac[QDF_MAC_ADDR_SIZE];
+};
+
+/**
+ * struct ml_link_info - ml link information
+ * @vdev_id: vdev id for this link
+ * @link_id: link id defined as in 802.11 BE spec.
+ * @link_status: active 0, inactive 1
+ * @reserved: reserved bits
+ * @chan_freq: Channel frequency in MHz
+ */
+struct ml_link_info {
+	uint32_t vdev_id:8,
+		 link_id:8,
+		 link_status:2,
+		 reserved:14;
+	uint32_t chan_freq;
+};
+
+/**
+ * struct ml_link_state_info_event - ML link state info response
+ * @status: to indicate the status for ml link info
+ * @hw_mode_index: current hardware mode index
+ * @link_info: link information
+ * @num_mlo_vdev_link_info: number of mlo vdev link info
+ * @vdev_id: vdev_id
+ * @mldaddr: mld addr
+ */
+struct ml_link_state_info_event {
+	uint32_t status;
+	uint32_t hw_mode_index;
+	struct ml_link_info link_info[WLAN_MLO_MAX_VDEVS];
+	uint16_t num_mlo_vdev_link_info;
+	uint8_t vdev_id;
+	struct qdf_mac_addr mldaddr;
+};
+
+/**
+ * struct ml_link_state_cmd_info - ml link state command info
+ * @request_cookie: request cookie
+ * @ml_link_state_resp_cb: callback function to handle response
+ * @ml_link_state_req_context: request context
+ */
+struct ml_link_state_cmd_info {
+	void *request_cookie;
+	void (*ml_link_state_resp_cb)(struct ml_link_state_info_event *ev,
+				      void *cookie);
+	void *ml_link_state_req_context;
+};
+#endif
 /**
  * struct mlo_sta_csa_params - CSA request parameters in mlo mgr
  * @csa_param: csa parameters
@@ -314,7 +372,7 @@ struct mlo_sta_quiet_status {
  * @copied_reassoc_rsp: Reassoc response copied from assoc link roam handling
  *                      to re-use while link connect in case of deferred/need
  *                      basis link connect (e.g. MLO OWE roaming).
- *
+ * @ml_link_state: ml link state command info param
  * NB: not using kernel-doc format since the kernel-doc script doesn't
  *     handle the qdf_bitmap() macro
  */
@@ -337,6 +395,9 @@ struct wlan_mlo_sta {
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	struct wlan_cm_connect_resp *copied_reassoc_rsp;
 #endif
+#ifdef WLAN_FEATURE_11BE_MLO
+	struct ml_link_state_cmd_info ml_link_state;
+#endif
 };
 
 /*
@@ -1006,4 +1067,5 @@ struct mgmt_rx_mlo_link_removal_info {
 	uint8_t hw_link_id;
 	uint16_t tbtt_count;
 };
+
 #endif

+ 21 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_sta.h

@@ -722,6 +722,18 @@ mlo_allocate_and_copy_ies(struct wlan_cm_connect_req *target,
  */
 void
 mlo_free_connect_ies(struct wlan_cm_connect_req *connect_req);
+
+/**
+ * mlo_get_link_state_context() - get ml link context
+ * @psoc: psoc handler
+ * @resp_cb: api to handle link state callback
+ * @context: response context
+ * @vdev_id: vdev id
+ */
+QDF_STATUS
+mlo_get_link_state_context(struct wlan_objmgr_psoc *psoc,
+			   get_ml_link_state_cb *resp_cb,
+			   void **context, uint8_t vdev_id);
 #else
 static inline
 QDF_STATUS mlo_connect(struct wlan_objmgr_vdev *vdev,
@@ -903,5 +915,14 @@ void mlo_process_ml_reconfig_ie(struct wlan_objmgr_vdev *vdev,
 				uint8_t *ml_ie, qdf_size_t ml_ie_len,
 				struct mlo_partner_info *partner_info)
 { }
+#ifdef WLAN_FEATURE_11BE_MLO
+static inline QDF_STATUS
+mlo_get_link_state_context(struct wlan_objmgr_psoc *psoc,
+			   get_ml_link_state_cb *resp_cb,
+			   void **context, uint8_t vdev_id)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #endif
 #endif

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

@@ -20,6 +20,7 @@
  */
 #include "wlan_mlo_mgr_cmn.h"
 #include "wlan_mlo_mgr_main.h"
+#include "wlan_mlo_mgr_sta.h"
 #ifdef WLAN_MLO_MULTI_CHIP
 #include "wlan_lmac_if_def.h"
 #endif
@@ -796,3 +797,139 @@ mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc *psoc,
 
 	return QDF_STATUS_SUCCESS;
 }
+
+static void ml_extract_link_state(struct wlan_objmgr_psoc *psoc,
+				  struct ml_link_state_info_event *event)
+{
+	QDF_STATUS status;
+	get_ml_link_state_cb resp_cb;
+	void *context;
+	uint8_t vdev_id;
+
+	vdev_id = event->vdev_id;
+
+	status = mlo_get_link_state_context(psoc,
+					    &resp_cb, &context, vdev_id);
+
+	if (resp_cb)
+		resp_cb(event, context);
+}
+
+QDF_STATUS
+wlan_handle_ml_link_state_info_event(struct wlan_objmgr_psoc *psoc,
+				     struct ml_link_state_info_event *event)
+{
+	if (!event)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	ml_extract_link_state(psoc, event);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static QDF_STATUS ml_get_link_state_req_cb(struct scheduler_msg *msg)
+{
+	struct wlan_objmgr_vdev *vdev = msg->bodyptr;
+	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
+	struct mlo_link_state_cmd_params cmd = {0};
+	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
+	struct wlan_objmgr_psoc *psoc;
+	int status = 0;
+
+	if (!vdev) {
+		mlo_err("null input vdev");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	psoc = wlan_vdev_get_psoc(vdev);
+
+	if (!psoc) {
+		mlo_err("null psoc");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
+
+	if (!mlo_tx_ops) {
+		mlo_err("tx_ops is null!");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
+		mlo_err("vdev is not MLO vdev");
+		return status;
+	}
+
+	mlo_dev_ctx = vdev->mlo_dev_ctx;
+	cmd.vdev_id = vdev->vdev_objmgr.vdev_id;
+	qdf_mem_copy(&cmd.mld_mac[0], &mlo_dev_ctx->mld_addr,
+		     QDF_MAC_ADDR_SIZE);
+
+	if (!mlo_tx_ops->request_link_state_info_cmd) {
+		mlo_err("handler is not registered");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	status = mlo_tx_ops->request_link_state_info_cmd(psoc, &cmd);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		mlo_err("failed to send ml link info command to FW");
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+mlo_get_link_state_register_resp_cb(struct wlan_objmgr_vdev *vdev,
+				    struct ml_link_state_cmd_info *req)
+{
+	struct wlan_mlo_dev_context *mlo_ctx;
+	struct wlan_mlo_sta *sta_ctx = NULL;
+
+	if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
+		return QDF_STATUS_E_NULL_VALUE;
+	mlo_ctx = vdev->mlo_dev_ctx;
+
+	if (!mlo_ctx) {
+		mlo_err("null mlo_dev_ctx");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	sta_ctx = mlo_ctx->sta_ctx;
+
+	if (!sta_ctx)
+		return QDF_STATUS_E_INVAL;
+
+	mlo_dev_lock_acquire(mlo_ctx);
+
+	sta_ctx->ml_link_state.ml_link_state_resp_cb =
+		req->ml_link_state_resp_cb;
+	sta_ctx->ml_link_state.ml_link_state_req_context =
+		req->request_cookie;
+	mlo_dev_lock_release(mlo_ctx);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static QDF_STATUS ml_get_link_state_req_flush_cb(struct scheduler_msg *msg)
+{
+	mlo_debug("ml_get_link_state_req flush callback");
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS ml_post_get_link_state_msg(struct wlan_objmgr_vdev *vdev)
+{
+	struct scheduler_msg msg = {0};
+	QDF_STATUS qdf_status = 0;
+
+	msg.bodyptr = vdev;
+	msg.callback = ml_get_link_state_req_cb;
+	msg.flush_callback = ml_get_link_state_req_flush_cb;
+
+	qdf_status = scheduler_post_message(
+				QDF_MODULE_ID_OS_IF,
+				QDF_MODULE_ID_MLME,
+				QDF_MODULE_ID_OS_IF,
+				&msg);
+	return qdf_status;
+}
+

+ 44 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_sta.c

@@ -2455,4 +2455,48 @@ err_release_refs:
 	for (i = 0; i < vdev_count; i++)
 		mlo_release_vdev_ref(wlan_vdev_list[i]);
 }
+
+QDF_STATUS
+mlo_get_link_state_context(struct wlan_objmgr_psoc *psoc,
+			   get_ml_link_state_cb *resp_cb,
+			   void **context, uint8_t vdev_id)
+{
+	struct wlan_mlo_dev_context *mlo_ctx;
+	struct wlan_mlo_sta *sta_ctx = NULL;
+	struct wlan_objmgr_vdev *vdev;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_MLO_MGR_ID);
+	if (!vdev)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	mlo_ctx = vdev->mlo_dev_ctx;
+
+	if (!mlo_ctx) {
+		mlo_err("null mlo_dev_ctx");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	sta_ctx = mlo_ctx->sta_ctx;
+
+	if (!sta_ctx) {
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	mlo_dev_lock_acquire(mlo_ctx);
+	*resp_cb = sta_ctx->ml_link_state.ml_link_state_resp_cb;
+	*context = sta_ctx->ml_link_state.ml_link_state_req_context;
+
+	mlo_dev_lock_release(mlo_ctx);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
+	return QDF_STATUS_SUCCESS;
+}
+
 #endif