Browse Source

qcacld-3.0: Set unforce mode for link

TDLS for MLO, it forces link active when sending TDLS discovery
Request, it needs to unforce the link when:
There is no discovery response on that link; or
The remain links except the link which is TDLS link; or
The link for TDLS but no more TDLS connection.

CRs-Fixed: 3623332
Change-Id: Ie9fb0d210952531744bba397c1a34f4d8f1f14fb
Paul Zhang 1 year ago
parent
commit
59d68775f9

+ 44 - 0
components/tdls/core/src/wlan_tdls_cmds_process.c

@@ -1661,6 +1661,48 @@ QDF_STATUS tdls_process_add_peer_rsp(struct tdls_add_sta_rsp *rsp)
 	return QDF_STATUS_E_INVAL;
 }
 
+static void tdls_process_unforce_link_mode(struct wlan_objmgr_vdev *vdev)
+{
+	struct tdls_vdev_priv_obj *tdls_vdev;
+	struct tdls_peer *peer;
+	qdf_list_t *head;
+	qdf_list_node_t *p_node;
+	QDF_STATUS status;
+	bool unforce = true;
+	int i;
+
+	tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
+	if (!tdls_vdev)
+		return;
+
+	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
+		head = &tdls_vdev->peer_list[i];
+		status = qdf_list_peek_front(head, &p_node);
+		while (QDF_IS_STATUS_SUCCESS(status)) {
+			peer = qdf_container_of(p_node, struct tdls_peer, node);
+
+			tdls_debug("Peer: " QDF_MAC_ADDR_FMT "link status %d, vdev id %d",
+				   QDF_MAC_ADDR_REF(peer->peer_mac.bytes),
+				   peer->link_status, wlan_vdev_get_id(vdev));
+
+			if (peer->link_status == TDLS_LINK_CONNECTED ||
+			    peer->link_status == TDLS_LINK_CONNECTING) {
+				unforce = false;
+				goto unforce_exit;
+			}
+
+			status = qdf_list_peek_next(head, p_node, &p_node);
+		}
+	}
+
+unforce_exit:
+	if (unforce) {
+		tdls_debug("try to set vdev %d to unforce",
+			   wlan_vdev_get_id(vdev));
+		tdls_set_link_unforce(vdev);
+	}
+}
+
 QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp)
 {
 	uint8_t sta_idx, id;
@@ -1734,6 +1776,8 @@ QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp)
 						  TDLS_LINK_DROPPED_BY_REMOTE);
 	}
 
+	tdls_process_unforce_link_mode(vdev);
+
 cmddone:
 	tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_DEL_PEER);
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);

+ 24 - 0
components/tdls/core/src/wlan_tdls_ct.c

@@ -97,6 +97,7 @@ void tdls_discovery_timeout_peer_cb(void *user_data)
 	struct wlan_objmgr_vdev *tdls_link_vdev;
 	struct tdls_rx_mgmt_frame *rx_mgmt;
 	uint8_t *mac;
+	bool unforce = true;
 
 	if (!user_data) {
 		tdls_err("discovery time out data is null");
@@ -163,6 +164,15 @@ void tdls_discovery_timeout_peer_cb(void *user_data)
 		while (QDF_IS_STATUS_SUCCESS(status)) {
 			peer = qdf_container_of(p_node, struct tdls_peer,
 						node);
+
+			tdls_debug("Peer: " QDF_MAC_ADDR_FMT "link status %d, vdev id %d",
+				   QDF_MAC_ADDR_REF(peer->peer_mac.bytes),
+				   peer->link_status, wlan_vdev_get_id(vdev));
+
+			if (peer->link_status != TDLS_LINK_DISCOVERING &&
+			    peer->link_status != TDLS_LINK_IDLE)
+				unforce = false;
+
 			if (TDLS_LINK_DISCOVERING != peer->link_status) {
 				status = qdf_list_peek_next(head, p_node,
 							    &p_node);
@@ -176,6 +186,12 @@ void tdls_discovery_timeout_peer_cb(void *user_data)
 		}
 	}
 
+	if (wlan_vdev_mlme_is_mlo_vdev(vdev) && unforce) {
+		tdls_debug("try to set vdev %d to unforce",
+			   wlan_vdev_get_id(vdev));
+		tdls_set_link_unforce(vdev);
+	}
+
 	tdls_vdev->discovery_sent_cnt = 0;
 	/* add tdls power save prohibited */
 
@@ -1458,6 +1474,14 @@ void tdls_disable_offchan_and_teardown_links(
 	QDF_STATUS status;
 	uint8_t vdev_id;
 	bool tdls_in_progress = false;
+	bool is_mlo_vdev;
+
+	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
+	if (is_mlo_vdev) {
+		tdls_debug("try to set vdev %d to unforce",
+			   wlan_vdev_get_id(vdev));
+		tdls_set_link_unforce(vdev);
+	}
 
 	status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc);
 	if (QDF_STATUS_SUCCESS != status) {

+ 30 - 0
components/tdls/core/src/wlan_tdls_main.c

@@ -80,6 +80,7 @@ static char *tdls_get_cmd_type_str(enum tdls_command_type cmd_type)
 	CASE_RETURN_STRING(TDLS_CMD_SET_SECOFFCHANOFFSET);
 	CASE_RETURN_STRING(TDLS_DELETE_ALL_PEERS_INDICATION);
 	CASE_RETURN_STRING(TDLS_CMD_START_BSS);
+	CASE_RETURN_STRING(TDLS_CMD_SET_LINK_UNFORCE);
 	default:
 		return "Invalid TDLS command";
 	}
@@ -582,6 +583,17 @@ QDF_STATUS tdls_handle_start_bss(struct wlan_objmgr_psoc *psoc)
 }
 #endif
 
