Browse Source

qcacld-3.0: Increment TDLS discovery attempts after tx completion

TDLS peer discovery count is incremented every time after
TDLS discovery frame is queued for the peer till max attempts
are reached. But sometimes due to host or firmware scan the
frames could get flushed and still the discovery attempts
counter is incremented resulting in reduced possibility of
discovering the peer.

So increment TDLS discovery attempts after successful
tx completion of the TDLS discovery frames.

CRs-Fixed: 3647289
Change-Id: I7e3fe1973b34276ed5ea20a7114f3635ed59c6ef
Pragaspathi Thilagaraj 1 year ago
parent
commit
3d6edc5fb8

+ 22 - 20
components/tdls/core/src/wlan_tdls_ct.c

@@ -816,8 +816,8 @@ void tdls_ct_idle_handler(void *user_data)
  */
 static void
 tdls_ct_process_idle_and_discovery(struct tdls_peer *curr_peer,
-				struct tdls_vdev_priv_obj *tdls_vdev_obj,
-				struct tdls_soc_priv_obj *tdls_soc_obj)
+				   struct tdls_vdev_priv_obj *tdls_vdev_obj,
+				   struct tdls_soc_priv_obj *tdls_soc_obj)
 {
 	uint16_t valid_peers;
 
@@ -942,10 +942,10 @@ static void tdls_ct_process_cap_unknown(struct tdls_peer *curr_peer,
 					struct tdls_vdev_priv_obj *tdls_vdev,
 					struct tdls_soc_priv_obj *tdls_soc)
 {
-	if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(
-			tdls_soc->tdls_configs.tdls_feature_flags) &&
-			(!curr_peer->is_forced_peer))
-			return;
+	if (!curr_peer->is_forced_peer &&
+	    TDLS_IS_EXTERNAL_CONTROL_ENABLED(
+				tdls_soc->tdls_configs.tdls_feature_flags))
+		return;
 
 	if (curr_peer->rx_pkt || curr_peer->tx_pkt)
 		tdls_debug(QDF_MAC_ADDR_FMT "link_status %d tdls_support %d tx %d rx %d vdev %d",
@@ -954,29 +954,31 @@ static void tdls_ct_process_cap_unknown(struct tdls_peer *curr_peer,
 			   curr_peer->tx_pkt, curr_peer->rx_pkt,
 			   wlan_vdev_get_id(tdls_vdev->vdev));
 
-	if (!TDLS_IS_LINK_CONNECTED(curr_peer) &&
-	    ((curr_peer->tx_pkt + curr_peer->rx_pkt) >=
-	    tdls_vdev->threshold_config.tx_packet_n)) {
-		/* Ignore discovery attempt if External Control is enabled, that
+	if (TDLS_IS_LINK_CONNECTED(curr_peer))
+		return;
+
+	if ((curr_peer->tx_pkt + curr_peer->rx_pkt) >=
+	     tdls_vdev->threshold_config.tx_packet_n) {
+		/*
+		 * Ignore discovery attempt if External Control is enabled, that
 		 * is, peer is forced. In that case, continue discovery attempt
 		 * regardless attempt count
 		 */
 		tdls_debug("TDLS UNKNOWN pre discover ");
 		if (curr_peer->is_forced_peer ||
-			curr_peer->discovery_attempt++ <
+		    curr_peer->discovery_attempt <
 		    tdls_vdev->threshold_config.discovery_tries_n) {
 			tdls_debug("TDLS UNKNOWN discover ");
 			tdls_vdev->curr_candidate = curr_peer;
 			tdls_implicit_send_discovery_request(tdls_vdev);
-		} else {
-			if (curr_peer->link_status != TDLS_LINK_CONNECTING) {
-				curr_peer->tdls_support =
-						TDLS_CAP_NOT_SUPPORTED;
-				tdls_set_peer_link_status(
-						curr_peer,
-						TDLS_LINK_IDLE,
-						TDLS_LINK_NOT_SUPPORTED);
-			}
+
+			return;
+		}
+
+		if (curr_peer->link_status != TDLS_LINK_CONNECTING) {
+			curr_peer->tdls_support = TDLS_CAP_NOT_SUPPORTED;
+			tdls_set_peer_link_status(curr_peer, TDLS_LINK_IDLE,
+						  TDLS_LINK_NOT_SUPPORTED);
 		}
 	}
 }

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

@@ -1550,6 +1550,37 @@ tdls_process_sta_connect(struct tdls_sta_notify_params *notify)
 	return QDF_STATUS_SUCCESS;
 }
 
