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
Este commit está contenido en:

cometido por
Madan Koyyalamudi

padre
4ceea0ebe4
commit
545b3b934e
@@ -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(¶ms->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;
|
||||
int i;
|
||||
|
||||
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);
|
||||
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;
|
||||
int i;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
qdf_timer_init(soc->osdev, &swlm->params.tcl.flush_timer,
|
||||
dp_swlm_tcl_flush_timer, (void *)soc,
|
||||
QDF_TIMER_TYPE_WAKE_APPS);
|
||||
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;
|
||||
|
||||
|
@@ -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(¶ms->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;
|
||||
}
|
||||
|
||||
|
Referencia en una nueva incidencia
Block a user