Pārlūkot izejas kodu

qcacmn: Add os_if changes for tdls management

Add os interface changes to send tdls management
frames to tdls component

Change-Id: Ib675e4b089a88ad618f918d9992a777c7221b34c
CRs-Fixed: 2034220
Kabilan Kannan 8 gadi atpakaļ
vecāks
revīzija
f3f11a78c3

+ 347 - 2
core/src/wlan_tdls_cmds_process.c

@@ -569,6 +569,244 @@ tdls_add_peer_serialize_callback(struct wlan_serialization_command *cmd,
 	return status;
 }
 
+void tdls_reset_nss(struct tdls_soc_priv_obj *tdls_soc,
+				  uint8_t action_code)
+{
+	if (!tdls_soc)
+		return;
+
+	if (TDLS_TEARDOWN != action_code ||
+		tdls_soc->tdls_nss_switch_in_progress)
+		return;
+
+	if (tdls_soc->tdls_teardown_peers_cnt != 0)
+		tdls_soc->tdls_teardown_peers_cnt--;
+	if (tdls_soc->tdls_teardown_peers_cnt == 0) {
+		if (tdls_soc->tdls_nss_transition_mode ==
+		    TDLS_NSS_TRANSITION_S_1x1_to_2x2) {
+			/* TDLS NSS switch is fully completed, so
+			 * reset the flags.
+			 */
+			tdls_notice("TDLS NSS switch is fully completed");
+			tdls_soc->tdls_nss_switch_in_progress = false;
+			tdls_soc->tdls_nss_teardown_complete = false;
+		} else {
+			/* TDLS NSS switch is not yet completed, but
+			 * tdls teardown is completed for all the
+			 * peers.
+			 */
+			tdls_notice("teardown done & NSS switch in progress");
+			tdls_soc->tdls_nss_teardown_complete = true;
+		}
+	}
+
+}
+
+/**
+ * tdls_set_cap() - set TDLS capability type
+ * @tdls_vdev: tdls vdev object
+ * @mac: peer mac address
+ * @cap: TDLS capability type
+ *
+ * Return: 0 if successful or negative errno otherwise
+ */
+int tdls_set_cap(struct tdls_vdev_priv_obj *tdls_vdev, const uint8_t *mac,
+			  enum tdls_peer_capab cap)
+{
+	struct tdls_peer *curr_peer;
+
+	curr_peer = tdls_get_peer(tdls_vdev, mac);
+	if (curr_peer == NULL) {
+		tdls_err("curr_peer is NULL");
+		return -EINVAL;
+	}
+
+	curr_peer->tdls_support = cap;
+	return 0;
+}
+
+static int tdls_validate_setup_frames(struct tdls_soc_priv_obj *tdls_soc,
+				struct tdls_validate_action_req *tdls_validate)
+{
+	/* supplicant still sends tdls_mgmt(SETUP_REQ)
+	 * even after we return error code at
+	 * 'add_station()'. Hence we have this check
+	 * again in addition to add_station().	Anyway,
+	 * there is no harm to double-check.
+	 */
+	if (TDLS_SETUP_REQUEST == tdls_validate->action_code) {
+		tdls_err(QDF_MAC_ADDRESS_STR " TDLS Max peer already connected. action (%d) declined. Num of peers (%d), Max allowed (%d).",
+			 QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
+			 tdls_validate->action_code,
+			 tdls_soc->connected_peer_count,
+			 tdls_soc->max_num_tdls_sta);
+		return -EINVAL;
+	}
+	/* maximum reached. tweak to send
+	 * error code to peer and return error
+	 * code to supplicant
+	 */
+	tdls_validate->status_code = QDF_STATUS_E_RESOURCES;
+	tdls_err(QDF_MAC_ADDRESS_STR " TDLS Max peer already connected, send response status (%d). Num of peers (%d), Max allowed (%d).",
+		 QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
+		 tdls_validate->action_code,
+		 tdls_soc->connected_peer_count,
+		 tdls_soc->max_num_tdls_sta);
+
+	tdls_validate->max_sta_failed = -EPERM;
+	return 0;
+}
+
+int tdls_validate_mgmt_request(struct tdls_validate_action_req *tdls_validate)
+{
+	struct tdls_vdev_priv_obj *tdls_vdev;
+	struct tdls_soc_priv_obj *tdls_soc;
+	struct tdls_peer *curr_peer;
+	struct tdls_peer *temp_peer;
+	QDF_STATUS status;
+
+
+	if (!tdls_validate || !tdls_validate->vdev)
+		return -EINVAL;
+
+	if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(tdls_validate->vdev,
+							&tdls_vdev,
+							&tdls_soc))
+		return -ENOTSUPP;
+
+	/*
+	 * STA or P2P client should be connected and authenticated before
+	 *  sending any TDLS frames
+	 */
+	if (!tdls_is_vdev_connected(tdls_validate->vdev) ||
+	    !tdls_is_vdev_authenticated(tdls_validate->vdev)) {
+		tdls_err("STA is not connected or not authenticated.");
+		return -EAGAIN;
+	}
+
+	/* other than teardown frame, mgmt frames are not sent if disabled */
+	if (TDLS_TEARDOWN != tdls_validate->action_code) {
+		if (!tdls_check_is_tdls_allowed(tdls_validate->vdev)) {
+			tdls_err("TDLS not allowed, reject MGMT, action = %d",
+				tdls_validate->action_code);
+			return -EPERM;
+		}
+		/* if tdls_mode is disabled, then decline the peer's request */
+		if (TDLS_SUPPORT_DISABLED == tdls_soc->tdls_current_mode ||
+		    TDLS_SUPPORT_SUSPENDED == tdls_soc->tdls_current_mode) {
+			tdls_notice(QDF_MAC_ADDRESS_STR
+				" TDLS mode is disabled. action %d declined.",
+				QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
+				tdls_validate->action_code);
+			return -ENOTSUPP;
+		}
+		if (tdls_soc->tdls_nss_switch_in_progress) {
+			tdls_err("nss switch in progress, action %d declined "
+				QDF_MAC_ADDRESS_STR,
+				tdls_validate->action_code,
+				QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac));
+			return -EAGAIN;
+		}
+	}
+
+	if (TDLS_IS_SETUP_ACTION(tdls_validate->action_code)) {
+		if (NULL != tdls_is_progress(tdls_vdev,
+			tdls_validate->peer_mac, true)) {
+			tdls_err("setup is ongoing. action %d declined for "
+				 QDF_MAC_ADDRESS_STR,
+				 tdls_validate->action_code,
+				 QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac));
+			return -EPERM;
+		}
+	}
+
+	/*
+	 * Discard TDLS Discovery request and setup confirm if violates
+	 * ACM rules
+	 */
+	if ((TDLS_DISCOVERY_REQUEST == tdls_validate->action_code ||
+		TDLS_SETUP_CONFIRM == tdls_validate->action_code)) {
+		/*  call hdd_wmm_is_acm_allowed() */
+		if (!tdls_soc->tdls_wmm_cb(&tdls_vdev->vdev)) {
+			tdls_err("admission ctrl set to VI, action %d declined",
+				 tdls_validate->action_code);
+			return -EPERM;
+		}
+	}
+
+
+	if (TDLS_SETUP_REQUEST == tdls_validate->action_code ||
+	    TDLS_SETUP_RESPONSE == tdls_validate->action_code) {
+		if (tdls_soc->max_num_tdls_sta <=
+			tdls_soc->connected_peer_count) {
+			status = tdls_validate_setup_frames(tdls_soc,
+							    tdls_validate);
+			if (QDF_STATUS_SUCCESS != status)
+				return status;
+			/* fall through to send setup resp
+			 * with failure status code
+			 */
+		} else {
+			curr_peer =
+				tdls_find_peer(tdls_vdev,
+					       tdls_validate->peer_mac);
+			if (curr_peer) {
+				if (TDLS_IS_LINK_CONNECTED(curr_peer)) {
+					tdls_err(QDF_MAC_ADDRESS_STR " already connected action %d declined.",
+						QDF_MAC_ADDR_ARRAY(
+						tdls_validate->peer_mac),
+						tdls_validate->action_code);
+
+					return -EPERM;
+				}
+			}
+		}
+	}
+
+	tdls_notice("tdls_mgmt" QDF_MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %zu",
+		   QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
+		   tdls_validate->action_code, tdls_validate->dialog_token,
+		   tdls_validate->status_code, tdls_validate->len);
+
+	/*Except teardown responder will not be used so just make 0 */
+	tdls_validate->responder = 0;
+	if (TDLS_TEARDOWN == tdls_validate->action_code) {
+		temp_peer = tdls_find_peer(tdls_vdev, tdls_validate->peer_mac);
+		if (!temp_peer) {
+			tdls_err(QDF_MAC_ADDRESS_STR " peer doesn't exist",
+				     QDF_MAC_ADDR_ARRAY(
+				     tdls_validate->peer_mac));
+			return -EPERM;
+		}
+
+		if (TDLS_IS_LINK_CONNECTED(temp_peer))
+			tdls_validate->responder = temp_peer->is_responder;
+		else {
+			tdls_err(QDF_MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, tdls_validate->len = %zu",
+				 QDF_MAC_ADDR_ARRAY(tdls_validate->peer_mac),
+				 temp_peer->link_status,
+				 tdls_validate->dialog_token,
+				 tdls_validate->status_code,
+				 tdls_validate->len);
+			return -EPERM;
+		}
+	}
+
+	/* For explicit trigger of DIS_REQ come out of BMPS for
+	 * successfully receiving DIS_RSP from peer.
+	 */
+	if ((TDLS_SETUP_RESPONSE == tdls_validate->action_code) ||
+	    (TDLS_SETUP_CONFIRM == tdls_validate->action_code) ||
+	    (TDLS_DISCOVERY_RESPONSE == tdls_validate->action_code) ||
+	    (TDLS_DISCOVERY_REQUEST == tdls_validate->action_code)) {
+		/* Fw will take care if PS offload is enabled. */
+		if (TDLS_DISCOVERY_REQUEST != tdls_validate->action_code)
+			tdls_set_cap(tdls_vdev, tdls_validate->peer_mac,
+					      TDLS_CAP_SUPPORTED);
+	}
+	return 0;
+}
+
 QDF_STATUS tdls_process_add_peer(struct tdls_add_peer_request *req)
 {
 	struct wlan_serialization_command cmd = {0,};
@@ -1000,6 +1238,105 @@ error:
 	return status;
 }
 
