Explorar o código

qcacld-3.0: Add support for t2lm send action req frame

Add support to handle mlo link disable event and
send t2lm action frame.

Change-Id: I0b620c17fbb89b89d4d03cd55b1a6f41d28d6c2b
CRs-Fixed: 3470960
Amruta Kulkarni %!s(int64=2) %!d(string=hai) anos
pai
achega
86e9bf96dd

+ 21 - 1
components/umac/mlme/mlo_mgr/inc/wlan_t2lm_api.h

@@ -107,6 +107,7 @@ QDF_STATUS t2lm_handle_tx_resp(struct wlan_objmgr_vdev *vdev,
 /**
  * t2lm_handle_tx_req - Handler for populating T2LM action frame
  * @vdev: vdev pointer
+ * @peer: pointer to peer
  * @event_data: T2LM event data pointer
  * @token: Dialog token
  *
@@ -115,7 +116,8 @@ QDF_STATUS t2lm_handle_tx_resp(struct wlan_objmgr_vdev *vdev,
  * Return: qdf_status
  */
 QDF_STATUS t2lm_handle_tx_req(struct wlan_objmgr_vdev *vdev,
-			      void *event_data, uint8_t *token);
+		   struct wlan_objmgr_peer *peer,
+		   void *event_data, uint8_t *token);
 
 /**
  * t2lm_handle_rx_resp - Handler for parsing T2LM action frame
@@ -218,7 +220,24 @@ wlan_t2lm_clear_peer_negotiation(struct wlan_objmgr_peer *peer);
 void
 wlan_t2lm_clear_all_tid_mapping(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * wlan_populate_link_disable_t2lm_frame - Populate link disable t2lm frame
+ * @vdev: pointer to vdev
+ * @params: link disable params
+ *
+ * Return: none
+ */
+QDF_STATUS
+wlan_populate_link_disable_t2lm_frame(struct wlan_objmgr_vdev *vdev,
+				      struct mlo_link_disable_request_evt_params *params);
 #else
