Browse Source

qcacld-3.0: T2LM timer changes

Code changes to run the T2LM timer in FW instead of host.

Change-Id: Ic66da9e0311121d2ae23c600c97f225c56aa215f
CRs-Fixed: 3595388
Amruta Kulkarni 1 year ago
parent
commit
fc51b6ff4f

+ 4 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c

@@ -1618,6 +1618,9 @@ cm_update_tid_mapping(struct wlan_objmgr_vdev *vdev)
 	if (!vdev || !vdev->mlo_dev_ctx)
 		return QDF_STATUS_E_NULL_VALUE;
 
+	if (!wlan_cm_is_vdev_connected(vdev))
+		return QDF_STATUS_E_AGAIN;
+
 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev) ||
 	    !mlo_check_if_all_links_up(vdev))
 		return QDF_STATUS_E_FAILURE;
@@ -1628,7 +1631,7 @@ cm_update_tid_mapping(struct wlan_objmgr_vdev *vdev)
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
-	status = wlan_process_bcn_prbrsp_t2lm_ie(vdev, t2lm_ctx, t2lm_ctx->tsf);
+	status = wlan_update_t2lm_mapping(vdev, t2lm_ctx, t2lm_ctx->tsf);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		mlme_err("T2LM IE beacon process failed");
 	}

+ 37 - 0
components/umac/mlme/mlo_mgr/inc/wlan_t2lm_api.h

@@ -246,7 +246,44 @@ wlan_t2lm_clear_all_tid_mapping(struct wlan_objmgr_vdev *vdev);
 QDF_STATUS
 wlan_populate_link_disable_t2lm_frame(struct wlan_objmgr_vdev *vdev,
 				      struct mlo_link_disable_request_evt_params *params);
+
+/**
+ * wlan_update_t2lm_mapping - Update t2lm mapping to fw
+ * @vdev: pointer to vdev
+ * @rx_t2lm: received t2lm mapping from beacon
+ * @tsf: timing sync function value
+ *
+ * Return: qdf status
+ */
+QDF_STATUS wlan_update_t2lm_mapping(
+		struct wlan_objmgr_vdev *vdev,
+		struct wlan_t2lm_context *rx_t2lm,
+		uint64_t tsf);
+
+/**
+ * wlan_t2lm_init_default_mapping - Initialize t2lm to default mapping
+ * @t2lm_ctx: t2lm ctx stored in ml dev ctx
+ *
+ * Return: qdf status
+ */
+QDF_STATUS
+wlan_t2lm_init_default_mapping(struct wlan_t2lm_context *t2lm_ctx);
+
 #else
+static inline QDF_STATUS
+wlan_t2lm_init_default_mapping(struct wlan_t2lm_context *t2lm_ctx)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
+static inline QDF_STATUS wlan_update_t2lm_mapping(
+		struct wlan_objmgr_vdev *vdev,
+		struct wlan_t2lm_context *rx_t2lm,
+		uint64_t tsf)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
 static inline QDF_STATUS
 wlan_populate_link_disable_t2lm_frame(struct wlan_objmgr_vdev *vdev,
 				      struct mlo_link_disable_request_evt_params *params)

+ 202 - 0
components/umac/mlme/mlo_mgr/src/wlan_t2lm_api.c

@@ -729,3 +729,205 @@ QDF_STATUS wlan_t2lm_deliver_event(struct wlan_objmgr_vdev *vdev,
 	return t2lm_deliver_event(vdev, peer, event, event_data,
 				  frame_len, dialog_token);
 }