+static void
+tdls_update_discovery_tries(struct wlan_objmgr_vdev *vdev)
+{
+	struct tdls_soc_priv_obj *soc_obj;
+	struct tdls_vdev_priv_obj *vdev_obj;
+	struct tdls_user_config *tdls_config;
+	struct tdls_config_params *vdev_config;
+	QDF_STATUS status;
+
+	status = tdls_get_vdev_objects(vdev, &vdev_obj, &soc_obj);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		tdls_err("can't get vdev_obj & soc_obj");
+		return;
+	}
+
+	vdev_config = &vdev_obj->threshold_config;
+	tdls_config = &soc_obj->tdls_configs;
+
+	vdev_config->discovery_tries_n =
+			tdls_config->tdls_max_discovery_attempt;
+
+	/*
+	 * For MLO peer discovery will happen on 2 links and the best link
+	 * will be chosen based on score for TDLS. So factor that into the
+	 * number of discovery attempts to increase the discoverability
+	 * window for the peer.
+	 */
+	if (wlan_vdev_mlme_is_mlo_vdev(vdev))
+		vdev_config->discovery_tries_n *= 2;
+}
+
 QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify)
 {
 	QDF_STATUS status;
@@ -1566,6 +1597,8 @@ QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify)
 	}
 
 	status = tdls_process_sta_connect(notify);
+	if (QDF_IS_STATUS_SUCCESS(status))
+		tdls_update_discovery_tries(notify->vdev);
 
 	wlan_objmgr_vdev_release_ref(notify->vdev, WLAN_TDLS_NB_ID);
 	qdf_mem_free(notify);

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

@@ -473,6 +473,8 @@ wlan_vdev_get_tdls_vdev_obj(struct wlan_objmgr_vdev *vdev)
  * @mac: mac address of tdls peer
  * @link_state: tdls link state
  * @link_reason: reason
+ *
+ * Return: None
  */
 void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev,
 			  const uint8_t *mac,

+ 0 - 9
components/tdls/core/src/wlan_tdls_peer.c

@@ -821,15 +821,6 @@ static void tdls_update_pmo_status(struct tdls_vdev_priv_obj *tdls_vdev,
 }
 #endif
 
-/**
- * tdls_set_link_status() - set link statue for TDLS peer
- * @vdev_obj: TDLS vdev object
- * @mac: MAC address of current TDLS peer
- * @link_status: link status
- * @link_reason: reason with link status
- *
- * Return: None.
- */
 void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev_obj,
 			  const uint8_t *mac,
 			  enum tdls_link_state link_status,

+ 19 - 0
components/tdls/dispatcher/inc/wlan_tdls_api.h

@@ -193,6 +193,19 @@ void wlan_tdls_handle_p2p_client_connect(struct wlan_objmgr_psoc *psoc,
 					 struct wlan_objmgr_vdev *vdev)
 {}
 #endif /* WLAN_FEATURE_TDLS_CONCURRENCIES */
+
+/**
+ * wlan_tdls_increment_discovery_attempts() - Increment TDLS peer discovery
+ * attempts
+ * @psoc: Pointer to PSOC object
+ * @vdev_id: Vdev id
+ * @peer_addr: Peer mac address
+ *
+ * Return: None
+ */
+void wlan_tdls_increment_discovery_attempts(struct wlan_objmgr_psoc *psoc,
+					    uint8_t vdev_id,
+					    uint8_t *peer_addr);
 #else
 
 #ifdef FEATURE_SET
