qcacld-3.0: Refactor TX/RX tuning in bus BW worker
Refactor tuning done in hdd_pld_request_bus_bandwidth for TX and RX. Change-Id: I1e994394d286c3152b5a01f3e0747e06d56e811b CRs-Fixed: 3045963
This commit is contained in:

committed by
Madan Koyyalamudi

parent
2f5862c059
commit
1b920619fb
@@ -10065,6 +10065,165 @@ static inline void hdd_low_tput_gro_flush_skip_handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_bus_bandwidth_work_tune_rx() - Function to tune for RX
|
||||||
|
* @hdd_ctx - handle to hdd context
|
||||||
|
* @rx_packets - receive packet count in last bus bandwidth interval
|
||||||
|
* @next_rx_level - pointer to next_rx_level to be filled
|
||||||
|
* @is_rx_pm_qos_high - pointer indicating if high qos is needed, to be filled
|
||||||
|
*
|
||||||
|
* The function tunes various aspects of the driver based on a running average
|
||||||
|
* of RX packets received in last bus bandwidth interval.
|
||||||
|
*
|
||||||
|
* Returns: true if RX level has changed, else returns false
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
bool hdd_bus_bandwidth_work_tune_rx(struct hdd_context *hdd_ctx,
|
||||||
|
const uint64_t rx_packets,
|
||||||
|
enum wlan_tp_level *next_rx_level,
|
||||||
|
bool *is_rx_pm_qos_high)
|
||||||
|
{
|
||||||
|
bool rx_level_change = false;
|
||||||
|
bool rxthread_high_tput_req;
|
||||||
|
uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
|
||||||
|
uint64_t avg_rx;
|
||||||
|
uint64_t no_rx_offload_pkts, avg_no_rx_offload_pkts;
|
||||||
|
uint64_t rx_offload_pkts, avg_rx_offload_pkts;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Includes tcp+udp, if perf core is required for tcp, then
|
||||||
|
* perf core is also required for udp.
|
||||||
|
*/
|
||||||
|
no_rx_offload_pkts = hdd_ctx->no_rx_offload_pkt_cnt;
|
||||||
|
hdd_ctx->no_rx_offload_pkt_cnt = 0;
|
||||||
|
rx_offload_pkts = rx_packets - no_rx_offload_pkts;
|
||||||
|
|
||||||
|
avg_no_rx_offload_pkts = (no_rx_offload_pkts +
|
||||||
|
hdd_ctx->prev_no_rx_offload_pkts) / 2;
|
||||||
|
hdd_ctx->prev_no_rx_offload_pkts = no_rx_offload_pkts;
|
||||||
|
|
||||||
|
avg_rx_offload_pkts = (rx_offload_pkts +
|
||||||
|
hdd_ctx->prev_rx_offload_pkts) / 2;
|
||||||
|
hdd_ctx->prev_rx_offload_pkts = rx_offload_pkts;
|
||||||
|
|
||||||
|
avg_rx = avg_no_rx_offload_pkts + avg_rx_offload_pkts;
|
||||||
|
/*
|
||||||
|
* Takes care to set Rx_thread affinity for below case
|
||||||
|
* 1)LRO/GRO not supported ROME case
|
||||||
|
* 2)when rx_ol is disabled in cases like concurrency etc
|
||||||
|
* 3)For UDP cases
|
||||||
|
*/
|
||||||
|
if (avg_no_rx_offload_pkts > hdd_ctx->config->bus_bw_high_threshold) {
|
||||||
|
rxthread_high_tput_req = true;
|
||||||
|
*is_rx_pm_qos_high = true;
|
||||||
|
} else {
|
||||||
|
rxthread_high_tput_req = false;
|
||||||
|
*is_rx_pm_qos_high = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cds_sched_handle_throughput_req(rxthread_high_tput_req))
|
||||||
|
hdd_warn("Rx thread high_tput(%d) affinity request failed",
|
||||||
|
rxthread_high_tput_req);
|
||||||
|
|
||||||
|
/* fine-tuning parameters for RX Flows */
|
||||||
|
if (avg_rx > hdd_ctx->config->tcp_delack_thres_high) {
|
||||||
|
if (hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH &&
|
||||||
|
++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt) {
|
||||||
|
*next_rx_level = WLAN_SVC_TP_HIGH;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hdd_ctx->rx_high_ind_cnt = 0;
|
||||||
|
*next_rx_level = WLAN_SVC_TP_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdd_ctx->cur_rx_level != *next_rx_level) {
|
||||||
|
struct wlan_rx_tp_data rx_tp_data = {0};
|
||||||
|
|
||||||
|
hdd_ctx->cur_rx_level = *next_rx_level;
|
||||||
|
rx_level_change = true;
|
||||||
|
/* Send throughput indication only if it is enabled.
|
||||||
|
* Disabling tcp_del_ack will revert the tcp stack behavior
|
||||||
|
* to default delayed ack. Note that this will disable the
|
||||||
|
* dynamic delayed ack mechanism across the system
|
||||||
|
*/
|
||||||
|
if (hdd_ctx->en_tcp_delack_no_lro)
|
||||||
|
rx_tp_data.rx_tp_flags |= TCP_DEL_ACK_IND;
|
||||||
|
|
||||||
|
if (hdd_ctx->config->enable_tcp_adv_win_scale)
|
||||||
|
rx_tp_data.rx_tp_flags |= TCP_ADV_WIN_SCL;
|
||||||
|
|
||||||
|
rx_tp_data.level = *next_rx_level;
|
||||||
|
wlan_hdd_update_tcp_rx_param(hdd_ctx, &rx_tp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rx_level_change;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_bus_bandwidth_work_tune_tx() - Function to tune for TX
|
||||||
|
* @hdd_ctx - handle to hdd context
|
||||||
|
* @tx_packets - transmit packet count in last bus bandwidth interval
|
||||||
|
* @next_tx_level - pointer to next_tx_level to be filled
|
||||||
|
* @is_tx_pm_qos_high - pointer indicating if high qos is needed, to be filled
|
||||||
|
*
|
||||||
|
* The function tunes various aspects of the driver based on a running average
|
||||||
|
* of TX packets received in last bus bandwidth interval.
|
||||||
|
*
|
||||||
|
* Returns: true if TX level has changed, else returns false
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
bool hdd_bus_bandwidth_work_tune_tx(struct hdd_context *hdd_ctx,
|
||||||
|
const uint64_t tx_packets,
|
||||||
|
enum wlan_tp_level *next_tx_level,
|
||||||
|
bool *is_tx_pm_qos_high)
|
||||||
|
{
|
||||||
|
bool tx_level_change = false;
|
||||||
|
uint64_t no_tx_offload_pkts, avg_no_tx_offload_pkts;
|
||||||
|
uint64_t tx_offload_pkts, avg_tx_offload_pkts;
|
||||||
|
uint64_t avg_tx;
|
||||||
|
|
||||||
|
no_tx_offload_pkts = hdd_ctx->no_tx_offload_pkt_cnt;
|
||||||
|
hdd_ctx->no_tx_offload_pkt_cnt = 0;
|
||||||
|
tx_offload_pkts = tx_packets - no_tx_offload_pkts;
|
||||||
|
|
||||||
|
avg_no_tx_offload_pkts = (no_tx_offload_pkts +
|
||||||
|
hdd_ctx->prev_no_tx_offload_pkts) / 2;
|
||||||
|
hdd_ctx->prev_no_tx_offload_pkts = no_tx_offload_pkts;
|
||||||
|
|
||||||
|
avg_tx_offload_pkts = (tx_offload_pkts +
|
||||||
|
hdd_ctx->prev_tx_offload_pkts) / 2;
|
||||||
|
hdd_ctx->prev_tx_offload_pkts = tx_offload_pkts;
|
||||||
|
|
||||||
|
avg_tx = avg_no_tx_offload_pkts + avg_tx_offload_pkts;
|
||||||
|
|
||||||
|
/* fine-tuning parameters for TX Flows */
|
||||||
|
hdd_ctx->prev_tx = tx_packets;
|
||||||
|
|
||||||
|
if (avg_no_tx_offload_pkts >
|
||||||
|
hdd_ctx->config->bus_bw_high_threshold)
|
||||||
|
*is_tx_pm_qos_high = true;
|
||||||
|
else
|
||||||
|
*is_tx_pm_qos_high = false;
|
||||||
|
|
||||||
|
if (avg_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
|
||||||
|
*next_tx_level = WLAN_SVC_TP_HIGH;
|
||||||
|
else
|
||||||
|
*next_tx_level = WLAN_SVC_TP_LOW;
|
||||||
|
|
||||||
|
if (hdd_ctx->config->enable_tcp_limit_output &&
|
||||||
|
hdd_ctx->cur_tx_level != *next_tx_level) {
|
||||||
|
struct wlan_tx_tp_data tx_tp_data = {0};
|
||||||
|
|
||||||
|
hdd_ctx->cur_tx_level = *next_tx_level;
|
||||||
|
tx_level_change = true;
|
||||||
|
tx_tp_data.level = *next_tx_level;
|
||||||
|
tx_tp_data.tcp_limit_output = true;
|
||||||
|
wlan_hdd_update_tcp_tx_param(hdd_ctx, &tx_tp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx_level_change;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
|
* hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
|
||||||
* @hdd_ctx - handle to hdd context
|
* @hdd_ctx - handle to hdd context
|
||||||
@@ -10076,30 +10235,22 @@ static inline void hdd_low_tput_gro_flush_skip_handler(
|
|||||||
*
|
*
|
||||||
* Returns: None
|
* Returns: None
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx,
|
static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx,
|
||||||
const uint64_t tx_packets,
|
const uint64_t tx_packets,
|
||||||
const uint64_t rx_packets)
|
const uint64_t rx_packets)
|
||||||
{
|
{
|
||||||
uint16_t index = 0;
|
uint16_t index;
|
||||||
bool vote_level_change = false;
|
bool vote_level_change = false;
|
||||||
bool rx_level_change = false;
|
bool rx_level_change;
|
||||||
bool tx_level_change = false;
|
bool tx_level_change;
|
||||||
bool rxthread_high_tput_req = false;
|
|
||||||
bool dptrace_high_tput_req;
|
bool dptrace_high_tput_req;
|
||||||
u64 total_pkts = tx_packets + rx_packets;
|
u64 total_pkts = tx_packets + rx_packets;
|
||||||
uint64_t avg_tx = 0, avg_rx = 0;
|
|
||||||
uint64_t no_rx_offload_pkts = 0, avg_no_rx_offload_pkts = 0;
|
|
||||||
uint64_t rx_offload_pkts = 0, avg_rx_offload_pkts = 0;
|
|
||||||
uint64_t no_tx_offload_pkts = 0, avg_no_tx_offload_pkts = 0;
|
|
||||||
uint64_t tx_offload_pkts = 0, avg_tx_offload_pkts = 0;
|
|
||||||
enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_IDLE;
|
enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_IDLE;
|
||||||
static enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
|
static enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
|
||||||
enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
|
enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
|
||||||
uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
|
|
||||||
cpumask_t pm_qos_cpu_mask;
|
cpumask_t pm_qos_cpu_mask;
|
||||||
bool is_rx_pm_qos_high = false;
|
bool is_rx_pm_qos_high;
|
||||||
bool is_tx_pm_qos_high = false;
|
bool is_tx_pm_qos_high;
|
||||||
enum tput_level tput_level;
|
enum tput_level tput_level;
|
||||||
struct bbm_params param = {0};
|
struct bbm_params param = {0};
|
||||||
bool legacy_client = false;
|
bool legacy_client = false;
|
||||||
@@ -10107,6 +10258,9 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx,
|
|||||||
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
|
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
|
||||||
static enum tput_level prev_tput_level = TPUT_LEVEL_NONE;
|
static enum tput_level prev_tput_level = TPUT_LEVEL_NONE;
|
||||||
|
|
||||||
|
if (!soc)
|
||||||
|
return;
|
||||||
|
|
||||||
cpumask_clear(&pm_qos_cpu_mask);
|
cpumask_clear(&pm_qos_cpu_mask);
|
||||||
|
|
||||||
if (hdd_ctx->high_bus_bw_request) {
|
if (hdd_ctx->high_bus_bw_request) {
|
||||||
@@ -10234,113 +10388,18 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx,
|
|||||||
|
|
||||||
qdf_dp_trace_apply_tput_policy(dptrace_high_tput_req);
|
qdf_dp_trace_apply_tput_policy(dptrace_high_tput_req);
|
||||||
|
|
||||||
/*
|
rx_level_change = hdd_bus_bandwidth_work_tune_rx(hdd_ctx,
|
||||||
* Includes tcp+udp, if perf core is required for tcp, then
|
rx_packets,
|
||||||
* perf core is also required for udp.
|
&next_rx_level,
|
||||||
*/
|
&is_rx_pm_qos_high);
|
||||||
no_rx_offload_pkts = hdd_ctx->no_rx_offload_pkt_cnt;
|
|
||||||
hdd_ctx->no_rx_offload_pkt_cnt = 0;
|
|
||||||
rx_offload_pkts = rx_packets - no_rx_offload_pkts;
|
|
||||||
|
|
||||||
avg_no_rx_offload_pkts = (no_rx_offload_pkts +
|
tx_level_change = hdd_bus_bandwidth_work_tune_tx(hdd_ctx,
|
||||||
hdd_ctx->prev_no_rx_offload_pkts) / 2;
|
tx_packets,
|
||||||
hdd_ctx->prev_no_rx_offload_pkts = no_rx_offload_pkts;
|
&next_tx_level,
|
||||||
|
&is_tx_pm_qos_high);
|
||||||
|
|
||||||
avg_rx_offload_pkts = (rx_offload_pkts +
|
hdd_pm_qos_update_cpu_mask(&pm_qos_cpu_mask,
|
||||||
hdd_ctx->prev_rx_offload_pkts) / 2;
|
is_tx_pm_qos_high | is_rx_pm_qos_high);
|
||||||
hdd_ctx->prev_rx_offload_pkts = rx_offload_pkts;
|
|
||||||
|
|
||||||
avg_rx = avg_no_rx_offload_pkts + avg_rx_offload_pkts;
|
|
||||||
/*
|
|
||||||
* Takes care to set Rx_thread affinity for below case
|
|
||||||
* 1)LRO/GRO not supported ROME case
|
|
||||||
* 2)when rx_ol is disabled in cases like concurrency etc
|
|
||||||
* 3)For UDP cases
|
|
||||||
*/
|
|
||||||
if (avg_no_rx_offload_pkts > hdd_ctx->config->bus_bw_high_threshold) {
|
|
||||||
rxthread_high_tput_req = true;
|
|
||||||
is_rx_pm_qos_high = true;
|
|
||||||
} else {
|
|
||||||
rxthread_high_tput_req = false;
|
|
||||||
is_rx_pm_qos_high = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hdd_pm_qos_update_cpu_mask(&pm_qos_cpu_mask, is_rx_pm_qos_high);
|
|
||||||
|
|
||||||
if (cds_sched_handle_throughput_req(rxthread_high_tput_req))
|
|
||||||
hdd_warn("Rx thread high_tput(%d) affinity request failed",
|
|
||||||
rxthread_high_tput_req);
|
|
||||||
|
|
||||||
/* fine-tuning parameters for RX Flows */
|
|
||||||
if (avg_rx > hdd_ctx->config->tcp_delack_thres_high) {
|
|
||||||
if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
|
|
||||||
(++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
|
|
||||||
next_rx_level = WLAN_SVC_TP_HIGH;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hdd_ctx->rx_high_ind_cnt = 0;
|
|
||||||
next_rx_level = WLAN_SVC_TP_LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hdd_ctx->cur_rx_level != next_rx_level) {
|
|
||||||
struct wlan_rx_tp_data rx_tp_data = {0};
|
|
||||||
|
|
||||||
hdd_ctx->cur_rx_level = next_rx_level;
|
|
||||||
rx_level_change = true;
|
|
||||||
/* Send throughput indication only if it is enabled.
|
|
||||||
* Disabling tcp_del_ack will revert the tcp stack behavior
|
|
||||||
* to default delayed ack. Note that this will disable the
|
|
||||||
* dynamic delayed ack mechanism across the system
|
|
||||||
*/
|
|
||||||
if (hdd_ctx->en_tcp_delack_no_lro) {
|
|
||||||
rx_tp_data.rx_tp_flags |= TCP_DEL_ACK_IND;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hdd_ctx->config->enable_tcp_adv_win_scale)
|
|
||||||
rx_tp_data.rx_tp_flags |= TCP_ADV_WIN_SCL;
|
|
||||||
|
|
||||||
rx_tp_data.level = next_rx_level;
|
|
||||||
wlan_hdd_update_tcp_rx_param(hdd_ctx, &rx_tp_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
no_tx_offload_pkts = hdd_ctx->no_tx_offload_pkt_cnt;
|
|
||||||
hdd_ctx->no_tx_offload_pkt_cnt = 0;
|
|
||||||
tx_offload_pkts = tx_packets - no_tx_offload_pkts;
|
|
||||||
|
|
||||||
avg_no_tx_offload_pkts = (no_tx_offload_pkts +
|
|
||||||
hdd_ctx->prev_no_tx_offload_pkts) / 2;
|
|
||||||
hdd_ctx->prev_no_tx_offload_pkts = no_tx_offload_pkts;
|
|
||||||
|
|
||||||
avg_tx_offload_pkts = (tx_offload_pkts +
|
|
||||||
hdd_ctx->prev_tx_offload_pkts) / 2;
|
|
||||||
hdd_ctx->prev_tx_offload_pkts = tx_offload_pkts;
|
|
||||||
|
|
||||||
avg_tx = avg_no_tx_offload_pkts + avg_tx_offload_pkts;
|
|
||||||
|
|
||||||
/* fine-tuning parameters for TX Flows */
|
|
||||||
hdd_ctx->prev_tx = tx_packets;
|
|
||||||
|
|
||||||
if (avg_no_tx_offload_pkts > hdd_ctx->config->bus_bw_high_threshold)
|
|
||||||
is_tx_pm_qos_high = true;
|
|
||||||
else
|
|
||||||
is_tx_pm_qos_high = false;
|
|
||||||
|
|
||||||
hdd_pm_qos_update_cpu_mask(&pm_qos_cpu_mask, is_tx_pm_qos_high);
|
|
||||||
|
|
||||||
if (avg_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
|
|
||||||
next_tx_level = WLAN_SVC_TP_HIGH;
|
|
||||||
else
|
|
||||||
next_tx_level = WLAN_SVC_TP_LOW;
|
|
||||||
|
|
||||||
if ((hdd_ctx->config->enable_tcp_limit_output) &&
|
|
||||||
(hdd_ctx->cur_tx_level != next_tx_level)) {
|
|
||||||
struct wlan_tx_tp_data tx_tp_data = {0};
|
|
||||||
hdd_ctx->cur_tx_level = next_tx_level;
|
|
||||||
tx_level_change = true;
|
|
||||||
tx_tp_data.level = next_tx_level;
|
|
||||||
tx_tp_data.tcp_limit_output = true;
|
|
||||||
wlan_hdd_update_tcp_tx_param(hdd_ctx, &tx_tp_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
index = hdd_ctx->hdd_txrx_hist_idx;
|
index = hdd_ctx->hdd_txrx_hist_idx;
|
||||||
if (vote_level_change || tx_level_change || rx_level_change) {
|
if (vote_level_change || tx_level_change || rx_level_change) {
|
||||||
@@ -10364,9 +10423,6 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx,
|
|||||||
hdd_ctx->hdd_txrx_hist_idx++;
|
hdd_ctx->hdd_txrx_hist_idx++;
|
||||||
hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
|
hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
|
||||||
|
|
||||||
/* Clear all the mask if no silver/gold vote is required */
|
|
||||||
if (next_vote_level < PLD_BUS_WIDTH_MEDIUM)
|
|
||||||
cpumask_clear(&pm_qos_cpu_mask);
|
|
||||||
|
|
||||||
if (!hdd_ctx->pm_qos_request)
|
if (!hdd_ctx->pm_qos_request)
|
||||||
hdd_pm_qos_update_request(hdd_ctx, &pm_qos_cpu_mask);
|
hdd_pm_qos_update_request(hdd_ctx, &pm_qos_cpu_mask);
|
||||||
|
Reference in New Issue
Block a user