+
+QDF_STATUS
+wlan_t2lm_init_default_mapping(struct wlan_t2lm_context *t2lm_ctx)
+{
+	if (!t2lm_ctx)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	qdf_mem_zero(t2lm_ctx, sizeof(struct wlan_t2lm_context));
+
+	t2lm_ctx->established_t2lm.t2lm.default_link_mapping = 1;
+	t2lm_ctx->established_t2lm.t2lm.direction = WLAN_T2LM_BIDI_DIRECTION;
+	t2lm_ctx->established_t2lm.t2lm.link_mapping_size = 0;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_update_t2lm_mapping(struct wlan_objmgr_vdev *vdev,
+			 struct wlan_t2lm_context *rx_t2lm, uint64_t tsf)
+{
+	struct wlan_t2lm_context *t2lm_ctx;
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	uint64_t mst_start_tsf;
+	uint64_t mst_end_tsf;
+	uint64_t rx_bcn_tsf_exp_dur;
+	uint64_t mst_end_tsf_low;
+	uint64_t mst_end_tsf_high;
+	uint16_t mst;
+	uint32_t exp_dur;
+
+	if (!vdev)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	t2lm_ctx = &mlo_dev_ctx->t2lm_ctx;
+	if (rx_t2lm->upcoming_t2lm.t2lm.direction == WLAN_T2LM_INVALID_DIRECTION &&
+	    rx_t2lm->established_t2lm.t2lm.direction == WLAN_T2LM_INVALID_DIRECTION) {
+		if (!t2lm_ctx->established_t2lm.t2lm.default_link_mapping) {
+			wlan_t2lm_init_default_mapping(t2lm_ctx);
+			t2lm_debug("initialize to default T2LM mapping");
+		}
+		return QDF_STATUS_SUCCESS;
+	}
+
+	if (rx_t2lm->established_t2lm.t2lm.expected_duration &&
+	    !rx_t2lm->established_t2lm.t2lm.mapping_switch_time_present &&
+	    rx_t2lm->upcoming_t2lm.t2lm.expected_duration &&
+	    rx_t2lm->upcoming_t2lm.t2lm.mapping_switch_time_present) {
+		if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid,
+				 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid,
+				 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
+			t2lm_debug("T2LM mapping is already configured");
+			return QDF_STATUS_E_ALREADY;
+		}
+
+		qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm,
+			     &rx_t2lm->established_t2lm.t2lm,
+			     sizeof(struct wlan_t2lm_info));
+
+		t2lm_ctx->established_t2lm.t2lm.expected_duration = 0;
+		t2lm_ctx->established_t2lm.t2lm.expected_duration_present = 0;
+		t2lm_ctx->established_t2lm.t2lm.mapping_switch_time = 0;
+		t2lm_ctx->established_t2lm.t2lm.mapping_switch_time_present = 0;
+
+		wlan_mlo_dev_t2lm_notify_link_update(vdev,
+					&t2lm_ctx->established_t2lm.t2lm);
+		wlan_clear_peer_level_tid_to_link_mapping(vdev);
+		t2lm_debug("Update T2LM established mapping to FW");
+		wlan_send_tid_to_link_mapping(
+				vdev, &t2lm_ctx->established_t2lm.t2lm);
+
+		if (!qdf_mem_cmp(t2lm_ctx->upcoming_t2lm.t2lm.ieee_link_map_tid,
+				 rx_t2lm->upcoming_t2lm.t2lm.ieee_link_map_tid,
+				 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
+			t2lm_debug("Ongoing mapping is already established");
+			return QDF_STATUS_E_ALREADY;
+		}
+		qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm,
+			     &rx_t2lm->upcoming_t2lm.t2lm,
+			     sizeof(struct wlan_t2lm_info));
+		t2lm_debug("Update T2LM upcoming mapping to FW");
+		wlan_send_tid_to_link_mapping(
+				vdev, &t2lm_ctx->upcoming_t2lm.t2lm);
+	}
+
+	if (t2lm_ctx->established_t2lm.t2lm.expected_duration_present &&
+	    rx_t2lm->established_t2lm.t2lm.expected_duration_present) {
+		/* Established T2LM is already saved in the T2LM context.
+		 * T2LM IE in the beacon/probe response frame has the updated
+		 * expected duration.
+		 */
+		if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid,
+				 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid,
+				 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
+			if (!t2lm_ctx->mst_start_tsf) {
+				t2lm_ctx->mst_end_tsf = tsf + (rx_t2lm->established_t2lm.t2lm.expected_duration << 10);
+				t2lm_ctx->mst_start_tsf = tsf;
+			}
+
+			/* Check if AP has updated expected duration value
+			 * more than expected delta between 2 beacons,
+			 * calculation as following:
+			 * 1.when receive a beacon with mapping switch
+			 * time set, calculate the mapping switch start TSF
+			 * by replacing bit25~bit10 in the bcn TSF
+			 * mst_start_tsf = (bcn_tsf & (~mst_mask)) | (mst << 10);
+			 * 2.based on the expected duration,
+			 * calculate the mapping end time tsf
+			 * mst_end_tsf = mst_start_tsf + expected_duration;
+			 * 3.then after the TSF become established mapping,
+			 *  whenever host receive a beacon,
+			 * check if the new expected duration based
+			 * on current beacon TSF has a big drift to the old one.
+			 * mst_end_tsf - (200 << 10) < rx_bcn_tsf_exp_dur +
+			 *  rx_bcn_tsf_exp_dur < mst_end_tsf + (200 << 10)
+			 */
+			rx_bcn_tsf_exp_dur = tsf + (rx_t2lm->established_t2lm.t2lm.expected_duration << 10);
+			mst_end_tsf_low = t2lm_ctx->mst_end_tsf - (200 << 10);
+			mst_end_tsf_high = t2lm_ctx->mst_end_tsf + (200 << 10);
+			if (t2lm_ctx->mst_end_tsf && (rx_bcn_tsf_exp_dur < mst_end_tsf_low) &&
+			    (rx_bcn_tsf_exp_dur > mst_end_tsf_high)) {
+				t2lm_ctx->established_t2lm.t2lm.expected_duration =
+					rx_t2lm->established_t2lm.t2lm.expected_duration;
+				wlan_send_tid_to_link_mapping(
+					vdev, &t2lm_ctx->established_t2lm.t2lm);
+			} else {
+				t2lm_debug("T2LM exp duration in range");
+			}
+		}
+	} else if (rx_t2lm->established_t2lm.t2lm.expected_duration_present &&
+		   !rx_t2lm->established_t2lm.t2lm.mapping_switch_time_present) {
+		if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid,
+				 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid,
+				 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
+			t2lm_debug("T2LM mapping is already configured");
+			return QDF_STATUS_E_ALREADY;
+		}
+
+		mst_start_tsf = tsf;
+		t2lm_ctx->mst_start_tsf = mst_start_tsf;
+		mst_end_tsf = mst_start_tsf + (rx_t2lm->established_t2lm.t2lm.expected_duration << 10);
+		t2lm_ctx->mst_end_tsf = mst_end_tsf;
+
+		/* Mapping switch time is already expired when STA receives the
+		 * T2LM IE from beacon/probe response frame.
+		 */
+		qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm,
+			     &rx_t2lm->established_t2lm.t2lm,
+			     sizeof(struct wlan_t2lm_info));
+
+		/* Notify the registered caller about the link update*/
+		wlan_mlo_dev_t2lm_notify_link_update(vdev,
+					&t2lm_ctx->established_t2lm.t2lm);
+		wlan_clear_peer_level_tid_to_link_mapping(vdev);
+		t2lm_debug("MST expired, update established T2LM mapping to FW");
+		wlan_send_tid_to_link_mapping(
+				vdev, &t2lm_ctx->established_t2lm.t2lm);
+	}
+
+	if (rx_t2lm->upcoming_t2lm.t2lm.mapping_switch_time_present) {
+		if (!qdf_mem_cmp(t2lm_ctx->upcoming_t2lm.t2lm.ieee_link_map_tid,
+				 rx_t2lm->upcoming_t2lm.t2lm.ieee_link_map_tid,
+				 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
+			t2lm_debug("Ongoing mapping is already established");
+			return QDF_STATUS_E_ALREADY;
+		}
+
+		mst = rx_t2lm->upcoming_t2lm.t2lm.mapping_switch_time;
+		exp_dur = rx_t2lm->upcoming_t2lm.t2lm.expected_duration;
+		if (mst) {
+			mst_start_tsf = (tsf & (~WLAN_T2LM_MAPPING_SWITCH_TSF_BITS)) | (mst << 10);
+			mst_end_tsf = mst_start_tsf + exp_dur;
+			t2lm_ctx->mst_start_tsf = mst_start_tsf;
+			t2lm_ctx->mst_end_tsf = mst_end_tsf;
+		}
+
+		qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm,
+			     &rx_t2lm->upcoming_t2lm.t2lm,
+			     sizeof(struct wlan_t2lm_info));
+		t2lm_debug("Update T2LM upcoming mapping to FW");
+		wlan_send_tid_to_link_mapping(
+				vdev, &t2lm_ctx->upcoming_t2lm.t2lm);
+	} else {
+		if (t2lm_ctx->established_t2lm.t2lm.direction == WLAN_T2LM_INVALID_DIRECTION &&
+		    t2lm_ctx->upcoming_t2lm.t2lm.direction != WLAN_T2LM_INVALID_DIRECTION) {
+			t2lm_debug("Copy upcoming T2LM mapping to expected T2LM");
+			qdf_mem_copy(&t2lm_ctx->established_t2lm,
+				     &t2lm_ctx->upcoming_t2lm,
+				     sizeof(struct wlan_mlo_t2lm_ie));
+		}
+		/* Upcoming mapping should be cleared as mapping switch time has expired */
+		qdf_mem_zero(&t2lm_ctx->upcoming_t2lm,
+			     sizeof(struct wlan_mlo_t2lm_ie));
+		t2lm_ctx->upcoming_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+

+ 5 - 7
core/mac/src/pe/lim/lim_process_beacon_frame.c

@@ -49,6 +49,7 @@
 #ifdef WLAN_FEATURE_11BE_MLO
 #include <cds_ieee80211_common.h>
 #endif
+#include "wlan_t2lm_api.h"
 
 #ifdef WLAN_FEATURE_11BE_MLO
 void lim_process_bcn_prb_rsp_t2lm(struct mac_context *mac_ctx,
@@ -67,20 +68,17 @@ void lim_process_bcn_prb_rsp_t2lm(struct mac_context *mac_ctx,
 	if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
 		return;
 
-	if (!mlo_check_if_all_links_up(vdev))
+	if (!wlan_cm_is_vdev_connected(vdev))
 		return;
 
-	if (bcn_ptr->t2lm_ctx.upcoming_t2lm.t2lm.direction ==
-	    WLAN_T2LM_INVALID_DIRECTION &&
-	    bcn_ptr->t2lm_ctx.established_t2lm.t2lm.direction ==
-	    WLAN_T2LM_INVALID_DIRECTION)
+	if (!mlo_check_if_all_links_up(vdev))
 		return;
 
 	t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
+
 	qdf_mem_copy((uint8_t *)&t2lm_ctx->tsf, (uint8_t *)bcn_ptr->timeStamp,
 		     sizeof(uint64_t));
-	wlan_process_bcn_prbrsp_t2lm_ie(vdev, &bcn_ptr->t2lm_ctx,
-					t2lm_ctx->tsf);
+	wlan_update_t2lm_mapping(vdev, &bcn_ptr->t2lm_ctx, t2lm_ctx->tsf);
 }
 
 void lim_process_beacon_mlo(struct mac_context *mac_ctx,