@@ -267,5 +280,11 @@ void wlan_tdls_handle_p2p_client_connect(struct wlan_objmgr_psoc *psoc,
 static inline
 void wlan_tdls_notify_start_bss_failure(struct wlan_objmgr_psoc *psoc)
 {}
+
+static inline
+void wlan_tdls_increment_discovery_attempts(struct wlan_objmgr_psoc *psoc,
+					    uint8_t vdev_id,
+					    uint8_t *peer_addr)
+{}
 #endif
 #endif

+ 37 - 0
components/tdls/dispatcher/src/wlan_tdls_api.c

@@ -26,6 +26,7 @@
 #include "../../core/src/wlan_tdls_main.h"
 #include "../../core/src/wlan_tdls_ct.h"
 #include "../../core/src/wlan_tdls_mgmt.h"
+#include "wlan_tdls_peer.h"
 #include <wlan_objmgr_global_obj.h>
 #include <wlan_objmgr_cmn.h>
 #include "wlan_tdls_cfg_api.h"
@@ -470,3 +471,39 @@ void wlan_tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
 {
 	tdls_update_rx_pkt_cnt(vdev, mac_addr, dest_mac_addr);
 }
+
+void wlan_tdls_increment_discovery_attempts(struct wlan_objmgr_psoc *psoc,
+					    uint8_t vdev_id,
+					    uint8_t *peer_addr)
+{
+	struct tdls_soc_priv_obj *tdls_soc_obj;
+	struct tdls_vdev_priv_obj *tdls_vdev_obj;
+	struct tdls_peer *peer;
+	struct wlan_objmgr_vdev *vdev;
+	QDF_STATUS status;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_TDLS_NB_ID);
+	if (!vdev)
+		return;
+
+	status = tdls_get_vdev_objects(vdev, &tdls_vdev_obj, &tdls_soc_obj);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		tdls_err("Failed to get TDLS objects");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
+		return;
+	}
+
+	peer = tdls_get_peer(tdls_vdev_obj, peer_addr);
+	if (!peer) {
+		tdls_err("tdls_peer is NULL");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
+		return;
+	}
+
+	peer->discovery_attempt++;
+	tdls_debug("vdev:%d peer discovery attempts:%d", vdev_id,
+		   peer->discovery_attempt);
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
+}

+ 48 - 9
core/mac/src/pe/lim/lim_process_tdls.c

@@ -98,6 +98,21 @@ static const uint8_t eth_890d_header[] = {
 	0x00, 0x00, 0x89, 0x0d,
 };
 
+#define ETH_ADDR_LEN 6 /* bytes */
+
+struct tdls_ethernet_hdr {
+	uint8_t dest_addr[ETH_ADDR_LEN];
+	uint8_t src_addr[ETH_ADDR_LEN];
+} qdf_packed;
+
+#define eth_890d_hdr_len 2 /* bytes */
+
+static const uint8_t eth_890d_tdls_discvory_frm_hdr[] = {
+	0x89, 0x0d, 0x02, 0x0c, 0x0a,
+};
+
+#define TDLS_ETHR_HDR_LEN (sizeof(struct tdls_ethernet_hdr))
+
 /*
  * type of links used in TDLS
  */