+/**
+ * tdls_process_send_mgmt_rsp() - handle response for send mgmt
+ * @rsp: TDLS send mgmt response
+ *
+ * Return: QDF_STATUS_SUCCESS for success; other values if failed
+ */
+QDF_STATUS tdls_process_send_mgmt_rsp(struct tdls_send_mgmt_rsp *rsp)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_psoc *psoc;
+	struct tdls_vdev_priv_obj *tdls_vdev;
+	struct tdls_soc_priv_obj *tdls_soc = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct tdls_osif_indication ind;
+
+	psoc = rsp->psoc;
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, rsp->session_id,
+						    WLAN_TDLS_SB_ID);
+	if (!vdev) {
+		tdls_err("invalid vdev");
+		status =  QDF_STATUS_E_INVAL;
+		qdf_mem_free(rsp);
+		return status;
+	}
+	tdls_soc = wlan_psoc_get_tdls_soc_obj(psoc);
+	tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
+	if (!tdls_soc || !tdls_vdev) {
+		tdls_err("soc object:%p, vdev object:%p", tdls_soc, tdls_vdev);
+		status = QDF_STATUS_E_FAILURE;
+	}
+
+	tdls_release_serialization_command(vdev, WLAN_SER_CMD_TDLS_SEND_MGMT);
+
+	if (legacy_result_success == rsp->status_code)
+		goto free_rsp;
+	tdls_err("send mgmt failed. status code(=%d)", rsp->status_code);
+	status = QDF_STATUS_E_FAILURE;
+
+	if (tdls_soc && tdls_soc->tdls_event_cb) {
+		ind.vdev = vdev;
+		ind.status = rsp->status_code;
+		tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data,
+				       TDLS_EVENT_MGMT_TX_ACK_CNF, &ind);
+	}
+
+free_rsp:
+	qdf_mem_free(rsp);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
+	return status;
+}
+
+/**
+ * tdls_send_mgmt_tx_completion() - process tx completion
+ * @tx_complete: TDLS mgmt completion info
+ *
+ * Return: QDF_STATUS_SUCCESS for success; other values if failed
+ */
+QDF_STATUS tdls_send_mgmt_tx_completion(
+			struct tdls_mgmt_tx_completion_ind *tx_complete)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_psoc *psoc;
+	struct tdls_vdev_priv_obj *tdls_vdev;
+	struct tdls_soc_priv_obj *tdls_soc = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct tdls_osif_indication ind;
+
+	psoc = tx_complete->psoc;
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+						    tx_complete->session_id,
+						    WLAN_TDLS_SB_ID);
+
+	if (!vdev) {
+		tdls_err("invalid vdev");
+		status =  QDF_STATUS_E_INVAL;
+		goto free_tx_complete;
+	}
+
+	tdls_soc = wlan_psoc_get_tdls_soc_obj(psoc);
+	tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
+
+	if (!tdls_soc || !tdls_vdev) {
+		tdls_err("soc object:%p, vdev object:%p", tdls_soc, tdls_vdev);
+		status = QDF_STATUS_E_FAILURE;
+	}
+
+	if (tdls_soc && tdls_soc->tdls_event_cb) {
+		ind.vdev = vdev;
+		ind.status = tx_complete->tx_complete_status;
+		tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data,
+			       TDLS_EVENT_MGMT_TX_ACK_CNF, &ind);
+	}
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
+free_tx_complete:
+	qdf_mem_free(tx_complete);
+	return status;
+}
+
 /**
  * tdls_add_peer_rsp() - handle response for add TDLS peer
  * @rsp: TDLS add peer response
@@ -1139,10 +1476,12 @@ QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp)
 			tdls_debug(QDF_MAC_ADDRESS_STR " status is %d",
 				   QDF_MAC_ADDR_ARRAY(macaddr),
 				   curr_peer->link_status);
+
 			wlan_vdev_obj_lock(vdev);
 			id = wlan_vdev_get_id(vdev);
 			wlan_vdev_obj_unlock(vdev);
-			if (TDLS_IS_CONNECTED(curr_peer)) {
+
+			if (TDLS_IS_LINK_CONNECTED(curr_peer)) {
 				soc_obj->tdls_dereg_tl_peer(
 					soc_obj->tdls_tl_peer_data,
 					id, curr_peer->sta_id);
@@ -1464,6 +1803,10 @@ static QDF_STATUS tdls_config_force_peer(
 
 	tdls_set_callback(peer, req->callback);
 
+	tdls_set_ct_mode(soc_obj->soc);
+	if (soc_obj->enable_tdls_connection_tracker)
+		tdls_implicit_enable(vdev_obj);
+
 	return status;
 error:
 	qdf_mem_free(peer_update_param);
@@ -1605,8 +1948,10 @@ QDF_STATUS tdls_process_remove_force_peer(struct tdls_oper_request *req)
 		qdf_mem_free(peer_update_param);
 		goto error;
 	}
+	tdls_set_ct_mode(soc_obj->soc);
+	if (!soc_obj->enable_tdls_connection_tracker)
+		tdls_implicit_disable(vdev_obj);
 
-	/*TODO set tdls connection tracker state*/
 error:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
 	qdf_mem_free(req);