+static void tdls_handle_link_unforce(struct wlan_objmgr_vdev *vdev)
+{
+	struct tdls_action_frame_request req = {0};
+
+	req.vdev = vdev;
+	req.tdls_mgmt.frame_type = TDLS_MAX_ACTION_CODE;
+
+	tdls_debug("set vdev %d unforce", wlan_vdev_get_id(vdev));
+	tdls_set_link_mode(&req);
+}
+
 QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -668,6 +680,9 @@ QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
 	case TDLS_CMD_START_BSS:
 		tdls_handle_start_bss(msg->bodyptr);
 		break;
+	case TDLS_CMD_SET_LINK_UNFORCE:
+		tdls_handle_link_unforce(msg->bodyptr);
+		break;
 	default:
 		break;
 	}
@@ -2039,6 +2054,21 @@ void tdls_scan_complete_event_handler(struct wlan_objmgr_vdev *vdev,
 	tdls_post_scan_done_msg(tdls_soc);
 }
 
+void tdls_set_link_unforce(struct wlan_objmgr_vdev *vdev)
+{
+	QDF_STATUS status;
+	struct scheduler_msg msg = {0};
+
+	msg.callback = tdls_process_cmd;
+	msg.type = TDLS_CMD_SET_LINK_UNFORCE;
+	msg.bodyptr = vdev;
+	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
+					QDF_MODULE_ID_TDLS,
+					QDF_MODULE_ID_OS_IF, &msg);
+	if (QDF_IS_STATUS_ERROR(status))
+		tdls_err("failed to set tdls link mode");
+}
+
 /**
  * tdls_check_peer_buf_capable() - Check buffer sta capable of tdls peers
  * @tdls_vdev: TDLS vdev object

+ 8 - 0
components/tdls/core/src/wlan_tdls_main.h

@@ -811,6 +811,14 @@ void tdls_scan_complete_event_handler(struct wlan_objmgr_vdev *vdev,
 			struct scan_event *event,
 			void *arg);
 
+/**
+ * tdls_set_link_unforce() - set link unforce
+ * @vdev: vdev object
+ *
+ * Return: void
+ */
+void tdls_set_link_unforce(struct wlan_objmgr_vdev *vdev);
+
 /**
  * tdls_scan_callback() - callback for TDLS scan operation
  * @tdls_soc: tdls soc pvt object

+ 39 - 6
components/tdls/core/src/wlan_tdls_mgmt.c

@@ -87,6 +87,26 @@ tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev)
 	return wlan_mlo_get_tdls_link_vdev(vdev);
 }
 
+void
+tdls_set_remain_links_unforce(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct wlan_objmgr_vdev *mlo_vdev;
+	int i;
+
+	/* TDLS link is selected, unforce link for other vdevs */
+	mlo_dev_ctx = vdev->mlo_dev_ctx;
+	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
+		mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
+		if (!mlo_vdev || mlo_vdev == vdev)
+			continue;
+
+		tdls_debug("try to set vdev %d to unforce",
+			   wlan_vdev_get_id(mlo_vdev));
+		tdls_set_link_unforce(mlo_vdev);
+	}
+}
+
 QDF_STATUS
 tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev)
 {
@@ -425,6 +445,11 @@ tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev)
 	return NULL;
 }
 
