qcacld-3.0: Move TC based dynamic GRO logic to DP component

Move TC based dynamic GRO logic to DP component.

Change-Id: I3c6658e8f19a71e548c77ff6fd637148925008d7
CRs-Fixed: 3219451
This commit is contained in:
Yeshwanth Sriram Guntuka
2022-06-08 11:40:13 +05:30
committed by Madan Koyyalamudi
parent 2304bbd8de
commit 6529648bf3
9 changed files with 215 additions and 113 deletions

View File

@@ -321,7 +321,7 @@ struct wlan_dp_intf {
qdf_atomic_t num_active_task;
uint32_t sap_tx_block_mask;
uint8_t gro_disallowed[DP_MAX_RX_THREADS];
qdf_atomic_t gro_disallowed;
uint8_t gro_flushed[DP_MAX_RX_THREADS];
bool runtime_disable_rx_thread;
@@ -430,7 +430,8 @@ struct wlan_dp_psoc_context {
struct {
qdf_atomic_t rx_aggregation;
uint8_t gro_force_flush[DP_MAX_RX_THREADS];
bool force_gro_enable;
bool tc_based_dyn_gro;
uint32_t tc_ingress_prio;
}
dp_agg_param;

View File

@@ -1650,6 +1650,48 @@ static void dp_pld_request_bus_bandwidth(struct wlan_dp_psoc_context *dp_ctx,
}
}
#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
/**
* dp_rx_check_qdisc_for_intf() - Check if any ingress qdisc is configured
* for given adapter
* @dp_intf: pointer to DP interface context
*
* The function checks if ingress qdisc is registered for a given
* net device.
*
* Return: None
*/
static void
dp_rx_check_qdisc_for_intf(struct wlan_dp_intf *dp_intf)
{
struct wlan_dp_psoc_callbacks *dp_ops;
QDF_STATUS status;
dp_ops = &dp_intf->dp_ctx->dp_ops;
status = dp_ops->dp_rx_check_qdisc_configured(dp_intf->dev,
dp_intf->dp_ctx->dp_agg_param.tc_ingress_prio);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (qdf_likely(qdf_atomic_read(&dp_intf->gro_disallowed)))
return;
dp_debug("ingress qdisc/filter configured disable GRO");
qdf_atomic_set(&dp_intf->gro_disallowed, 1);
return;
} else if (status == QDF_STATUS_E_NOSUPPORT) {
if (qdf_unlikely(qdf_atomic_read(&dp_intf->gro_disallowed))) {
dp_debug("ingress qdisc/filter removed enable GRO");
qdf_atomic_set(&dp_intf->gro_disallowed, 0);
}
}
}
#else
static void
dp_rx_check_qdisc_for_intf(struct wlan_dp_intf *dp_intf)
{
}
#endif
/**
* __dp_bus_bw_work_handler() - Bus bandwidth work handler
* @dp_ctx: handle to DP context
@@ -1709,6 +1751,9 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx)
continue;
}
if (dp_ctx->dp_agg_param.tc_based_dyn_gro)
dp_rx_check_qdisc_for_intf(dp_intf);
tx_packets += DP_BW_GET_DIFF(
QDF_NET_DEV_STATS_TX_PKTS(&dp_intf->stats),
dp_intf->prev_tx_packets);

View File

@@ -961,11 +961,13 @@ static QDF_STATUS dp_gro_rx_bh_disable(struct wlan_dp_intf *dp_intf,
uint32_t rx_aggregation;
uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(nbuf);
uint8_t low_tput_force_flush = 0;
int32_t gro_disallowed;
rx_aggregation = qdf_atomic_read(&dp_ctx->dp_agg_param.rx_aggregation);
gro_disallowed = qdf_atomic_read(&dp_intf->gro_disallowed);
if (dp_get_current_throughput_level(dp_ctx) == PLD_BUS_WIDTH_IDLE ||
!rx_aggregation || dp_intf->gro_disallowed[rx_ctx_id]) {
!rx_aggregation || gro_disallowed) {
status = dp_ctx->dp_ops.dp_rx_napi_gro_flush(napi_to_use, nbuf,
&low_tput_force_flush);
if (!low_tput_force_flush)
@@ -973,7 +975,7 @@ static QDF_STATUS dp_gro_rx_bh_disable(struct wlan_dp_intf *dp_intf,
rx_gro_low_tput_flush++;
if (!rx_aggregation)
dp_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] = 1;
if (dp_intf->gro_disallowed[rx_ctx_id])
if (gro_disallowed)
dp_intf->gro_flushed[rx_ctx_id] = 1;
} else {
status = dp_ctx->dp_ops.dp_rx_napi_gro_receive(napi_to_use,
@@ -1400,58 +1402,6 @@ void wlan_dp_set_fisa_disallowed_for_vdev(ol_txrx_soc_handle soc,
#endif
#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
/**
* dp_rx_check_qdisc_for_intf() - Check if any ingress qdisc is configured
* for given adapter
* @dp_intf: pointer to DP interface context
* @rx_ctx_id: Rx context id
*
* The function checks if ingress qdisc is registered for a given
* net device.
*
* Return: None
*/
static void
dp_rx_check_qdisc_for_intf(struct wlan_dp_intf *dp_intf,
uint8_t rx_ctx_id)
{
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
struct wlan_dp_psoc_callbacks *dp_ops;
QDF_STATUS status;
/*
* Restrict the qdisc based dynamic GRO enable/disable to
* standalone STA mode only. Reset the configuration for
* any other device mode or concurrency.
*/
if (dp_intf->device_mode != QDF_STA_MODE ||
(qdf_atomic_read(&dp_intf->dp_ctx->rx_skip_qdisc_chk_conc)))
goto reset_wl;
dp_ops = &dp_intf->dp_ctx->dp_ops;
status = dp_ops->dp_rx_check_qdisc_configured(dp_intf->dev,
rx_ctx_id);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (qdf_likely(dp_intf->gro_disallowed[rx_ctx_id]))
return;
dp_debug("ingress qdisc/filter configured disable GRO");
dp_intf->gro_disallowed[rx_ctx_id] = 1;
wlan_dp_set_fisa_disallowed_for_vdev(soc, dp_intf->intf_id,
rx_ctx_id, 1);
return;
}
reset_wl:
if (qdf_unlikely(dp_intf->gro_disallowed[rx_ctx_id])) {
dp_debug("ingress qdisc/filter removed enable GRO");
wlan_dp_set_fisa_disallowed_for_vdev(soc, dp_intf->intf_id,
rx_ctx_id, 0);
dp_intf->gro_disallowed[rx_ctx_id] = 0;
dp_intf->gro_flushed[rx_ctx_id] = 0;
}
}
QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
qdf_nbuf_t nbuf)
{
@@ -1461,15 +1411,29 @@ QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
bool nbuf_receive_offload_ok = false;
enum dp_nbuf_push_type push_type;
uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(nbuf);
if (!dp_ctx->dp_agg_param.force_gro_enable)
/* rx_ctx_id is already verified for out-of-range */
dp_rx_check_qdisc_for_intf(dp_intf, rx_ctx_id);
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
int32_t gro_disallowed;
if (QDF_NBUF_CB_RX_TCP_PROTO(nbuf) &&
!QDF_NBUF_CB_RX_PEER_CACHED_FRM(nbuf))
nbuf_receive_offload_ok = true;
gro_disallowed = qdf_atomic_read(&dp_intf->gro_disallowed);
if (gro_disallowed == 0 &&
dp_intf->gro_flushed[rx_ctx_id] != 0) {
if (qdf_likely(soc))
wlan_dp_set_fisa_disallowed_for_vdev(soc,
dp_intf->intf_id,
rx_ctx_id, 0);
dp_intf->gro_flushed[rx_ctx_id] = 0;
} else if (gro_disallowed &&
dp_intf->gro_flushed[rx_ctx_id] == 0) {
if (qdf_likely(soc))
wlan_dp_set_fisa_disallowed_for_vdev(soc,
dp_intf->intf_id,
rx_ctx_id, 1);
}
if (nbuf_receive_offload_ok && dp_ctx->receive_offload_cb &&
!dp_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] &&
!dp_intf->gro_flushed[rx_ctx_id] &&

View File

@@ -618,7 +618,7 @@ struct wlan_dp_psoc_callbacks {
void (*dp_register_rx_offld_flush_cb)(enum dp_rx_offld_flush_cb type);
QDF_STATUS (*dp_rx_check_qdisc_configured)(qdf_netdev_t dev,
uint8_t rx_ctx_id);
uint32_t prio);
bool (*dp_is_gratuitous_arp_unsolicited_na)(qdf_nbuf_t nbuf);

View File

@@ -256,19 +256,16 @@ bool ucfg_dp_is_ol_enabled(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_dp_rx_handle_concurrency() - Handle concurrency setting in DP
* @psoc: PSOC mapped to DP context
* @is_wifi3_0_target: true if it is wifi3.0 target
* @is_concurrency: Is concurrency enabled/disabled
* @disable: true/false to disable/enable the Rx offload
*
* Return: None
*/
void ucfg_dp_rx_handle_concurrency(struct wlan_objmgr_psoc *psoc,
bool is_wifi3_0_target,
bool is_concurrency);
bool disable);
#else
static inline
void ucfg_dp_rx_handle_concurrency(struct wlan_objmgr_psoc *psoc,
bool is_wifi3_0_target,
bool is_concurrency) { }
bool disable) { }
#endif
/**
@@ -1124,13 +1121,13 @@ void ucfg_dp_set_rx_aggregation_val(struct wlan_objmgr_psoc *psoc,
uint32_t value);
/**
* ucfg_dp_set_force_gro_enable() - Set force gro enable
* ucfg_dp_set_tc_based_dyn_gro() - Set tc based dynamic gro
* @psoc: psoc handle
* @value : value to be set
*
* Return: None
*/
void ucfg_dp_set_force_gro_enable(struct wlan_objmgr_psoc *psoc, bool value);
void ucfg_dp_set_tc_based_dyn_gro(struct wlan_objmgr_psoc *psoc, bool value);
/**
* ucfg_dp_runtime_disable_rx_thread() - Disable rx thread
@@ -1149,4 +1146,13 @@ void ucfg_dp_runtime_disable_rx_thread(struct wlan_objmgr_vdev *vdev,
* Return: true if NAPI enabled
*/
bool ucfg_dp_get_napi_enabled(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_dp_set_tc_ingress_prio() - Set tc ingress priority
* @psoc: psoc handle mapped to DP context
* @value: value to be set
*
* Return: None
*/
void ucfg_dp_set_tc_ingress_prio(struct wlan_objmgr_psoc *psoc, uint32_t value);
#endif /* _WLAN_DP_UCFG_API_H_ */

View File

@@ -91,6 +91,7 @@ ucfg_dp_create_intf(struct wlan_objmgr_psoc *psoc,
dp_nud_init_tracking(dp_intf);
dp_mic_init_work(dp_intf);
qdf_atomic_init(&dp_ctx->num_latency_critical_clients);
qdf_atomic_init(&dp_intf->gro_disallowed);
return QDF_STATUS_SUCCESS;
}
@@ -678,8 +679,7 @@ bool ucfg_dp_is_ol_enabled(struct wlan_objmgr_psoc *psoc)
#ifdef RECEIVE_OFFLOAD
void ucfg_dp_rx_handle_concurrency(struct wlan_objmgr_psoc *psoc,
bool is_wifi3_0_target,
bool is_concurrency)
bool disable)
{
struct wlan_dp_psoc_context *dp_ctx;
@@ -689,23 +689,7 @@ void ucfg_dp_rx_handle_concurrency(struct wlan_objmgr_psoc *psoc,
return;
}
if (is_wifi3_0_target) {
/*
* Donot disable rx offload on concurrency for lithium and
* beryllium based targets
*/
if (is_concurrency)
qdf_atomic_set(&dp_ctx->rx_skip_qdisc_chk_conc, 1);
else
qdf_atomic_set(&dp_ctx->rx_skip_qdisc_chk_conc, 0);
return;
}
if (!dp_ctx->ol_enable)
return;
if (is_concurrency) {
if (disable) {
if (DP_BUS_BW_CFG(dp_ctx->dp_cfg.enable_tcp_delack)) {
struct wlan_rx_tp_data rx_tp_data;
@@ -2048,7 +2032,7 @@ void ucfg_dp_set_rx_aggregation_val(struct wlan_objmgr_psoc *psoc,
qdf_atomic_set(&dp_ctx->dp_agg_param.rx_aggregation, !!value);
}
void ucfg_dp_set_force_gro_enable(struct wlan_objmgr_psoc *psoc, bool value)
void ucfg_dp_set_tc_based_dyn_gro(struct wlan_objmgr_psoc *psoc, bool value)
{
struct wlan_dp_psoc_context *dp_ctx = dp_psoc_get_priv(psoc);
@@ -2056,7 +2040,7 @@ void ucfg_dp_set_force_gro_enable(struct wlan_objmgr_psoc *psoc, bool value)
dp_err("DP ctx is NULL");
return;
}
dp_ctx->dp_agg_param.force_gro_enable = value;
dp_ctx->dp_agg_param.tc_based_dyn_gro = value;
}
void ucfg_dp_runtime_disable_rx_thread(struct wlan_objmgr_vdev *vdev,
@@ -2081,3 +2065,14 @@ bool ucfg_dp_get_napi_enabled(struct wlan_objmgr_psoc *psoc)
}
return dp_ctx->napi_enable;
}
void ucfg_dp_set_tc_ingress_prio(struct wlan_objmgr_psoc *psoc, uint32_t value)
{
struct wlan_dp_psoc_context *dp_ctx = dp_psoc_get_priv(psoc);
if (!dp_ctx) {
dp_err("DP ctx is NULL");
return;
}
dp_ctx->dp_agg_param.tc_ingress_prio = value;
}

View File

@@ -320,6 +320,7 @@ target_if_dp_send_dhcp_ind(uint16_t vdev_id,
struct wmi_unified *wmi_handle;
struct wlan_objmgr_psoc *psoc;
wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
QDF_STATUS status;
psoc = wlan_objmgr_get_psoc_by_id(0, WLAN_PSOC_TARGET_IF_ID);
if (!psoc) {
@@ -345,8 +346,11 @@ target_if_dp_send_dhcp_ind(uint16_t vdev_id,
WMI_CHAR_ARRAY_TO_MAC_ADDR(dhcp_ind->peer_mac_addr.bytes,
&peer_set_param_fp.peer_macaddr);
return wmi_unified_process_dhcp_ind(wmi_handle,
&peer_set_param_fp);
status = wmi_unified_process_dhcp_ind(wmi_handle,
&peer_set_param_fp);
wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID);
return status;
}
void target_if_dp_register_tx_ops(struct wlan_dp_psoc_sb_ops *sb_ops)

View File

@@ -26,6 +26,20 @@
#include "wlan_dp_public_struct.h"
#include <wlan_cfg80211.h>
#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
/**
* enum qdisc_filter_status - QDISC filter status
* @QDISC_FILTER_RTNL_LOCK_FAIL: rtnl lock acquire failed
* @QDISC_FILTER_PRIO_MATCH: qdisc filter with priority match
* @QDISC_FILTER_PRIO_MISMATCH: no filter match with configured priority
*/
enum qdisc_filter_status {
QDISC_FILTER_RTNL_LOCK_FAIL,
QDISC_FILTER_PRIO_MATCH,
QDISC_FILTER_PRIO_MISMATCH,
};
#endif
/**
* osif_dp_classify_pkt() - classify packet
* @skb - sk buff

View File

@@ -299,36 +299,94 @@ static void osif_dp_qdf_lro_flush(void *data)
#endif
#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
static enum qdisc_filter_status
__osif_check_for_prio_filter_in_clsact_qdisc(struct tcf_block *block,
uint32_t prio)
{
struct tcf_chain *chain;
struct tcf_proto *tp;
struct tcf_proto *tp_next;
enum qdisc_filter_status ret = QDISC_FILTER_PRIO_MISMATCH;
if (!rtnl_trylock())
return QDISC_FILTER_RTNL_LOCK_FAIL;
mutex_lock(&block->lock);
list_for_each_entry(chain, &block->chain_list, list) {
mutex_lock(&chain->filter_chain_lock);
tp = tcf_chain_dereference(chain->filter_chain, chain);
while (tp) {
tp_next = rcu_dereference_protected(tp->next, 1);
if (tp->prio == (prio << 16)) {
ret = QDISC_FILTER_PRIO_MATCH;
break;
}
tp = tp_next;
}
mutex_unlock(&chain->filter_chain_lock);
if (ret == QDISC_FILTER_PRIO_MATCH)
break;
}
mutex_unlock(&block->lock);
rtnl_unlock();
return ret;
}
#else
static enum qdisc_filter_status
__osif_check_for_prio_filter_in_clsact_qdisc(struct tcf_block *block,
uint32_t prio)
{
struct tcf_chain *chain;
struct tcf_proto *tp;
enum qdisc_filter_status ret = QDISC_FILTER_PRIO_MISMATCH;
if (!rtnl_trylock())
return QDISC_FILTER_RTNL_LOCK_FAIL;
list_for_each_entry(chain, &block->chain_list, list) {
for (tp = rtnl_dereference(chain->filter_chain); tp;
tp = rtnl_dereference(tp->next)) {
if (tp->prio == (prio << 16))
ret = QDISC_FILTER_PRIO_MATCH;
}
}
rtnl_unlock();
return ret;
}
#endif
/**
* osif_dp_is_chain_list_non_empty_for_clsact_qdisc() - Check if chain_list in
* ingress block is non-empty for a clsact qdisc.
* osif_check_for_prio_filter_in_clsact_qdisc() - Check if priority 3 filter
* is configured in the ingress clsact qdisc
* @qdisc: pointer to clsact qdisc
*
* Return: true if chain_list is not empty else false
* Return: qdisc filter status
*/
static bool
osif_dp_is_chain_list_non_empty_for_clsact_qdisc(struct Qdisc *qdisc)
static enum qdisc_filter_status
osif_check_for_prio_filter_in_clsact_qdisc(struct Qdisc *qdisc, uint32_t prio)
{
const struct Qdisc_class_ops *cops;
struct tcf_block *ingress_block;
cops = qdisc->ops->cl_ops;
if (qdf_unlikely(!cops || !cops->tcf_block))
return false;
return QDISC_FILTER_PRIO_MISMATCH;
ingress_block = cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
if (qdf_unlikely(!ingress_block))
return false;
return QDISC_FILTER_PRIO_MISMATCH;
if (list_empty(&ingress_block->chain_list))
return false;
else
return true;
return __osif_check_for_prio_filter_in_clsact_qdisc(ingress_block,
prio);
}
/**
* osif_dp_rx_check_qdisc_for_configured() - Check if any ingress qdisc configured
* for given adapter
* osif_dp_rx_check_qdisc_for_configured() - Check if any ingress qdisc
* configured for given adapter
* @dp_intf: pointer to DP interface context
* @rx_ctx_id: Rx context id
*
@@ -338,11 +396,13 @@ osif_dp_is_chain_list_non_empty_for_clsact_qdisc(struct Qdisc *qdisc)
* Return: None
*/
static QDF_STATUS
osif_dp_rx_check_qdisc_configured(qdf_netdev_t ndev, uint8_t rx_ctx_id)
osif_dp_rx_check_qdisc_configured(qdf_netdev_t ndev, uint32_t prio)
{
struct netdev_queue *ingress_q;
struct Qdisc *ingress_qdisc;
struct net_device *dev = (struct net_device *)ndev;
bool disable_gro = false;
enum qdisc_filter_status status;
if (!dev->ingress_queue)
goto reset_wl;
@@ -357,14 +417,27 @@ osif_dp_rx_check_qdisc_configured(qdf_netdev_t ndev, uint8_t rx_ctx_id)
if (qdf_unlikely(!ingress_qdisc))
goto reset;
if (!(qdf_str_eq(ingress_qdisc->ops->id, "ingress") ||
(qdf_str_eq(ingress_qdisc->ops->id, "clsact") &&
osif_dp_is_chain_list_non_empty_for_clsact_qdisc(ingress_qdisc))))
goto reset;
if (qdf_str_eq(ingress_qdisc->ops->id, "ingress")) {
disable_gro = true;
} else if (qdf_str_eq(ingress_qdisc->ops->id, "clsact")) {
status = osif_check_for_prio_filter_in_clsact_qdisc(
ingress_qdisc,
prio);
rcu_read_unlock();
if (status == QDISC_FILTER_RTNL_LOCK_FAIL) {
rcu_read_unlock();
return QDF_STATUS_E_AGAIN;
} else if (status == QDISC_FILTER_PRIO_MISMATCH) {
goto reset;
}
return 0;
disable_gro = true;
}
if (disable_gro) {
rcu_read_unlock();
return QDF_STATUS_SUCCESS;
}
reset:
rcu_read_unlock();
@@ -375,7 +448,7 @@ reset_wl:
#else
static QDF_STATUS
osif_dp_rx_check_qdisc_configured(qdf_netdev_t ndev, uint8_t rx_ctx_id)
osif_dp_rx_check_qdisc_configured(qdf_netdev_t ndev, uint32_t prio)
{
return QDF_STATUS_E_NOSUPPORT;
}