+ 98 - 0
core/src/wlan_tdls_cmds_process.h

@@ -25,6 +25,11 @@
 #ifndef _WLAN_TDLS_CMDS_PROCESS_H_
 #define _WLAN_TDLS_CMDS_PROCESS_H_
 
+#define TDLS_IS_SETUP_ACTION(action) \
+	((TDLS_SETUP_REQUEST <= action) && \
+	(TDLS_SETUP_CONFIRM >= action))
+
+
 /**
  * enum tdls_add_oper - add peer type
  * @TDLS_OPER_NONE: none
@@ -37,6 +42,53 @@ enum tdls_add_oper {
 	TDLS_OPER_UPDATE
 };
 
+/**
+ * enum legacy_result_code - defined to comply with tSirResultCodes, need refine
+ *                           when mlme converged.
+ * @legacy_result_success: success
+ * @legacy_result_max: max result value
+ */
+enum legacy_result_code {
+	legacy_result_success,
+	legacy_result_max = 0x7FFFFFFF
+};
+
+/**
+ * struct tdls_send_mgmt_rsp - TDLS Response struct PE --> TDLS module
+ *                           same as struct tSirSmeRsp
+ * @message_type: message type eWNI_SME_TDLS_SEND_MGMT_RSP
+ * @length: message length
+ * @session_id: session id
+ * @transaction_id: transaction id
+ * @status_code: status code as tSirResultCodes
+ * @psoc: soc object
+ */
+struct tdls_send_mgmt_rsp {
+	uint16_t message_type;
+	uint16_t length;
+	uint8_t session_id;
+	uint16_t transaction_id;
+	enum legacy_result_code status_code;
+	struct wlan_objmgr_psoc *psoc;
+};
+
+/**
+ * struct tdls_mgmt_tx_completion_ind - TDLS TX completion PE --> TDLS module
+ *                           same as struct sSirMgmtTxCompletionInd
+ * @message_type: message type eWNI_SME_MGMT_FRM_TX_COMPLETION_IND
+ * @length: message length
+ * @session_id: session id
+ * @tx_complete_status: tx complete status
+ * @psoc: soc object
+ */
+struct tdls_mgmt_tx_completion_ind {
+	uint16_t message_type;
+	uint16_t length;
+	uint8_t session_id;      /* Session ID */
+	uint32_t tx_complete_status;
+	struct wlan_objmgr_psoc *psoc;
+};
+
 /**
  * struct tdls_add_sta_req - TDLS request struct TDLS module --> PE
  *                           same as struct tSirTdlsAddStaReq;
@@ -213,6 +265,52 @@ QDF_STATUS tdls_pe_del_peer(struct tdls_del_peer_request *req);
  */
 QDF_STATUS tdls_process_add_peer_rsp(struct tdls_add_sta_rsp *rsp);
 
