Jelajahi Sumber

qcacld-3.0: Implement SWLM support for MULTI TX queue traffic

Currently SWLM is supported for single queue based traffic,
enhancing the SWLM to support multi queue based traffic.

Change-Id: If2d80e8122bbc972af0bba70e7a3f4c1da000c77
CRs-Fixed: 3161166
Karthik Kantamneni 3 tahun lalu
induk
melakukan
545b3b934e
2 mengubah file dengan 110 tambahan dan 87 penghapusan
  1. 96 75
      core/dp/txrx3.0/dp_swlm.c
  2. 14 12
      core/dp/txrx3.0/dp_swlm.h

+ 96 - 75
core/dp/txrx3.0/dp_swlm.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -26,6 +27,7 @@
  *				      and check if it passes the pre-set
  *				      threshold.
  * @soc: Datapath global soc handle
+ * @rid: TCL ring id
  *
  * This function calculates the current TX and RX throughput and checks
  * if it is above the pre-set thresholds by SWLM.
@@ -33,31 +35,31 @@
  * Returns: true, if the TX/RX throughput is passing the threshold
  *	    false, otherwise
  */
-static bool dp_swlm_is_tput_thresh_reached(struct dp_soc *soc)
+static bool dp_swlm_is_tput_thresh_reached(struct dp_soc *soc, uint8_t rid)
 {
-	struct dp_swlm *swlm = &soc->swlm;
-	static int prev_rx_bytes, prev_tx_bytes;
+	struct dp_swlm_params *params = &soc->swlm.params;
 	int rx_delta, tx_delta, tx_packet_delta;
-	static int prev_tx_packets;
 	bool result = false;
 
-	tx_delta = soc->stats.tx.egress.bytes - prev_tx_bytes;
-	prev_tx_bytes = soc->stats.tx.egress.bytes;
-	if (tx_delta > swlm->params.tcl.tx_traffic_thresh) {
-		swlm->params.tcl.sampling_session_tx_bytes = tx_delta;
+	tx_delta = soc->stats.tx.egress[rid].bytes -
+			params->tcl[rid].prev_tx_bytes;
+	params->tcl[rid].prev_tx_bytes = soc->stats.tx.egress[rid].bytes;
+	if (tx_delta > params->tx_traffic_thresh) {
+		params->tcl[rid].sampling_session_tx_bytes = tx_delta;
 		result = true;
 	}
 
-	rx_delta = soc->stats.rx.ingress.bytes - prev_rx_bytes;
-	prev_rx_bytes = soc->stats.rx.ingress.bytes;
-	if (!result && rx_delta > swlm->params.tcl.rx_traffic_thresh) {
-		swlm->params.tcl.sampling_session_tx_bytes = tx_delta;
+	rx_delta = soc->stats.rx.ingress.bytes - params->tcl[rid].prev_rx_bytes;
+	params->tcl[rid].prev_rx_bytes = soc->stats.rx.ingress.bytes;
+	if (!result && rx_delta > params->rx_traffic_thresh) {
+		params->tcl[rid].sampling_session_tx_bytes = tx_delta;
 		result = true;
 	}
 
-	tx_packet_delta = soc->stats.tx.egress.num - prev_tx_packets;
-	prev_tx_packets = soc->stats.tx.egress.num;
-	if (tx_packet_delta < swlm->params.tcl.tx_pkt_thresh)
+	tx_packet_delta = soc->stats.tx.egress[rid].num -
+		params->tcl[rid].prev_tx_packets;
+	params->tcl[rid].prev_tx_packets = soc->stats.tx.egress[rid].num;
+	if (tx_packet_delta < params->tx_pkt_thresh)
 		result = false;
 
 	return result;
@@ -85,43 +87,43 @@ dp_swlm_can_tcl_wr_coalesce(struct dp_soc *soc,
 	u64 curr_time = qdf_get_log_timestamp_usecs();
 	int tput_level_pass, coalesce = 0;
 	struct dp_swlm *swlm = &soc->swlm;
-	static int tput_pass_cnt;
-	static u64 expire_time;
+	uint8_t rid = tcl_data->ring_id;
+	struct dp_swlm_params *params = &soc->swlm.params;
 
-	if (curr_time >= expire_time) {
-		expire_time = qdf_get_log_timestamp_usecs() +
-			      swlm->params.tcl.sampling_time;
-		tput_level_pass = dp_swlm_is_tput_thresh_reached(soc);
+	if (curr_time >= params->tcl[rid].expire_time) {
+		params->tcl[rid].expire_time = qdf_get_log_timestamp_usecs() +
+			      params->sampling_time;
+		tput_level_pass = dp_swlm_is_tput_thresh_reached(soc, rid);
 		if (tput_level_pass) {
-			tput_pass_cnt++;
+			params->tcl[rid].tput_pass_cnt++;
 		} else {
-			tput_pass_cnt = 0;
-			DP_STATS_INC(swlm, tcl.tput_criteria_fail, 1);
+			params->tcl[rid].tput_pass_cnt = 0;
+			DP_STATS_INC(swlm, tcl[rid].tput_criteria_fail, 1);
 			goto coalescing_fail;
 		}
 	}
 
-	swlm->params.tcl.bytes_coalesced += qdf_nbuf_len(tcl_data->nbuf);
+	params->tcl[rid].bytes_coalesced += tcl_data->pkt_len;
 
-	if (tput_pass_cnt > DP_SWLM_TCL_TPUT_PASS_THRESH) {
+	if (params->tcl[rid].tput_pass_cnt > DP_SWLM_TCL_TPUT_PASS_THRESH) {
 		coalesce = 1;
-		if (swlm->params.tcl.bytes_coalesced >
-		    swlm->params.tcl.bytes_flush_thresh) {
+		if (params->tcl[rid].bytes_coalesced >
+		    params->tcl[rid].bytes_flush_thresh) {
 			coalesce = 0;
-			DP_STATS_INC(swlm, tcl.bytes_thresh_reached, 1);
-		} else if (curr_time > swlm->params.tcl.coalesce_end_time) {
+			DP_STATS_INC(swlm, tcl[rid].bytes_thresh_reached, 1);
+		} else if (curr_time > params->tcl[rid].coalesce_end_time) {
 			coalesce = 0;
-			DP_STATS_INC(swlm, tcl.time_thresh_reached, 1);
+			DP_STATS_INC(swlm, tcl[rid].time_thresh_reached, 1);
 		}
 	}
 
 coalescing_fail:
 	if (!coalesce) {
-		dp_swlm_tcl_reset_session_data(soc);
+		dp_swlm_tcl_reset_session_data(soc, rid);
 		return 0;
 	}
 
-	qdf_timer_mod(&swlm->params.tcl.flush_timer, 1);
+	qdf_timer_mod(&params->tcl[rid].flush_timer, 1);
 
 	return 1;
 }
@@ -129,22 +131,31 @@ coalescing_fail:
 QDF_STATUS dp_print_swlm_stats(struct dp_soc *soc)
 {
 	struct dp_swlm *swlm = &soc->swlm;
-
-	dp_info("TCL Coalescing stats:");
-	dp_info("Num coalesce success: %d", swlm->stats.tcl.coalesce_success);
-	dp_info("Num coalesce fail: %d", swlm->stats.tcl.coalesce_fail);
-	dp_info("Timer flush success: %d", swlm->stats.tcl.timer_flush_success);
-	dp_info("Timer flush fail: %d", swlm->stats.tcl.timer_flush_fail);
-	dp_info("Coalesce fail (TID): %d", swlm->stats.tcl.tid_fail);
-	dp_info("Coalesce fail (special frame): %d", swlm->stats.tcl.sp_frames);
-	dp_info("Coalesce fail (Low latency connection): %d",
-		swlm->stats.tcl.ll_connection);
-	dp_info("Coalesce fail (bytes thresh crossed): %d",
-		swlm->stats.tcl.bytes_thresh_reached);
-	dp_info("Coalesce fail (time thresh crossed): %d",
-		swlm->stats.tcl.time_thresh_reached);
-	dp_info("Coalesce fail (TPUT sampling fail): %d",
-		swlm->stats.tcl.tput_criteria_fail);
+	int i;
+
+	for (i = 0; i < soc->num_tcl_data_rings; i++) {
+		dp_info("TCL: %u Coalescing stats:", i);
+		dp_info("Num coalesce success: %d",
+			swlm->stats.tcl[i].coalesce_success);
+		dp_info("Num coalesce fail: %d",
+			swlm->stats.tcl[i].coalesce_fail);
+		dp_info("Timer flush success: %d",
+			swlm->stats.tcl[i].timer_flush_success);
+		dp_info("Timer flush fail: %d",
+			swlm->stats.tcl[i].timer_flush_fail);
+		dp_info("Coalesce fail (TID): %d",
+			swlm->stats.tcl[i].tid_fail);
+		dp_info("Coalesce fail (special frame): %d",
+			swlm->stats.tcl[i].sp_frames);
+		dp_info("Coalesce fail (Low latency connection): %d",
+			swlm->stats.tcl[i].ll_connection);
+		dp_info("Coalesce fail (bytes thresh crossed): %d",
+			swlm->stats.tcl[i].bytes_thresh_reached);
+		dp_info("Coalesce fail (time thresh crossed): %d",
+			swlm->stats.tcl[i].time_thresh_reached);
+		dp_info("Coalesce fail (TPUT sampling fail): %d",
+			swlm->stats.tcl[i].tput_criteria_fail);
+	}
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -161,10 +172,11 @@ static struct dp_swlm_ops dp_latency_mgr_ops = {
  */
 static void dp_swlm_tcl_flush_timer(void *arg)
 {
-	struct dp_soc *soc = arg;
+	struct dp_swlm_tcl_params *tcl = arg;
+	struct dp_soc *soc = tcl->soc;
 	struct dp_swlm *swlm = &soc->swlm;
 	hal_ring_handle_t hal_ring_hdl =
-				soc->tcl_data_ring[0].hal_srng;
+				soc->tcl_data_ring[tcl->ring_id].hal_srng;
 
 	if (hal_srng_try_access_start(soc->hal_soc, hal_ring_hdl) < 0)
 		goto fail;
@@ -177,14 +189,14 @@ static void dp_swlm_tcl_flush_timer(void *arg)
 		goto fail;
 	}
 
-	DP_STATS_INC(swlm, tcl.timer_flush_success, 1);
+	DP_STATS_INC(swlm, tcl[tcl->ring_id].timer_flush_success, 1);
 	hal_srng_access_end(soc->hal_soc, hal_ring_hdl);
 	hif_pm_runtime_put(soc->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE);
 
 	return;
 
 fail:
-	DP_STATS_INC(swlm, tcl.timer_flush_fail, 1);
+	DP_STATS_INC(swlm, tcl[tcl->ring_id].timer_flush_fail, 1);
 
 	return;
 }
@@ -199,19 +211,25 @@ fail:
 static inline QDF_STATUS dp_soc_swlm_tcl_attach(struct dp_soc *soc)
 {
 	struct dp_swlm *swlm = &soc->swlm;
-
-	swlm->params.tcl.rx_traffic_thresh = DP_SWLM_TCL_RX_TRAFFIC_THRESH;
-	swlm->params.tcl.tx_traffic_thresh = DP_SWLM_TCL_TX_TRAFFIC_THRESH;
-	swlm->params.tcl.sampling_time = DP_SWLM_TCL_TRAFFIC_SAMPLING_TIME;
-	swlm->params.tcl.bytes_flush_thresh = 0;
-	swlm->params.tcl.time_flush_thresh = DP_SWLM_TCL_TIME_FLUSH_THRESH;
-	swlm->params.tcl.tx_thresh_multiplier =
-					DP_SWLM_TCL_TX_THRESH_MULTIPLIER;
-	swlm->params.tcl.tx_pkt_thresh = DP_SWLM_TCL_TX_PKT_THRESH;
-
-	qdf_timer_init(soc->osdev, &swlm->params.tcl.flush_timer,
-		       dp_swlm_tcl_flush_timer, (void *)soc,
-		       QDF_TIMER_TYPE_WAKE_APPS);
+	int i;
+
+	swlm->params.rx_traffic_thresh = DP_SWLM_TCL_RX_TRAFFIC_THRESH;
+	swlm->params.tx_traffic_thresh = DP_SWLM_TCL_TX_TRAFFIC_THRESH;
+	swlm->params.sampling_time = DP_SWLM_TCL_TRAFFIC_SAMPLING_TIME;
+	swlm->params.time_flush_thresh = DP_SWLM_TCL_TIME_FLUSH_THRESH;
+	swlm->params.tx_thresh_multiplier = DP_SWLM_TCL_TX_THRESH_MULTIPLIER;
+	swlm->params.tx_pkt_thresh = DP_SWLM_TCL_TX_PKT_THRESH;
+
+	for (i = 0; i < soc->num_tcl_data_rings; i++) {
+		swlm->params.tcl[i].soc = soc;
+		swlm->params.tcl[i].ring_id = i;
+		swlm->params.tcl[i].bytes_flush_thresh = 0;
+		qdf_timer_init(soc->osdev,
+			       &swlm->params.tcl[i].flush_timer,
+			       dp_swlm_tcl_flush_timer,
+			       (void *)&swlm->params.tcl[i],
+			       QDF_TIMER_TYPE_WAKE_APPS);
+	}
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -219,16 +237,16 @@ static inline QDF_STATUS dp_soc_swlm_tcl_attach(struct dp_soc *soc)
 /**
  * dp_soc_swlm_tcl_detach() - detach the TCL resources for the software
  *			      latency manager.
- * @soc: Datapath global soc handle
+ * @swlm: SWLM data pointer
+ * @ring_id: TCL ring id
  *
  * Returns: QDF_STATUS
  */
-static inline QDF_STATUS dp_soc_swlm_tcl_detach(struct dp_soc *soc)
+static inline QDF_STATUS dp_soc_swlm_tcl_detach(struct dp_swlm *swlm,
+						uint8_t ring_id)
 {
-	struct dp_swlm *swlm = &soc->swlm;
-
-	qdf_timer_stop(&swlm->params.tcl.flush_timer);
-	qdf_timer_free(&swlm->params.tcl.flush_timer);
+	qdf_timer_stop(&swlm->params.tcl[ring_id].flush_timer);
+	qdf_timer_free(&swlm->params.tcl[ring_id].flush_timer);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -267,12 +285,15 @@ QDF_STATUS dp_soc_swlm_detach(struct dp_soc *soc)
 {
 	struct dp_swlm *swlm = &soc->swlm;
 	QDF_STATUS ret;
+	int i;
 
 	swlm->is_enabled = false;
 
-	ret = dp_soc_swlm_tcl_detach(soc);
-	if (QDF_IS_STATUS_ERROR(ret))
-		return ret;
+	for (i = 0; i < soc->num_tcl_data_rings; i++) {
+		ret = dp_soc_swlm_tcl_detach(swlm, i);
+		if (QDF_IS_STATUS_ERROR(ret))
+			return ret;
+	}
 
 	swlm->ops = NULL;
 

+ 14 - 12
core/dp/txrx3.0/dp_swlm.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -61,21 +62,22 @@ bool dp_tx_is_special_frame(qdf_nbuf_t nbuf, uint32_t frame_mask)
 /**
  * dp_swlm_tcl_reset_session_data() -  Reset the TCL coalescing session data
  * @soc: DP soc handle
+ * @ring_id: TCL ring id
  *
  * Returns QDF_STATUS
  */
 static inline QDF_STATUS
-dp_swlm_tcl_reset_session_data(struct dp_soc *soc)
+dp_swlm_tcl_reset_session_data(struct dp_soc *soc, uint8_t ring_id)
 {
-	struct dp_swlm *swlm = &soc->swlm;
+	struct dp_swlm_params *params = &soc->swlm.params;
 
-	swlm->params.tcl.coalesce_end_time = qdf_get_log_timestamp_usecs() +
-		     swlm->params.tcl.time_flush_thresh;
-	swlm->params.tcl.bytes_coalesced = 0;
-	swlm->params.tcl.bytes_flush_thresh =
-				swlm->params.tcl.sampling_session_tx_bytes *
-				swlm->params.tcl.tx_thresh_multiplier;
-	qdf_timer_sync_cancel(&swlm->params.tcl.flush_timer);
+	params->tcl[ring_id].coalesce_end_time = qdf_get_log_timestamp_usecs() +
+		params->time_flush_thresh;
+	params->tcl[ring_id].bytes_coalesced = 0;
+	params->tcl[ring_id].bytes_flush_thresh =
+				params->tcl[ring_id].sampling_session_tx_bytes *
+				params->tx_thresh_multiplier;
+	qdf_timer_sync_cancel(&params->tcl[ring_id].flush_timer);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -97,17 +99,17 @@ dp_swlm_tcl_pre_check(struct dp_soc *soc,
 				FRAME_MASK_IPV4_EAPOL | FRAME_MASK_IPV6_DHCP;
 
 	if (tcl_data->tid > DP_VO_TID) {
-		DP_STATS_INC(swlm, tcl.tid_fail, 1);
+		DP_STATS_INC(swlm, tcl[tcl_data->ring_id].tid_fail, 1);
 		goto fail;
 	}
 
 	if (dp_tx_is_special_frame(tcl_data->nbuf, frame_mask)) {
-		DP_STATS_INC(swlm, tcl.sp_frames, 1);
+		DP_STATS_INC(swlm, tcl[tcl_data->ring_id].sp_frames, 1);
 		goto fail;
 	}
 
 	if (tcl_data->num_ll_connections) {
-		DP_STATS_INC(swlm, tcl.ll_connection, 1);
+		DP_STATS_INC(swlm, tcl[tcl_data->ring_id].ll_connection, 1);
 		goto fail;
 	}