@@ -547,21 +562,45 @@ static uint32_t lim_prepare_tdls_frame_header(struct mac_context *mac, uint8_t *
  * @tx_complete: indicates tx success/failure
  * @params: tx completion params
  *
- * function will be invoked on receiving tx completion indication
+ * Function will be invoked on receiving tx completion indication
  *
- * return: success: eHAL_STATUS_SUCCESS failure: eHAL_STATUS_FAILURE
+ * Return: success: eHAL_STATUS_SUCCESS failure: eHAL_STATUS_FAILURE
  */
-static QDF_STATUS lim_mgmt_tdls_tx_complete(void *context,
-					    qdf_nbuf_t buf,
-					    uint32_t tx_complete,
-					    void *params)
+static QDF_STATUS lim_mgmt_tdls_tx_complete(void *context, qdf_nbuf_t buf,
+					    uint32_t tx_complete, void *params)
 {
 	struct mac_context *mac_ctx = (struct mac_context *)context;
+	struct tdls_ethernet_hdr *ethernet_hdr;
+	tpSirMacActionFrameHdr action_hdr;
+	bool is_tdls_discvory_frm;
 
 	pe_debug("tdls_frm_session_id: %x tx_complete: %x",
-		mac_ctx->lim.tdls_frm_session_id, tx_complete);
+		 mac_ctx->lim.tdls_frm_session_id, tx_complete);
 
 	if (NO_SESSION != mac_ctx->lim.tdls_frm_session_id) {
+		if (buf &&
+		    (qdf_nbuf_len(buf) >= (TDLS_ETHR_HDR_LEN +
+					  eth_890d_hdr_len +
+					  PAYLOAD_TYPE_TDLS_SIZE +
+					  sizeof(*action_hdr)))) {
+			ethernet_hdr =
+				(struct tdls_ethernet_hdr *)qdf_nbuf_data(buf);
+			is_tdls_discvory_frm =
+				!qdf_mem_cmp(((uint8_t *)qdf_nbuf_data(buf) +
+				TDLS_ETHR_HDR_LEN),
+				eth_890d_tdls_discvory_frm_hdr,
+				sizeof(eth_890d_tdls_discvory_frm_hdr));
+
+			pe_debug("is_tdls_discvory_frm: %d",
+				 is_tdls_discvory_frm);
+			if (is_tdls_discvory_frm &&
+			    tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK)
+				wlan_tdls_increment_discovery_attempts(
+					mac_ctx->psoc,
+					mac_ctx->lim.tdls_frm_session_id,
+					ethernet_hdr->dest_addr);
+		}
+
 		lim_send_sme_mgmt_tx_completion(mac_ctx,
 				mac_ctx->lim.tdls_frm_session_id,
 				tx_complete);
@@ -3886,8 +3925,8 @@ lim_send_tdls_comp_mgmt_rsp(struct mac_context *mac_ctx, uint16_t msg_type,
 	struct tdls_send_mgmt_rsp *sme_rsp;
 	QDF_STATUS status;
 
-	pe_debug("Sending message %s with reasonCode %s",
-		lim_msg_str(msg_type), lim_result_code_str(result_code));
+	pe_debug("vdev:%d Sending message %s with reasonCode %s", vdev_id,
+		 lim_msg_str(msg_type), lim_result_code_str(result_code));
 
 	sme_rsp = qdf_mem_malloc(sizeof(*sme_rsp));
 	if (!sme_rsp)

+ 2 - 0
core/wma/inc/wma.h

@@ -1124,12 +1124,14 @@ enum frame_index {
  * @sub_type: sub type
  * @status: status
  * @ack_cmp_work: work structure
+ * @frame: frame nbuf
  */
 struct wma_tx_ack_work_ctx {
 	tp_wma_handle wma_handle;
 	uint16_t sub_type;
 	int32_t status;
 	qdf_work_t ack_cmp_work;
+	qdf_nbuf_t frame;
 };
 
 /**

+ 52 - 27
core/wma/src/wma_data.c

@@ -963,23 +963,27 @@ static void wma_data_tx_ack_work_handler(void *ack_work)
 	wma_handle = work->wma_handle;
 	if (!wma_handle || cds_is_load_or_unload_in_progress()) {
 		wma_err("Driver load/unload in progress");
-		goto end;
+		goto free_frame;
 	}
+
+	wma_debug("Data Tx Ack Cb Status %d", work->status);
 	ack_cb = wma_handle->umac_data_ota_ack_cb;
+	if (!ack_cb) {
+		wma_err("Data Tx Ack Cb is NULL");
+		goto free_frame;
+	}
 
-	if (work->status)
-		wma_debug("Data Tx Ack Cb Status %d", work->status);
-	else
-		wma_debug("Data Tx Ack Cb Status %d", work->status);
+	ack_cb(wma_handle->mac_context, work->frame, work->status,
+	       NULL);
+	goto end;
 
-	/* Call the Ack Cb registered by UMAC */
-	if (ack_cb)
-		ack_cb(wma_handle->mac_context, NULL, work->status, NULL);
-	else
-		wma_err("Data Tx Ack Cb is NULL");
+free_frame:
+	if (work->frame)
+		qdf_nbuf_free(work->frame);
 
 end:
 	qdf_mem_free(work);
+
 	if (wma_handle) {
 		wma_handle->umac_data_ota_ack_cb = NULL;
 		wma_handle->last_umac_data_nbuf = NULL;
@@ -1002,38 +1006,59 @@ void
 wma_data_tx_ack_comp_hdlr(void *wma_context, qdf_nbuf_t netbuf, int32_t status)
 {
 	tp_wma_handle wma_handle = (tp_wma_handle) wma_context;
+	struct wma_tx_ack_work_ctx *ack_work;
+	QDF_STATUS qdf_status;
 
 	if (wma_validate_handle(wma_handle))
 		return;
 
+	if (!netbuf) {
+		wma_debug("netbuf is NULL");
+		return;
+	}
+
 	/*
 	 * if netBuf does not match with pending nbuf then just free the
 	 * netbuf and do not call ack cb
 	 */
 	if (wma_handle->last_umac_data_nbuf != netbuf) {
-		if (wma_handle->umac_data_ota_ack_cb) {
-			wma_err("nbuf does not match but umac_data_ota_ack_cb is not null");
-		} else {
-			wma_err("nbuf does not match and umac_data_ota_ack_cb is also null");
-		}
+		wma_err("nbuf does not match but umac_data_ota_ack_cb is %s null",
+			wma_handle->umac_data_ota_ack_cb ? "not" : "");
 		goto free_nbuf;
 	}
 
-	if (wma_handle->umac_data_ota_ack_cb) {
-		struct wma_tx_ack_work_ctx *ack_work;
+	if (!wma_handle->umac_data_ota_ack_cb) {
+		wma_err_rl("ota_ack cb not registered");
+		goto free_nbuf;
+	}
 
-		ack_work = qdf_mem_malloc(sizeof(struct wma_tx_ack_work_ctx));
+	ack_work = qdf_mem_malloc(sizeof(struct wma_tx_ack_work_ctx));
+	if (ack_work) {
 		wma_handle->ack_work_ctx = ack_work;
-		if (ack_work) {
-			ack_work->wma_handle = wma_handle;
-			ack_work->sub_type = 0;
-			ack_work->status = status;
-
-			qdf_create_work(0, &ack_work->ack_cmp_work,
-					wma_data_tx_ack_work_handler,
-					ack_work);
-			qdf_sched_work(0, &ack_work->ack_cmp_work);
+
+		ack_work->wma_handle = wma_handle;
+		ack_work->sub_type = 0;
+		ack_work->status = status;
+		ack_work->frame = netbuf;
+
+		/*
+		 * free of the netbuf will be done by the scheduled work so
+		 * just do unmap here
+		 */
+		qdf_nbuf_unmap_single(wma_handle->qdf_dev, netbuf,
+				      QDF_DMA_TO_DEVICE);
+
+		qdf_status = qdf_create_work(0, &ack_work->ack_cmp_work,
+					     wma_data_tx_ack_work_handler,
+					     ack_work);
+		if (QDF_IS_STATUS_ERROR(qdf_status)) {
+			qdf_nbuf_free(netbuf);
+			wma_err("Failed to create TX ack work");
+			return;
 		}
+
+		qdf_sched_work(0, &ack_work->ack_cmp_work);
+		return;
 	}
 
 free_nbuf:

+ 3 - 0
core/wma/src/wma_main.c

@@ -4813,6 +4813,9 @@ QDF_STATUS wma_stop(void)
 
 	if (wma_handle->ack_work_ctx) {
 		cds_flush_work(&wma_handle->ack_work_ctx->ack_cmp_work);
+		if (wma_handle->ack_work_ctx->frame)
+			qdf_nbuf_free(wma_handle->ack_work_ctx->frame);
+
 		qdf_mem_free(wma_handle->ack_work_ctx);
 		wma_handle->ack_work_ctx = NULL;
 	}