+/**
+ * tdls_reset_nss() - reset tdls nss parameters
+ * @tdls_soc: TDLS soc object
+ * @action_code: action code
+ *
+ * Return: None
+ */
+void tdls_reset_nss(struct tdls_soc_priv_obj *tdls_soc,
+				  uint8_t action_code);
+
+/**
+ * tdls_set_cap() - set TDLS capability type
+ * @tdls_vdev: tdls vdev object
+ * @mac: peer mac address
+ * @cap: TDLS capability type
+ *
+ * Return: 0 if successful or negative errno otherwise
+ */
+int tdls_set_cap(struct tdls_vdev_priv_obj *tdls_vdev, const uint8_t *mac,
+			  enum tdls_peer_capab cap);
+
+/**
+ * tdls_validate_mgmt_request() -validate mgmt request
+ * @tdls_validate: action frame request
+ *
+ * Return: 0 for success or -EINVAL otherwise
+ */
+int tdls_validate_mgmt_request(struct tdls_validate_action_req *tdls_validate);
+
+/**
+ * tdls_process_send_mgmt_rsp() - handle response for send mgmt
+ * @rsp: TDLS send mgmt response
+ *
+ * Return: QDF_STATUS_SUCCESS for success; other values if failed
+ */
+QDF_STATUS tdls_process_send_mgmt_rsp(struct tdls_send_mgmt_rsp *rsp);
+
+/**
+ * tdls_send_mgmt_tx_completion() - process tx completion
+ * @tx_complete: TDLS mgmt completion info
+ *
+ * Return: QDF_STATUS_SUCCESS for success; other values if failed
+ */
+QDF_STATUS tdls_send_mgmt_tx_completion(
+			struct tdls_mgmt_tx_completion_ind *tx_complete);
+
 /**
  * tdls_process_add_peer_rsp() - handle response for delete TDLS peer
  * @rsp: TDLS delete peer response

+ 21 - 0
core/src/wlan_tdls_ct.c

@@ -52,6 +52,27 @@ bool tdls_is_vdev_connected(struct wlan_objmgr_vdev *vdev)
 	return true;
 }
 
+bool tdls_is_vdev_authenticated(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_objmgr_peer *peer;
+	bool is_authenticated = false;
+
+	wlan_vdev_obj_lock(vdev);
+	peer = wlan_vdev_get_bsspeer(vdev);
+	wlan_vdev_obj_unlock(vdev);
+
+	if (!peer) {
+		tdls_err("peer is null");
+		return false;
+	}
+
+	wlan_peer_obj_lock(peer);
+	is_authenticated = wlan_peer_mlme_get_auth_state(peer);
+	wlan_peer_obj_unlock(peer);
+
+	return is_authenticated;
+}
+
 /**
  * tdls_peer_reset_discovery_processed() - reset discovery status
  * @tdls_vdev: TDLS vdev object

+ 17 - 0
core/src/wlan_tdls_ct.h

@@ -155,4 +155,21 @@ void tdls_discovery_timeout_peer_cb(void *user_data);
  * Return: Void
  */
 void tdls_implicit_disable(struct tdls_vdev_priv_obj *tdls_vdev);
