diff --git a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h index b81df6058528..8c5dfd36976d 100644 --- a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h +++ b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h @@ -1532,15 +1532,14 @@ struct policy_mgr_cdp_cbacks { /** * struct policy_mgr_dp_cbacks - CDP Callbacks to be invoked * from policy manager - * @hdd_rx_handle_concurrency: Callback to handle concurrency related - * operations for rx + * @hdd_disable_rx_ol_in_concurrency: Callback to disable LRO/GRO offloads * @hdd_set_rx_mode_rps_cb: Callback to set RPS * @hdd_ipa_set_mcc_mode_cb: Callback to set mcc mode for ipa module * @hdd_v2_flow_pool_map: Callback to create vdev flow pool * @hdd_v2_flow_pool_unmap: Callback to delete vdev flow pool */ struct policy_mgr_dp_cbacks { - void (*hdd_rx_handle_concurrency)(bool); + void (*hdd_disable_rx_ol_in_concurrency)(bool); void (*hdd_set_rx_mode_rps_cb)(bool); void (*hdd_ipa_set_mcc_mode_cb)(bool); void (*hdd_v2_flow_pool_map)(int); diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c index 67e942ee585f..4785a580def7 100644 --- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c +++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c @@ -2011,8 +2011,8 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc, (policy_mgr_mode_specific_connection_count(psoc, PM_NDI_MODE, NULL) > 0)) { - if (pm_ctx->dp_cbacks.hdd_rx_handle_concurrency) - pm_ctx->dp_cbacks.hdd_rx_handle_concurrency(true); + if (pm_ctx->dp_cbacks.hdd_disable_rx_ol_in_concurrency) + pm_ctx->dp_cbacks.hdd_disable_rx_ol_in_concurrency(true); }; /* Enable RPS if SAP interface has come up */ @@ -2106,8 +2106,8 @@ QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc, (policy_mgr_mode_specific_connection_count(psoc, PM_NDI_MODE, NULL) == 0))) { - if (pm_ctx->dp_cbacks.hdd_rx_handle_concurrency) - pm_ctx->dp_cbacks.hdd_rx_handle_concurrency(false); + if (pm_ctx->dp_cbacks.hdd_disable_rx_ol_in_concurrency) + pm_ctx->dp_cbacks.hdd_disable_rx_ol_in_concurrency(false); }; /* Disable RPS if SAP interface has come up */ diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c index 70c9ba421977..3a5c07f982fe 100644 --- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c +++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c @@ -804,8 +804,8 @@ QDF_STATUS policy_mgr_register_dp_cb(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_FAILURE; } - pm_ctx->dp_cbacks.hdd_rx_handle_concurrency = - dp_cbacks->hdd_rx_handle_concurrency; + pm_ctx->dp_cbacks.hdd_disable_rx_ol_in_concurrency = + dp_cbacks->hdd_disable_rx_ol_in_concurrency; pm_ctx->dp_cbacks.hdd_set_rx_mode_rps_cb = dp_cbacks->hdd_set_rx_mode_rps_cb; pm_ctx->dp_cbacks.hdd_ipa_set_mcc_mode_cb = diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 816562e2043a..011f235bbfc6 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -958,10 +958,13 @@ QDF_STATUS cds_dp_open(struct wlan_objmgr_psoc *psoc) cds_debug("CDS successfully Opened"); - if (cdp_cfg_get(gp_cds_context->dp_soc, cfg_dp_force_gro_enable)) - hdd_ctx->dp_agg_param.force_gro_enable = true; + if (cdp_cfg_get(gp_cds_context->dp_soc, cfg_dp_tc_based_dyn_gro_enable)) + hdd_ctx->dp_agg_param.tc_based_dyn_gro = true; else - hdd_ctx->dp_agg_param.force_gro_enable = false; + hdd_ctx->dp_agg_param.tc_based_dyn_gro = false; + + hdd_ctx->dp_agg_param.tc_ingress_prio = + cdp_cfg_get(gp_cds_context->dp_soc, cfg_dp_tc_ingress_prio); return 0; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 96f7316529fc..5d74543caefc 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1198,6 +1198,20 @@ struct rcpi_info { struct hdd_context; +#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 + /** * struct hdd_adapter - hdd vdev/net_device context * @vdev: object manager vdev context @@ -1532,7 +1546,7 @@ struct hdd_adapter { void *cookie; bool response_expected; #endif - uint8_t gro_disallowed[DP_MAX_RX_THREADS]; + qdf_atomic_t gro_disallowed; uint8_t gro_flushed[DP_MAX_RX_THREADS]; bool handle_feature_update; /* Indicate if TSO and checksum offload features are enabled or not */ @@ -1865,7 +1879,8 @@ struct hdd_adapter_ops_history { * @country_change_work: work for updating vdev when country changes * @rx_aggregation: rx aggregation enable or disable state * @gro_force_flush: gro force flushed indication flag - * @force_gro_enable: force GRO enable or disable flag + * @tc_based_dyn_gro: TC based dynamic GRO enable/disable flag + * @tc_ingress_prio: TC ingress priority * @current_pcie_gen_speed: current pcie gen speed * @pm_qos_req: pm_qos request for all cpu cores * @qos_cpu_mask: voted cpu core mask @@ -1875,7 +1890,6 @@ struct hdd_adapter_ops_history { * @is_dual_mac_cfg_updated: indicate whether dual mac cfg has been updated * @twt_en_dis_work: work to send twt enable/disable cmd on MCC/SCC concurrency * @dump_in_progress: Stores value of dump in progress - * @rx_skip_qdisc_chk_conc: flag to skip ingress qdisc check in concurrency */ struct hdd_context { struct wlan_objmgr_psoc *psoc; @@ -2207,7 +2221,8 @@ struct hdd_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; int current_pcie_gen_speed; qdf_workqueue_t *adapter_ops_wq; @@ -2233,7 +2248,6 @@ struct hdd_context { bool is_therm_stats_in_progress; #endif uint64_t bw_vote_time; - qdf_atomic_t rx_skip_qdisc_chk_conc; }; /** diff --git a/core/hdd/inc/wlan_hdd_tx_rx.h b/core/hdd/inc/wlan_hdd_tx_rx.h index 078185ef98b5..c96ab216b26f 100644 --- a/core/hdd/inc/wlan_hdd_tx_rx.h +++ b/core/hdd/inc/wlan_hdd_tx_rx.h @@ -219,13 +219,12 @@ QDF_STATUS hdd_rx_pkt_thread_enqueue_cbk(void *adapter_context, int hdd_rx_ol_init(struct hdd_context *hdd_ctx); /** - * hdd_rx_handle_concurrency() - Handle concurrency related operations - * for rx - * @is_concurrency: true if there are concurrenct connections else false + * hdd_disable_rx_ol_in_concurrency() - Disable Rx offload due to concurrency + * @disable: true/false to disable/enable the Rx offload * * Return: none */ -void hdd_rx_handle_concurrency(bool is_concurrency); +void hdd_disable_rx_ol_in_concurrency(bool disable); /** * hdd_disable_rx_ol_for_low_tput() - Disable Rx offload in low TPUT scenario diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 2fe30d6d5320..9d179e904432 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -198,6 +198,9 @@ #include #include "qdf_lock.h" #include "wlan_hdd_thermal.h" +#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION +#include +#endif #ifdef MODULE #ifdef WLAN_WEAR_CHIPSET @@ -6996,6 +6999,7 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio qdf_event_create(&adapter->peer_cleanup_done); hdd_sta_info_init(&adapter->sta_info_list); hdd_sta_info_init(&adapter->cache_sta_info_list); + qdf_atomic_init(&adapter->gro_disallowed); for (i = 0; i < NET_DEV_HOLD_ID_MAX; i++) qdf_atomic_init( @@ -10574,6 +10578,168 @@ void hdd_send_mscs_action_frame(struct hdd_context *hdd_ctx, } #endif +#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) +static enum qdisc_filter_status +__hdd_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 +__hdd_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 + +/** + * hdd_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 priority 3 filter is present else false + */ +static enum qdisc_filter_status +hdd_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 QDISC_FILTER_PRIO_MISMATCH; + + ingress_block = cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL); + if (qdf_unlikely(!ingress_block)) + return QDISC_FILTER_PRIO_MISMATCH; + + return __hdd_check_for_prio_filter_in_clsact_qdisc(ingress_block, prio); +} + +/** + * hdd_rx_check_qdisc_for_adapter() - Check if any ingress qdisc is configured + * for given adapter + * @adapter: pointer to HDD adapter context + * @rx_ctx_id: Rx context id + * + * The function checks if ingress qdisc is registered for a given + * net device. + * + * Return: None + */ +static void +hdd_rx_check_qdisc_for_adapter(struct hdd_adapter *adapter) +{ + struct hdd_context *hdd_ctx = adapter->hdd_ctx; + struct netdev_queue *ingress_q; + struct Qdisc *ingress_qdisc; + bool disable_gro = false; + enum qdisc_filter_status ret; + + if (!adapter->dev->ingress_queue) + goto reset_wl; + + rcu_read_lock(); + + ingress_q = rcu_dereference(adapter->dev->ingress_queue); + if (qdf_unlikely(!ingress_q)) + goto reset; + + ingress_qdisc = rcu_dereference(ingress_q->qdisc); + if (qdf_unlikely(!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")) { + ret = hdd_check_for_prio_filter_in_clsact_qdisc(ingress_qdisc, + hdd_ctx->dp_agg_param.tc_ingress_prio); + + if (ret == QDISC_FILTER_RTNL_LOCK_FAIL) { + rcu_read_unlock(); + return; + } else if (ret == QDISC_FILTER_PRIO_MISMATCH) { + goto reset; + } + + disable_gro = true; + } + + if (disable_gro) { + rcu_read_unlock(); + + if (qdf_likely(qdf_atomic_read(&adapter->gro_disallowed))) + return; + + hdd_debug("ingress qdisc/filter configured disable GRO"); + qdf_atomic_set(&adapter->gro_disallowed, 1); + + return; + } + +reset: + rcu_read_unlock(); + +reset_wl: + if (qdf_unlikely(qdf_atomic_read(&adapter->gro_disallowed))) { + hdd_debug("ingress qdisc/filter removed enable GRO"); + qdf_atomic_set(&adapter->gro_disallowed, 0); + } +} +#else +static inline void +hdd_rx_check_qdisc_for_adapter(struct hdd_adapter *adapter) +{ +} +#endif + static void __hdd_bus_bw_work_handler(struct hdd_context *hdd_ctx) { struct hdd_adapter *adapter = NULL, *next_adapter = NULL, @@ -10630,6 +10796,9 @@ static void __hdd_bus_bw_work_handler(struct hdd_context *hdd_ctx) continue; } + if (hdd_ctx->dp_agg_param.tc_based_dyn_gro) + hdd_rx_check_qdisc_for_adapter(adapter); + tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets, adapter->prev_tx_packets); rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets, @@ -14524,7 +14693,14 @@ int hdd_configure_cds(struct hdd_context *hdd_ctx) if (ret) goto cds_disable; - dp_cbs.hdd_rx_handle_concurrency = hdd_rx_handle_concurrency; + /* Donot disable rx offload on concurrency for lithium based targets */ + if (!(hdd_ctx->target_type == TARGET_TYPE_QCA6290 || + hdd_ctx->target_type == TARGET_TYPE_QCA6390 || + hdd_ctx->target_type == TARGET_TYPE_QCA6490 || + hdd_ctx->target_type == TARGET_TYPE_QCA6750)) + if (hdd_ctx->ol_enable) + dp_cbs.hdd_disable_rx_ol_in_concurrency = + hdd_disable_rx_ol_in_concurrency; dp_cbs.hdd_set_rx_mode_rps_cb = hdd_set_rx_mode_rps; dp_cbs.hdd_ipa_set_mcc_mode_cb = hdd_ipa_set_mcc_mode; dp_cbs.hdd_v2_flow_pool_map = hdd_v2_flow_pool_map; diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c index 7acc1e7e3296..9e4d8d0b288e 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.c +++ b/core/hdd/src/wlan_hdd_nan_datapath.c @@ -1059,7 +1059,7 @@ int hdd_ndp_new_peer_handler(uint8_t vdev_id, uint16_t sta_id, if (hdd_ctx->ol_enable && !NAN_CONCURRENCY_SUPPORTED(hdd_ctx->psoc)) { hdd_debug("Disable LRO/GRO in NDI Mode"); - hdd_rx_handle_concurrency(true); + hdd_disable_rx_ol_in_concurrency(true); } hdd_bus_bw_compute_prev_txrx_stats(adapter); @@ -1110,7 +1110,7 @@ void hdd_cleanup_ndi(struct hdd_context *hdd_ctx, PM_STA_MODE, NULL) == 1)))) { hdd_debug("Enable LRO/GRO"); - hdd_rx_handle_concurrency(false); + hdd_disable_rx_ol_in_concurrency(false); } } diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 891c3b1dce7d..f4ffa2002ce9 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -1678,8 +1678,10 @@ static QDF_STATUS hdd_gro_rx_bh_disable(struct hdd_adapter *adapter, gro_result_t gro_ret; uint32_t rx_aggregation; uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(skb); + int32_t gro_disallowed; rx_aggregation = qdf_atomic_read(&hdd_ctx->dp_agg_param.rx_aggregation); + gro_disallowed = qdf_atomic_read(&adapter->gro_disallowed); skb_set_hash(skb, QDF_NBUF_CB_RX_FLOW_ID(skb), PKT_HASH_TYPE_L4); @@ -1687,7 +1689,7 @@ static QDF_STATUS hdd_gro_rx_bh_disable(struct hdd_adapter *adapter, gro_ret = napi_gro_receive(napi_to_use, skb); if (hdd_get_current_throughput_level(hdd_ctx) == PLD_BUS_WIDTH_IDLE || - !rx_aggregation || adapter->gro_disallowed[rx_ctx_id]) { + !rx_aggregation || gro_disallowed) { if (HDD_IS_EXTRA_GRO_FLUSH_NECESSARY(gro_ret)) { adapter->hdd_stats.tx_rx_stats. rx_gro_low_tput_flush++; @@ -1696,7 +1698,7 @@ static QDF_STATUS hdd_gro_rx_bh_disable(struct hdd_adapter *adapter, } if (!rx_aggregation) hdd_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] = 1; - if (adapter->gro_disallowed[rx_ctx_id]) + if (gro_disallowed) adapter->gro_flushed[rx_ctx_id] = 1; } local_bh_enable(); @@ -2003,7 +2005,7 @@ int hdd_rx_ol_init(struct hdd_context *hdd_ctx) return 0; } -void hdd_rx_handle_concurrency(bool is_concurrency) +void hdd_disable_rx_ol_in_concurrency(bool disable) { struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); @@ -2012,23 +2014,7 @@ void hdd_rx_handle_concurrency(bool is_concurrency) return; } - if (hdd_ctx->is_wifi3_0_target) { - /* - * Donot disable rx offload on concurrency for lithium and - * beryllium based targets - */ - if (is_concurrency) - qdf_atomic_set(&hdd_ctx->rx_skip_qdisc_chk_conc, 1); - else - qdf_atomic_set(&hdd_ctx->rx_skip_qdisc_chk_conc, 0); - - return; - } - - if (!hdd_ctx->ol_enable) - return; - - if (is_concurrency) { + if (disable) { if (HDD_MSM_CFG(hdd_ctx->config->enable_tcp_delack)) { struct wlan_rx_tp_data rx_tp_data; @@ -2064,7 +2050,7 @@ int hdd_rx_ol_init(struct hdd_context *hdd_ctx) return -EPERM; } -void hdd_rx_handle_concurrency(bool is_concurrency) +void hdd_disable_rx_ol_in_concurrency(bool disable) { } @@ -2169,6 +2155,7 @@ QDF_STATUS hdd_rx_deliver_to_stack(struct hdd_adapter *adapter, } #else +#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION #if defined(WLAN_SUPPORT_RX_FISA) /** * hdd_set_fisa_disallowed_for_vdev() - Set fisa disallowed bit for a vdev @@ -2195,106 +2182,6 @@ void hdd_set_fisa_disallowed_for_vdev(ol_txrx_soc_handle soc, uint8_t vdev_id, } #endif -#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION -/** - * hdd_is_chain_list_non_empty_for_clsact_qdisc() - Check if chain_list in - * ingress block is non-empty for a clsact qdisc. - * @qdisc: pointer to clsact qdisc - * - * Return: true if chain_list is not empty else false - */ -static bool -hdd_is_chain_list_non_empty_for_clsact_qdisc(struct Qdisc *qdisc) -{ - 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; - - ingress_block = cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL); - if (qdf_unlikely(!ingress_block)) - return false; - - if (list_empty(&ingress_block->chain_list)) - return false; - else - return true; -} - -/** - * hdd_rx_check_qdisc_for_adapter() - Check if any ingress qdisc is configured - * for given adapter - * @adapter: pointer to HDD adapter context - * @rx_ctx_id: Rx context id - * - * The function checks if ingress qdisc is registered for a given - * net device. - * - * Return: None - */ -static void -hdd_rx_check_qdisc_for_adapter(struct hdd_adapter *adapter, uint8_t rx_ctx_id) -{ - ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC); - struct netdev_queue *ingress_q; - struct Qdisc *ingress_qdisc; - - if (qdf_unlikely(!soc)) - return; - - /* - * Restrict the qdisc based dynamic GRO enable/disable to - * standalone STA mode only. Reset the configuration for - * any other device mode or concurrency. - */ - if (adapter->device_mode != QDF_STA_MODE || - (qdf_atomic_read(&adapter->hdd_ctx->rx_skip_qdisc_chk_conc))) - goto reset_wl; - - if (!adapter->dev->ingress_queue) - goto reset_wl; - - rcu_read_lock(); - - ingress_q = rcu_dereference(adapter->dev->ingress_queue); - if (qdf_unlikely(!ingress_q)) - goto reset; - - ingress_qdisc = rcu_dereference(ingress_q->qdisc); - if (qdf_unlikely(!ingress_qdisc)) - goto reset; - - if (!(qdf_str_eq(ingress_qdisc->ops->id, "ingress") || - (qdf_str_eq(ingress_qdisc->ops->id, "clsact") && - hdd_is_chain_list_non_empty_for_clsact_qdisc(ingress_qdisc)))) - goto reset; - - rcu_read_unlock(); - - if (qdf_likely(adapter->gro_disallowed[rx_ctx_id])) - return; - - hdd_debug("ingress qdisc/filter configured disable GRO"); - adapter->gro_disallowed[rx_ctx_id] = 1; - hdd_set_fisa_disallowed_for_vdev(soc, adapter->vdev_id, rx_ctx_id, 1); - - return; - -reset: - rcu_read_unlock(); - -reset_wl: - if (qdf_unlikely(adapter->gro_disallowed[rx_ctx_id])) { - hdd_debug("ingress qdisc/filter removed enable GRO"); - hdd_set_fisa_disallowed_for_vdev(soc, adapter->vdev_id, - rx_ctx_id, 0); - adapter->gro_disallowed[rx_ctx_id] = 0; - adapter->gro_flushed[rx_ctx_id] = 0; - } -} - QDF_STATUS hdd_rx_deliver_to_stack(struct hdd_adapter *adapter, struct sk_buff *skb) { @@ -2303,15 +2190,25 @@ QDF_STATUS hdd_rx_deliver_to_stack(struct hdd_adapter *adapter, int netif_status; bool skb_receive_offload_ok = false; uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(skb); - - if (!hdd_ctx->dp_agg_param.force_gro_enable) - /* rx_ctx_id is already verified for out-of-range */ - hdd_rx_check_qdisc_for_adapter(adapter, rx_ctx_id); + ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC); if (QDF_NBUF_CB_RX_TCP_PROTO(skb) && !QDF_NBUF_CB_RX_PEER_CACHED_FRM(skb)) skb_receive_offload_ok = true; + if (qdf_atomic_read(&adapter->gro_disallowed) == 0 && + adapter->gro_flushed[rx_ctx_id] != 0) { + if (qdf_likely(soc)) + hdd_set_fisa_disallowed_for_vdev(soc, adapter->vdev_id, + rx_ctx_id, 0); + adapter->gro_flushed[rx_ctx_id] = 0; + } else if (qdf_atomic_read(&adapter->gro_disallowed) && + adapter->gro_flushed[rx_ctx_id] == 0) { + if (qdf_likely(soc)) + hdd_set_fisa_disallowed_for_vdev(soc, adapter->vdev_id, + rx_ctx_id, 1); + } + if (skb_receive_offload_ok && hdd_ctx->receive_offload_cb && !hdd_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] && !adapter->gro_flushed[rx_ctx_id] &&