+static inline QDF_STATUS
+wlan_populate_link_disable_t2lm_frame(struct wlan_objmgr_vdev *vdev,
+				      struct mlo_link_disable_request_evt_params *params)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
 static inline QDF_STATUS
 t2lm_handle_rx_req(struct wlan_objmgr_vdev *vdev,
 		   struct wlan_objmgr_peer *peer,
@@ -236,6 +255,7 @@ t2lm_handle_tx_resp(struct wlan_objmgr_vdev *vdev,
 
 static inline QDF_STATUS
 t2lm_handle_tx_req(struct wlan_objmgr_vdev *vdev,
+		   struct wlan_objmgr_peer *peer,
 		   void *event_data, uint8_t *token)
 {
 	return QDF_STATUS_E_NOSUPPORT;

+ 181 - 4
components/umac/mlme/mlo_mgr/src/wlan_t2lm_api.c

@@ -24,6 +24,9 @@
 #include "wlan_cm_api.h"
 #include "wlan_mlo_mgr_roam.h"
 
+#define T2LM_MIN_DIALOG_TOKEN         1
+#define T2LM_MAX_DIALOG_TOKEN         0xFF
+
 static
 const char *t2lm_get_event_str(enum wlan_t2lm_evt event)
 {
@@ -111,6 +114,22 @@ bool t2lm_is_valid_t2lm_link_map(struct wlan_objmgr_vdev *vdev,
 	return is_valid_link_mask;
 }
 
+static uint8_t
+t2lm_gen_dialog_token(struct wlan_mlo_peer_t2lm_policy *t2lm_policy)
+{
+	if (!t2lm_policy)
+		return 0;
+
+	if (t2lm_policy->self_gen_dialog_token == T2LM_MAX_DIALOG_TOKEN)
+		/* wrap is ok */
+		t2lm_policy->self_gen_dialog_token = T2LM_MIN_DIALOG_TOKEN;
+	else
+		t2lm_policy->self_gen_dialog_token += 1;
+
+	t2lm_debug("gen dialog token %d", t2lm_policy->self_gen_dialog_token);
+	return t2lm_policy->self_gen_dialog_token;
+}
+
 QDF_STATUS t2lm_handle_rx_req(struct wlan_objmgr_vdev *vdev,
 			      struct wlan_objmgr_peer *peer,
 			      void *event_data, uint8_t *token)
@@ -167,9 +186,40 @@ QDF_STATUS t2lm_handle_tx_resp(struct wlan_objmgr_vdev *vdev,
 }
 
 QDF_STATUS t2lm_handle_tx_req(struct wlan_objmgr_vdev *vdev,
+			      struct wlan_objmgr_peer *peer,
 			      void *event_data, uint8_t *token)
 {
-	return QDF_STATUS_SUCCESS;
+	struct wlan_t2lm_onging_negotiation_info *t2lm_neg;
+	struct wlan_action_frame_args args;
+	QDF_STATUS status;
+
+	if (!vdev)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	if (!event_data) {
+		t2lm_err("Null event data ptr");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	t2lm_neg = (struct wlan_t2lm_onging_negotiation_info *)event_data;
+	args.category = ACTION_CATEGORY_PROTECTED_EHT;
+	args.action = EHT_T2LM_REQUEST;
+	args.arg1 = *token;
+
+	status = lim_send_t2lm_action_req_frame(vdev,
+						wlan_peer_get_macaddr(peer),
+						&args, t2lm_neg,
+						*token);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		t2lm_err("Failed to send T2LM action request frame");
+	} else {
+		t2lm_debug("Copy the ongoing neg to peer");
+		qdf_mem_copy(&peer->mlo_peer_ctx->t2lm_policy.ongoing_tid_to_link_mapping,
+			     t2lm_neg, sizeof(struct wlan_t2lm_onging_negotiation_info));
+	}
+
+	return status;
 }
 
 QDF_STATUS t2lm_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
@@ -205,11 +255,16 @@ QDF_STATUS t2lm_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	mlme_debug("t2lm rsp dialog token %d", t2lm_rsp.dialog_token);
+	mlme_debug("t2lm rsp is %d", t2lm_rsp.t2lm_resp_type);
 	t2lm_req = &ml_peer->t2lm_policy.ongoing_tid_to_link_mapping;
+	if (!t2lm_req) {
+		t2lm_err("Ongoing tid neg is null");
+		return QDF_STATUS_E_FAILURE;
+	}
 
-	/* match dialog token and send t2lm mapping */
 	for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) {
-		t2lm_info = &ml_peer->t2lm_policy.ongoing_tid_to_link_mapping.t2lm_info[dir];
+		t2lm_info = &t2lm_req->t2lm_info[dir];
 		if (t2lm_info &&
 		    t2lm_info->direction != WLAN_T2LM_INVALID_DIRECTION) {
 			if (t2lm_rsp.dialog_token == t2lm_req->dialog_token &&
@@ -220,6 +275,10 @@ QDF_STATUS t2lm_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
 					t2lm_err("sending t2lm wmi failed");
 					break;
 				}
+			} else if (t2lm_rsp.dialog_token == t2lm_req->dialog_token &&
+				   t2lm_rsp.t2lm_resp_type == WLAN_T2LM_RESP_TYPE_DENIED_TID_TO_LINK_MAPPING) {
+				t2lm_debug("T2LM rsp status denied, clear ongoing tid mapping");
+				wlan_t2lm_clear_ongoing_negotiation(peer);
 			}
 		}
 	}
@@ -296,7 +355,7 @@ QDF_STATUS t2lm_deliver_event(struct wlan_objmgr_vdev *vdev,
 		status = t2lm_handle_tx_resp(vdev, event_data, token);
 		break;
 	case WLAN_T2LM_EV_ACTION_FRAME_TX_REQ:
-		status = t2lm_handle_tx_req(vdev, event_data, token);
+		status = t2lm_handle_tx_req(vdev, peer, event_data, token);
 		break;
 	case WLAN_T2LM_EV_ACTION_FRAME_RX_RESP:
 		status = t2lm_handle_rx_resp(vdev, peer, event_data, token);
@@ -523,6 +582,124 @@ wlan_t2lm_clear_all_tid_mapping(struct wlan_objmgr_vdev *vdev)
 	wlan_mlo_t2lm_timer_stop(vdev);
 }
 
+static bool
+wlan_is_ml_link_disabled(uint32_t link_id_bitmap,
+			 uint8_t ml_link_id)
+{
+	uint8_t link;
+
+	if (!link_id_bitmap) {
+		t2lm_err("Link id bitmap is 0");
+		return false;
+	}
+
+	for (link = 0; link < WLAN_T2LM_MAX_NUM_LINKS; link++) {
+		if ((link == ml_link_id) &&
+		    (link_id_bitmap & BIT(link))) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void
+wlan_t2lm_set_link_mapping_of_tids(uint8_t link_id,
+				   struct wlan_t2lm_info *t2lm_info,
+				   bool set)
+{
+	uint8_t tid_num;
+
+	if (link_id >= WLAN_T2LM_MAX_NUM_LINKS) {
+		t2lm_err("Max 16 t2lm links are supported");
+		return;
+	}
+
+	for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
+		if (set)
+			t2lm_info->ieee_link_map_tid[tid_num] |= BIT(link_id);
+		else
+			t2lm_info->ieee_link_map_tid[tid_num] &= ~BIT(link_id);
+	}
+}
+
+QDF_STATUS
+wlan_populate_link_disable_t2lm_frame(struct wlan_objmgr_vdev *vdev,
+				      struct mlo_link_disable_request_evt_params *params)
+{
+	struct wlan_objmgr_peer *peer;
+	struct wlan_mlo_dev_context *ml_dev_ctx;
+	struct wlan_mlo_peer_t2lm_policy *t2lm_policy;
+	struct wlan_objmgr_vdev *tmp_vdev;
+	struct wlan_t2lm_onging_negotiation_info t2lm_neg = {0};
+	uint8_t dir = WLAN_T2LM_BIDI_DIRECTION;
+	uint8_t i = 0;
+	QDF_STATUS status;
+	uint8_t link_id;
+
+	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
+						WLAN_MLO_MGR_ID);
+
+	if (!peer) {
+		t2lm_err("peer is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!vdev->mlo_dev_ctx)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	t2lm_policy = &peer->mlo_peer_ctx->t2lm_policy;
+	t2lm_neg = t2lm_policy->ongoing_tid_to_link_mapping;
+
+	t2lm_neg.category = WLAN_T2LM_CATEGORY_REQUEST;
+	t2lm_neg.dialog_token = t2lm_gen_dialog_token(t2lm_policy);
+	qdf_mem_zero(&t2lm_neg.t2lm_info,
+		     sizeof(struct wlan_t2lm_info) * WLAN_T2LM_MAX_DIRECTION);
+	for (i = 0; i < WLAN_T2LM_MAX_DIRECTION; i++)
+		t2lm_neg.t2lm_info[i].direction = WLAN_T2LM_INVALID_DIRECTION;
+
+	t2lm_neg.t2lm_info[dir].default_link_mapping = 0;
+	t2lm_neg.t2lm_info[dir].direction = WLAN_T2LM_BIDI_DIRECTION;
+	t2lm_neg.t2lm_info[dir].mapping_switch_time_present = 0;
+	t2lm_neg.t2lm_info[dir].expected_duration_present = 0;
+	t2lm_neg.t2lm_info[dir].link_mapping_size = 1;
+
+	t2lm_debug("dir %d", t2lm_neg.t2lm_info[dir].direction);
+	ml_dev_ctx = vdev->mlo_dev_ctx;
+
+	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
+		if (!ml_dev_ctx->wlan_vdev_list[i])
+			continue;
+
+		tmp_vdev = ml_dev_ctx->wlan_vdev_list[i];
+		link_id = wlan_vdev_get_link_id(tmp_vdev);
+
+		/* if link id matches disabled link id bitmap
+		 * set that bit as 0.
+		 */
+		if (wlan_is_ml_link_disabled(params->link_id_bitmap,
+					     link_id)) {
+			wlan_t2lm_set_link_mapping_of_tids(link_id,
+						&t2lm_neg.t2lm_info[dir],
+						0);
+			t2lm_debug("Disabled link id %d", link_id);
+		} else {
+			wlan_t2lm_set_link_mapping_of_tids(link_id,
+						&t2lm_neg.t2lm_info[dir],
+						1);
+			t2lm_debug("Enabled link id %d", link_id);
+		}
+	}
+
+	status = t2lm_deliver_event(vdev, peer,
+				    WLAN_T2LM_EV_ACTION_FRAME_TX_REQ,
+				    &t2lm_neg,
+				    &t2lm_neg.dialog_token);
+
+	wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
+	return status;
+}
+
 QDF_STATUS wlan_t2lm_deliver_event(struct wlan_objmgr_vdev *vdev,
 				   struct wlan_objmgr_peer *peer,
 				   enum wlan_t2lm_evt event,

+ 5 - 5
core/mac/src/pe/lim/lim_process_action_frame.c

@@ -2152,6 +2152,9 @@ void lim_process_action_frame(struct mac_context *mac_ctx,
 	case ACTION_CATEGORY_PROTECTED_EHT:
 		pe_debug("EHT T2LM action category: %d action: %d",
 			 action_hdr->category, action_hdr->actionID);
+		mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+		body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+		frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
 		peer = wlan_objmgr_get_peer_by_mac(mac_ctx->psoc,
 						   mac_hdr->sa,
 						   WLAN_LEGACY_MAC_ID);
@@ -2161,9 +2164,6 @@ void lim_process_action_frame(struct mac_context *mac_ctx,
 		}
 		switch (action_hdr->actionID) {
 		case EHT_T2LM_REQUEST:
-			mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
-			body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
-			frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
 			if (wlan_t2lm_deliver_event(
 				session->vdev, peer,
 				WLAN_T2LM_EV_ACTION_FRAME_RX_REQ,
@@ -2186,13 +2186,13 @@ void lim_process_action_frame(struct mac_context *mac_ctx,
 			wlan_t2lm_deliver_event(
 					session->vdev, peer,
 					WLAN_T2LM_EV_ACTION_FRAME_RX_RESP,
-					(void *)rx_pkt_info, &token);
+					(void *)body_ptr, &token);
 			break;
 		case EHT_T2LM_TEARDOWN:
 			wlan_t2lm_deliver_event(
 					session->vdev, peer,
 					WLAN_T2LM_EV_ACTION_FRAME_RX_TEARDOWN,
-					(void *)rx_pkt_info, NULL);
+					(void *)body_ptr, NULL);
 			break;
 		default:
 			pe_err("Unhandled T2LM action frame");

+ 143 - 2
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -6334,6 +6334,8 @@ lim_send_t2lm_action_rsp_frame(struct mac_context *mac_ctx,
 
 	session_id = session->smeSessionId;
 
+	vdev_id = session->vdev_id;
+
 	qdf_mem_zero((uint8_t *)&frm, sizeof(frm));
 	frm.Category.category = ACTION_CATEGORY_PROTECTED_EHT;
 	frm.Action.action = EHT_T2LM_RESPONSE;
@@ -6387,7 +6389,7 @@ lim_send_t2lm_action_rsp_frame(struct mac_context *mac_ctx,
 		pe_err("Failed to pack a T2LM negotiation response (0x%08x)",
 		       status);
 		qdf_status = QDF_STATUS_E_FAILURE;
-		goto error_addba_rsp;
+		goto error_t2lm_rsp;
 	} else if (DOT11F_WARNED(status)) {
 		pe_warn("There were warnings while packing T2LM rsp (0x%08x)",
 			status);
@@ -6413,7 +6415,146 @@ lim_send_t2lm_action_rsp_frame(struct mac_context *mac_ctx,
 		return QDF_STATUS_SUCCESS;
 	}
 
-error_addba_rsp:
+error_t2lm_rsp:
+	cds_packet_free((void *)pkt_ptr);
+	return qdf_status;
+}
+
+QDF_STATUS
+lim_send_t2lm_action_req_frame(struct wlan_objmgr_vdev *vdev,
+			       uint8_t *peer_mac,
+			       struct wlan_action_frame_args *args,
+			       struct wlan_t2lm_onging_negotiation_info *t2lm_neg,
+			       uint8_t token)
+{
+	tDot11ft2lm_neg_req frm;
+	struct mac_context *mac_ctx;
+	struct pe_session *session;
+	uint8_t session_id = 0;
+	uint8_t *frame_ptr;
+	tpSirMacMgmtHdr mgmt_hdr;
+	uint32_t num_bytes, payload_size, status;
+	void *pkt_ptr = NULL;
+	QDF_STATUS qdf_status;
+	uint8_t vdev_id = 0;
+	uint8_t tx_flag = 0;
+	struct wlan_ie_tid_to_link_mapping *t2lm_ie;
+	struct wlan_ie_tid_to_link_mapping ie_buf = {0};
+	uint8_t *t2lm_frame;
+
+	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
+	if (!mac_ctx)
+		return QDF_STATUS_E_INVAL;
+
+	if (!vdev)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	vdev_id = wlan_vdev_get_id(vdev);
+
+	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
+	session_id = session->smeSessionId;
+
+	qdf_mem_zero((uint8_t *)&frm, sizeof(frm));
+
+	t2lm_ie = (struct wlan_ie_tid_to_link_mapping *)&frm.t2lm_ie[0].data;
+	t2lm_frame = wlan_mlo_add_t2lm_ie((uint8_t *)&ie_buf,
+					  t2lm_neg,
+					  vdev);
+	if (!t2lm_frame) {
+		pe_debug("Failed to populate T2LM IE");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	frm.t2lm_ie[0].num_data = ie_buf.elem_len - 1;
+
+	pe_debug("Dump T2LM IE buff len %d", ie_buf.elem_len);
+	qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, &ie_buf,
+			   ie_buf.elem_len +  sizeof(struct ie_header));
+
+	qdf_mem_copy(&frm.t2lm_ie[0].data, &ie_buf.data,
+		     frm.t2lm_ie[0].num_data);
+
+	frm.Category.category = args->category;
+	frm.Action.action = args->action;
+	frm.DialogToken.token = args->arg1;
+	frm.num_t2lm_ie = 1;
+	frm.t2lm_ie[0].present = 1;
+
+	pe_debug("Sending a T2LM negotiation Request from " QDF_MAC_ADDR_FMT " to " QDF_MAC_ADDR_FMT,
+		 QDF_MAC_ADDR_REF(session->self_mac_addr),
+		 QDF_MAC_ADDR_REF(peer_mac));
+	pe_debug("Dialog token %d", frm.DialogToken.token);
+
+	status = dot11f_get_packed_t2lm_neg_reqSize(mac_ctx, &frm,
+						    &payload_size);
+	if (DOT11F_FAILED(status)) {
+		pe_err("Failed to calculate packed size for a T2LM negotiation Request (0x%08x).",
+		       status);
+		/* We'll fall back on the worst case scenario: */
+		payload_size = sizeof(tDot11ft2lm_neg_req);
+	} else if (DOT11F_WARNED(status)) {
+		pe_warn("There were warnings while calculating packed size for a T2LM negotiation Request (0x%08x).",
+			status);
+	}
+
+	num_bytes = payload_size + sizeof(*mgmt_hdr);
+	qdf_status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
+				      (void **)&pkt_ptr);
+	if (!QDF_IS_STATUS_SUCCESS(qdf_status) || (!pkt_ptr)) {
+		pe_err("Failed to allocate %d bytes for a T2LM req action frm",
+		       num_bytes);
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_mem_zero(frame_ptr, num_bytes);
+
+	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
+				SIR_MAC_MGMT_ACTION, peer_mac,
+				session->self_mac_addr);
+
+	/* Update A3 with the BSSID */
+	mgmt_hdr = (tpSirMacMgmtHdr)frame_ptr;
+	sir_copy_mac_addr(mgmt_hdr->bssId, session->bssId);
+	lim_set_protected_bit(mac_ctx, session, peer_mac, mgmt_hdr);
+
+	status = dot11f_pack_t2lm_neg_req(mac_ctx, &frm,
+					  frame_ptr + sizeof(tSirMacMgmtHdr),
+					  payload_size, &payload_size);
+
+	if (DOT11F_FAILED(status)) {
+		pe_err("Failed to pack a T2LM negotiation request (0x%08x)",
+		       status);
+		qdf_status = QDF_STATUS_E_FAILURE;
+		goto error_t2lm_req;
+	} else if (DOT11F_WARNED(status)) {
+		pe_warn("There were warnings while packing T2LM req (0x%08x)",
+			status);
+	}
+
+	pe_debug("Dump T2LM TX req action frame");
+	qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, frame_ptr,
+			   num_bytes);
+
+	if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) ||
+	    session->opmode == QDF_P2P_CLIENT_MODE ||
+	    session->opmode == QDF_P2P_GO_MODE)
+		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+
+	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+			 session->peSessionId, mgmt_hdr->fc.subType));
+	qdf_status = wma_tx_frame(mac_ctx, pkt_ptr, (uint16_t)num_bytes,
+				  TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+				  lim_tx_complete, frame_ptr, tx_flag,
+				  vdev_id, 0, RATEID_DEFAULT, 0);
+	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+			 session->peSessionId, qdf_status));
+	if (qdf_status != QDF_STATUS_SUCCESS) {
+		pe_err("wma_tx_frame FAILED! Status [%d]", qdf_status);
+		return QDF_STATUS_E_FAILURE;
+	} else {
+		return QDF_STATUS_SUCCESS;
+	}
+
+error_t2lm_req:
 	cds_packet_free((void *)pkt_ptr);
 	return qdf_status;
 }