+
+/**
+ * tdls_is_vdev_connected() -check the vdev connection
+ * @vdev: vdev oobject
+ *
+ * Return: true or false
+ */
+bool tdls_is_vdev_connected(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * tdls_is_vdev_authenticated() -check the vdev authentication state
+ * @vdev: vdev oobject
+ *
+ * Return: true or false
+ */
+bool tdls_is_vdev_authenticated(struct wlan_objmgr_vdev *vdev);
+
 #endif

+ 2 - 0
core/src/wlan_tdls_main.c

@@ -30,6 +30,8 @@
 #include "wlan_tdls_tgt_api.h"
 #include "wlan_policy_mgr_public_struct.h"
 #include "wlan_policy_mgr_api.h"
+#include "wlan_scan_ucfg_api.h"
+
 
 /* Global tdls soc pvt object
  * this is useful for some functions which does not receive either vdev or psoc

+ 6 - 1
core/src/wlan_tdls_main.h

@@ -34,6 +34,7 @@
 #include <wlan_tdls_public_structs.h>
 #include <scheduler_api.h>
 #include "wlan_serialization_api.h"
+#include "wlan_tdls_mgmt.h"
 
 /* Bit mask flag for tdls_option to FW */
 #define ENA_TDLS_OFFCHAN      (1 << 0)  /* TDLS Off Channel support */
@@ -74,7 +75,7 @@
 #define tdls_alert(format, args...) \
 	tdls_logfl(QDF_TRACE_LEVEL_FATAL, format, ## args)
 
-#define TDLS_IS_CONNECTED(peer)  \
+#define TDLS_IS_LINK_CONNECTED(peer)  \
 	((TDLS_LINK_CONNECTED == (peer)->link_status) || \
 	 (TDLS_LINK_TEARING == (peer)->link_status))
 
@@ -203,6 +204,10 @@ struct tdls_soc_priv_obj {
 	enum tdls_nss_transition_state tdls_nss_transition_mode;
 	int32_t tdls_teardown_peers_cnt;
 	struct tdls_set_state_info set_state_info;
+	tdls_rx_callback tdls_rx_cb;
+	void *tdls_rx_cb_data;
+	tdls_wmm_check tdls_wmm_cb;
+	void *tdls_wmm_cb_data;
 	tdls_tx_ack_cnf_callback tdls_tx_cnf_cb;
 	void *tx_ack_cnf_cb_data;
 	tdls_evt_callback tdls_event_cb;

+ 2 - 3
core/src/wlan_tdls_mgmt.c

@@ -113,7 +113,6 @@ static QDF_STATUS tdls_process_rx_mgmt(
 			tdls_set_rssi(tdls_vdev, mac, rx_mgmt->rx_rssi);
 	}
 
-
 	if (rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET] ==
 	    TDLS_ACTION_FRAME) {
 		action_frame_type =
@@ -127,7 +126,7 @@ static QDF_STATUS tdls_process_rx_mgmt(
 		}
 	}
 
-	/* tdls_soc_obj->tdls_rx_cb ==> wlan_tdls_rx_callback() */
+	/* tdls_soc_obj->tdls_rx_cb ==> wlan_cfg80211_tdls_rx_callback() */
 	if (tdls_soc_obj && tdls_soc_obj->tdls_rx_cb)
 		tdls_soc_obj->tdls_rx_cb(tdls_soc_obj->tdls_rx_cb_data,
 					 rx_mgmt);
@@ -157,7 +156,6 @@ QDF_STATUS tdls_process_rx_frame(struct scheduler_msg *msg)
 
 	if (vdev) {
 		tdls_debug("tdls rx mgmt frame received");
-
 		tdls_vdev = wlan_objmgr_vdev_get_comp_private_obj(vdev,
 							WLAN_UMAC_COMP_TDLS);
 		if (tdls_vdev)
@@ -175,6 +173,7 @@ QDF_STATUS tdls_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
 	bool isregister)
 {
 	struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info[3];
+
 	QDF_STATUS status;
 	int num_of_entries;
 

+ 39 - 0
core/src/wlan_tdls_mgmt.h

@@ -28,6 +28,24 @@
 /* default tdls serialize timeout is set to 10 secs */
 #define TDLS_DEFAULT_SERIALIZE_CMD_TIMEOUT  10000
 
+#define TDLS_PUBLIC_ACTION_FRAME_OFFSET 24
+#define TDLS_PUBLIC_ACTION_FRAME 4
+#define TDLS_PUBLIC_ACTION_DISC_RESP 14
+#define TDLS_ACTION_FRAME 12
+#define TDLS_80211_PEER_ADDR_OFFSET (TDLS_PUBLIC_ACTION_FRAME + \
+				     QDF_MAC_ADDR_SIZE)
+#define TDLS_ACTION_FRAME_TYPE_MAX 11
+
+/**
+ * struct tdls_rx_mgmt_event - tdls rx mgmt frame event
+ * @tdls_soc_obj: tdls soc private object
+ * @rx_mgmt: tdls rx mgmt frame structure
+ */
+struct tdls_rx_mgmt_event {
+	struct tdls_soc_priv_obj *tdls_soc_obj;
+	struct tdls_rx_mgmt_frame *rx_mgmt;
+};
+
 /*
  * struct tdls_send_mgmt_request - tdls management request
  * @message_type: type of pe message
@@ -70,5 +88,26 @@ struct tdls_send_mgmt_request {
  */
 QDF_STATUS tdls_process_mgmt_req(
 			struct tdls_action_frame_request *tdls_mgmt_req);
+
+/**
+ * tdls_mgmt_rx_ops() - register or unregister rx callback
+ * @psoc: psoc object
+ * @isregister: register if true, unregister if false
+ *
+ * This function registers or unregisters rx callback to mgmt txrx
+ * component.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tdls_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
+	bool isregister);
+
+/**
+ * tdls_process_rx_frame() - process tdls rx frames
+ * @msg: scheduler msg
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tdls_process_rx_frame(struct scheduler_msg *msg);
 #endif
 

+ 4 - 2
dispatcher/inc/wlan_tdls_public_structs.h

@@ -29,6 +29,8 @@
 #include <qdf_mc_timer.h>
 #include <wlan_cmn.h>
 #include <wlan_cmn_ieee80211.h>
+#include <wlan_objmgr_psoc_obj.h>
+
 
 #define WLAN_TDLS_STA_MAX_NUM                        8
 #define WLAN_TDLS_STA_P_UAPSD_OFFCHAN_MAX_NUM        1
@@ -59,7 +61,7 @@
 #define WAIT_TIME_TDLS_LINK_ESTABLISH_REQ      1500
 
 /** Maximum time(ms) to wait for tdls mgmt to complete **/
-#define WAIT_TIME_TDLS_MGMT         11000
+#define WAIT_TIME_FOR_TDLS_MGMT         11000
 
 #define TDLS_TEARDOWN_PEER_UNREACHABLE   25
 #define TDLS_TEARDOWN_PEER_UNSPEC_REASON 26
@@ -252,7 +254,7 @@ enum tdls_event_msg_type {
 	TDLS_SHOULD_DISCOVER = 0,
 	TDLS_SHOULD_TEARDOWN,
 	TDLS_PEER_DISCONNECTED,
-	TDLS_CONNECTION_TRACKER_NOTIFY,
+	TDLS_CONNECTION_TRACKER_NOTIFY
 };
 
 /**

+ 35 - 0
dispatcher/inc/wlan_tdls_tgt_api.h

@@ -67,6 +67,22 @@ QDF_STATUS tgt_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
 QDF_STATUS tgt_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc,
 			      struct sta_uapsd_trig_params *params);
 
+/**
+ * tgt_tdls_send_mgmt_rsp() - process tdls mgmt response
+ * @pmsg: sheduler msg
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tgt_tdls_send_mgmt_rsp(struct scheduler_msg *pmsg);
+
+/**
+ * tgt_tdls_send_mgmt_tx_completion() -process tx completion message
+ * @pmsg: sheduler msg
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tgt_tdls_send_mgmt_tx_completion(struct scheduler_msg *pmsg);
+
 /**
  * tgt_tdls_del_peer_rsp() - handle TDLS del peer response
  * @pmsg: sheduler msg
@@ -111,4 +127,23 @@ QDF_STATUS tgt_tdls_unregister_ev_handler(struct wlan_objmgr_psoc *psoc);
 QDF_STATUS
 tgt_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
 		       struct tdls_event_info *info);
+
+/**
+ * tgt_tdls_mgmt_frame_rx_cb() - callback for rx mgmt frame
+ * @psoc: soc context
+ * @peer: peer context
+ * @buf: rx buffer
+ * @mgmt_rx_params: mgmt rx parameters
+ * @frm_type: frame type
+ *
+ * This function gets called from mgmt tx/rx component when rx mgmt
+ * received.
+ *
+ * Return: QDF_STATUS_SUCCESS
+ */
+QDF_STATUS tgt_tdls_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
+	struct wlan_objmgr_peer *peer, qdf_nbuf_t buf,
+	struct mgmt_rx_event_params *mgmt_rx_params,
+	enum mgmt_frame_type frm_type);
+
 #endif

+ 151 - 0
dispatcher/src/wlan_tdls_tgt_api.c

@@ -87,6 +87,36 @@ QDF_STATUS tgt_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS tgt_tdls_send_mgmt_tx_completion(struct scheduler_msg *pmsg)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (!pmsg || !pmsg->bodyptr) {
+		tdls_err("msg: 0x%p", pmsg);
+		QDF_ASSERT(0);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	status = tdls_send_mgmt_tx_completion(pmsg->bodyptr);
+
+	return status;
+}
+
+QDF_STATUS tgt_tdls_send_mgmt_rsp(struct scheduler_msg *pmsg)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (!pmsg || !pmsg->bodyptr) {
+		tdls_err("msg: 0x%p", pmsg);
+		QDF_ASSERT(0);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	status = tdls_process_send_mgmt_rsp(pmsg->bodyptr);
+
+	return status;
+}
+
 QDF_STATUS tgt_tdls_add_peer_rsp(struct scheduler_msg *pmsg)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -183,3 +213,124 @@ tgt_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
 
 	return status;
 }