+void
+tdls_set_remain_links_unforce(struct wlan_objmgr_vdev *vdev)
+{
+}
+
 QDF_STATUS
 tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev)
 {
@@ -852,7 +877,7 @@ tdls_send_mgmt_serialize_callback(struct wlan_serialization_command *cmd,
 }
 
 #ifdef WLAN_FEATURE_11BE_MLO
-static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
+QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
 {
 	uint8_t mlo_vdev_lst[WLAN_UMAC_MLO_MAX_VDEVS] = {-1};
 	struct wlan_objmgr_psoc *psoc;
@@ -865,10 +890,6 @@ static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
 	if (!is_mlo_vdev)
 		return status;
 
-	mlo_tdls_vdev = wlan_mlo_get_tdls_link_vdev(req->vdev);
-	if (mlo_tdls_vdev)
-		return status;
-
 	psoc = wlan_vdev_get_psoc(req->vdev);
 	if (!psoc) {
 		tdls_err("psoc is NULL");
@@ -877,6 +898,10 @@ static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
 
 	if (req->tdls_mgmt.frame_type == TDLS_DISCOVERY_RESPONSE ||
 	    req->tdls_mgmt.frame_type == TDLS_DISCOVERY_REQUEST) {
+		mlo_tdls_vdev = wlan_mlo_get_tdls_link_vdev(req->vdev);
+		if (mlo_tdls_vdev)
+			return status;
+
 		mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
 		vdev_count = 1;
 
@@ -886,12 +911,20 @@ static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
 						     vdev_count, mlo_vdev_lst);
 		if (status == QDF_STATUS_SUCCESS)
 			req->link_active = true;
+	} else if (req->tdls_mgmt.frame_type == TDLS_MAX_ACTION_CODE) {
+		mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
+		vdev_count = 1;
+		status =
+		    policy_mgr_mlo_sta_set_link(psoc,
+						MLO_LINK_FORCE_REASON_TDLS,
+						MLO_LINK_FORCE_MODE_NO_FORCE,
+						vdev_count, mlo_vdev_lst);
 	}
 
 	return status;
 }
 #else
-static QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
+QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
 {
 	return QDF_STATUS_SUCCESS;
 }

+ 16 - 0
components/tdls/core/src/wlan_tdls_mgmt.h

@@ -99,6 +99,14 @@ tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev);
 struct wlan_objmgr_vdev *
 tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * tdls_set_remain_links_unforce() - unforce links
+ * @vdev: vdev object
+ *
+ * Return: void
+ */
+void tdls_set_remain_links_unforce(struct wlan_objmgr_vdev *vdev);
+
 /**
  * tdls_mgmt_rx_ops() - register or unregister rx callback
  * @psoc: psoc object
@@ -150,5 +158,13 @@ tdls_process_mlo_choice_tdls_vdev(struct wlan_objmgr_vdev *vdev);
  * Return: void
  */
 void tdls_set_no_force_vdev(struct wlan_objmgr_vdev *vdev, bool flag);
+
+/**
+ * tdls_set_link_mode() - force active or unfore link for MLO case
+ * @req: the pointer of tdls_action_frame_request
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req);
 #endif
 

+ 3 - 1
components/tdls/dispatcher/inc/wlan_tdls_public_structs.h

@@ -241,6 +241,7 @@ enum tdls_feature_mode {
  * @TDLS_CMD_SET_SECOFFCHANOFFSET: tdls secondary offchannel offset
  * @TDLS_DELETE_ALL_PEERS_INDICATION: tdls delete all peers indication
  * @TDLS_CMD_START_BSS: SAP start indication to tdls module
+ * @TDLS_CMD_SET_LINK_UNFORCE: tdls to unforce link for MLO case
  */
 enum tdls_command_type {
 	TDLS_CMD_TX_ACTION = 1,
@@ -267,7 +268,8 @@ enum tdls_command_type {
 	TDLS_CMD_SET_OFFCHANMODE,
 	TDLS_CMD_SET_SECOFFCHANOFFSET,
 	TDLS_DELETE_ALL_PEERS_INDICATION,
-	TDLS_CMD_START_BSS
+	TDLS_CMD_START_BSS,
+	TDLS_CMD_SET_LINK_UNFORCE
 };
 
 /**

+ 1 - 0
components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c

@@ -528,6 +528,7 @@ bool ucfg_tdls_link_vdev_is_matching(struct wlan_objmgr_vdev *vdev)
 	if (!tdls_link_vdev) {
 		wlan_vdev_mlme_feat_ext2_cap_set(vdev,
 						 WLAN_VDEV_FEXT2_MLO_STA_TDLS);
+		tdls_set_remain_links_unforce(vdev);
 		return true;
 	}