+ 27 - 0
core/mac/src/pe/lim/lim_types.h

@@ -1462,6 +1462,23 @@ QDF_STATUS lim_send_delba_action_frame(struct mac_context *mac_ctx,
 				       uint8_t reason_code);
 
 #ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * lim_send_t2lm_action_req_frame() - Send T2LM negotiation request to peer
+ * @vdev: vdev pointer
+ * @peer_mac: Peer mac addr
+ * @args: Pointer to action frame args
+ * @ongoing_t2lm_neg: T2LM negotiation request
+ * @token: Dialog token
+ *
+ * Return: 0 for success, non-zero for failure
+ */
+QDF_STATUS
+lim_send_t2lm_action_req_frame(struct wlan_objmgr_vdev *vdev,
+			       uint8_t *peer_mac,
+			       struct wlan_action_frame_args *args,
+			       struct wlan_t2lm_onging_negotiation_info *t2lm_neg,
+			       uint8_t token);
+
 /**
  * lim_send_t2lm_action_rsp_frame() - Send T2LM negotiation response to peer
  * @mac_ctx: mac context
@@ -1487,6 +1504,16 @@ lim_send_t2lm_action_rsp_frame(struct mac_context *mac_ctx,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline QDF_STATUS
+lim_send_t2lm_action_req_frame(struct wlan_objmgr_vdev *vdev,
+			       uint8_t *peer_mac,
+			       struct wlan_action_frame_args *args,
+			       struct wlan_t2lm_onging_negotiation_info *t2lm_neg,
+			       uint8_t token)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 /**