+
+static
+QDF_STATUS tgt_tdls_mgmt_frame_process_rx_cb(
+			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_peer *peer,
+			qdf_nbuf_t buf,
+			struct mgmt_rx_event_params *mgmt_rx_params,
+			enum mgmt_frame_type frm_type)
+{
+	struct tdls_rx_mgmt_frame *rx_mgmt;
+	struct tdls_rx_mgmt_event *rx_mgmt_event;
+	struct tdls_soc_priv_obj *tdls_soc_obj;
+	struct scheduler_msg msg;
+	struct wlan_objmgr_vdev *vdev;
+	uint32_t vdev_id;
+	uint8_t *pdata;
+	QDF_STATUS status;
+
+	tdls_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
+			WLAN_UMAC_COMP_TDLS);
+	if (!tdls_soc_obj) {
+		tdls_err("tdls ctx is NULL, drop this frame");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!peer) {
+		vdev = tdls_get_vdev(psoc, WLAN_TDLS_SB_ID);
+		if (!vdev) {
+			tdls_err("current tdls vdev is null, can't get vdev id");
+			return QDF_STATUS_E_FAILURE;
+		}
+		wlan_vdev_obj_lock(vdev);
+		vdev_id = wlan_vdev_get_id(vdev);
+		wlan_vdev_obj_unlock(vdev);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
+	} else {
+		wlan_peer_obj_lock(peer);
+		vdev = wlan_peer_get_vdev(peer);
+		wlan_peer_obj_unlock(peer);
+		if (!vdev) {
+			tdls_err("vdev is NULL in peer, drop this frame");
+			return QDF_STATUS_E_FAILURE;
+		}
+		wlan_vdev_obj_lock(vdev);
+		vdev_id = wlan_vdev_get_id(vdev);
+		wlan_vdev_obj_unlock(vdev);
+	}
+
+	rx_mgmt_event = qdf_mem_malloc(sizeof(*rx_mgmt_event));
+	if (!rx_mgmt_event) {
+		tdls_err("Failed to allocate rx mgmt event");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	rx_mgmt = qdf_mem_malloc(sizeof(*rx_mgmt) +
+			mgmt_rx_params->buf_len);
+	if (!rx_mgmt) {
+		tdls_err("Failed to allocate rx mgmt frame");
+		qdf_mem_free(rx_mgmt_event);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	pdata = (uint8_t *)qdf_nbuf_data(buf);
+	rx_mgmt->frame_len = mgmt_rx_params->buf_len;
+	rx_mgmt->rx_chan = mgmt_rx_params->channel;
+	rx_mgmt->vdev_id = vdev_id;
+	rx_mgmt->frm_type = frm_type;
+	rx_mgmt->rx_rssi = mgmt_rx_params->rssi;
+
+	rx_mgmt_event->rx_mgmt = rx_mgmt;
+	rx_mgmt_event->tdls_soc_obj = tdls_soc_obj;
+	qdf_mem_copy(rx_mgmt->buf, pdata, mgmt_rx_params->buf_len);
+	msg.type = TDLS_EVENT_RX_MGMT;
+	msg.bodyptr = rx_mgmt_event;
+	msg.callback = tdls_process_rx_frame;
+	status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
+
+	qdf_nbuf_free(buf);
+
+	return status;
+}
+
+QDF_STATUS tgt_tdls_mgmt_frame_rx_cb(
+			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_peer *peer,
+			qdf_nbuf_t buf,
+			struct mgmt_rx_event_params *mgmt_rx_params,
+			enum mgmt_frame_type frm_type)
+{
+	QDF_STATUS status;
+
+	tdls_debug("psoc:%p, peer:%p, type:%d", psoc, peer, frm_type);
+
+
+	if (!buf) {
+		tdls_err("rx frame buff is null buf:%p", buf);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (!mgmt_rx_params || !psoc) {
+		tdls_err("input is NULL mgmt_rx_params:%p psoc:%p, peer:%p",
+			  mgmt_rx_params, psoc, peer);
+		status = QDF_STATUS_E_INVAL;
+		goto release_nbuf;
+	}
+
+	status = wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_SB_ID);
+	if (QDF_STATUS_SUCCESS != status)
+		goto release_nbuf;
+
+	status = tgt_tdls_mgmt_frame_process_rx_cb(psoc, peer, buf,
+						   mgmt_rx_params, frm_type);
+
+	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
+
+	if (QDF_STATUS_SUCCESS != status)
+release_nbuf:
+		qdf_nbuf_free(buf);
+	return status;
+}
+

+ 14 - 1
dispatcher/src/wlan_tdls_ucfg_api.c

@@ -194,6 +194,12 @@ QDF_STATUS ucfg_tdls_update_config(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	soc_obj->tdls_rx_cb = req->tdls_rx_cb;
+	soc_obj->tdls_rx_cb_data = req->tdls_rx_cb_data;
+
+	soc_obj->tdls_wmm_cb = req->tdls_wmm_cb;
+	soc_obj->tdls_wmm_cb_data = req->tdls_wmm_cb_data;
+
 	soc_obj->tdls_event_cb = req->tdls_event_cb;
 	soc_obj->tdls_evt_cb_data = req->tdls_evt_cb_data;
 
@@ -256,9 +262,14 @@ QDF_STATUS ucfg_tdls_psoc_enable(struct wlan_objmgr_psoc *psoc)
 					tdls_scan_serialization_comp_info_cb);
 	if (QDF_STATUS_SUCCESS != status) {
 		tdls_err("Serialize scan cmd register failed ");
-		status = QDF_STATUS_E_FAILURE;
+		return status;
 	}
 
+	/* register callbacks with tx/rx mgmt */
+	status = tdls_mgmt_rx_ops(psoc, true);
+	if (status != QDF_STATUS_SUCCESS)
+		tdls_err("Failed to register mgmt rx callback, status:%d",
+			status);
 	return status;
 }
 
@@ -647,4 +658,6 @@ void ucfg_tdls_update_tx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
 	tdls_update_tx_pkt_cnt(vdev, mac_addr);
 
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
+
 }
+