diff --git a/core/hdd/inc/wlan_hdd_lro.h b/core/hdd/inc/wlan_hdd_lro.h index 5de60c741b86..6964eedd51f1 100644 --- a/core/hdd/inc/wlan_hdd_lro.h +++ b/core/hdd/inc/wlan_hdd_lro.h @@ -50,6 +50,18 @@ int hdd_lro_init(struct hdd_context *hdd_ctx); enum hdd_lro_rx_status hdd_lro_rx(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter, struct sk_buff *skb); void hdd_lro_display_stats(struct hdd_context *hdd_ctx); + +/** + * hdd_lro_set_reset() - vendor command for Disable/Enable LRO + * @hdd_ctx: hdd context + * @hdd_adapter_t: adapter + * @enable_flag: enable or disable LRO. + * + * Return: none + */ +QDF_STATUS hdd_lro_set_reset(struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter, + uint8_t enable_flag); void hdd_disable_lro_in_concurrency(bool); /** * hdd_disable_lro_for_low_tput() - enable/disable LRO based on tput @@ -77,6 +89,12 @@ static inline void hdd_lro_display_stats(struct hdd_context *hdd_ctx) { } +static inline QDF_STATUS hdd_lro_set_reset(struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter, + uint8_t enable_flag) +{ + return 0; +} static inline void hdd_disable_lro_in_concurrency(bool disable) { } diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 8a1303ea3311..a7a9ae46d27d 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1704,6 +1704,7 @@ struct hdd_context { bool imps_enabled; int user_configured_pkt_filter_rules; bool is_fils_roaming_supported; + qdf_atomic_t vendor_disable_lro_flag; qdf_atomic_t disable_lro_in_concurrency; qdf_atomic_t disable_lro_in_low_tput; bool en_tcp_delack_no_lro; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index adb7c7445f58..7ec2f664ac0f 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5845,6 +5845,7 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = { .len = QDF_MAC_ADDR_SIZE}, [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32}, [QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 }, @@ -6235,6 +6236,13 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, if (status != QDF_STATUS_SUCCESS) ret_val = -EPERM; } + + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO]) { + enable_flag = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO]); + ret_val = hdd_lro_set_reset(hdd_ctx, adapter, + enable_flag); + } + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE]) { enable_flag = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE]); diff --git a/core/hdd/src/wlan_hdd_lro.c b/core/hdd/src/wlan_hdd_lro.c index 3dbaf6f1b048..6e9d57324b92 100644 --- a/core/hdd/src/wlan_hdd_lro.c +++ b/core/hdd/src/wlan_hdd_lro.c @@ -210,6 +210,41 @@ void hdd_lro_display_stats(struct hdd_context *hdd_ctx) hdd_debug("LRO stats is broken, will fix it"); } +QDF_STATUS +hdd_lro_set_reset(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter, + uint8_t enable_flag) +{ + if (!hdd_ctx->config->lro_enable || + QDF_STA_MODE != adapter->device_mode) { + hdd_debug("LRO is already Disabled"); + return 0; + } + + if (enable_flag) { + qdf_atomic_set(&hdd_ctx->vendor_disable_lro_flag, 0); + adapter->dev->features |= NETIF_F_LRO; + } else { + /* Disable LRO, Enable tcpdelack*/ + qdf_atomic_set(&hdd_ctx->vendor_disable_lro_flag, 1); + adapter->dev->features &= ~NETIF_F_LRO; + hdd_debug("LRO Disabled"); + + if (hdd_ctx->en_tcp_delack_no_lro) { + struct wlan_rx_tp_data rx_tp_data; + + hdd_debug("Enable TCP delack as LRO is disabled"); + rx_tp_data.rx_tp_flags = TCP_DEL_ACK_IND; + rx_tp_data.level = hdd_ctx->cur_rx_level; + wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index, + WLAN_SVC_WLAN_TP_IND, + &rx_tp_data, + sizeof(rx_tp_data)); + hdd_ctx->en_tcp_delack_no_lro = 1; + } + } + return 0; +} + /** * hdd_disable_lro_in_concurrency() - Disable LRO due to concurrency * @disable: bool value diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 46adc8d346e9..2c7d99dbad45 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3502,6 +3502,12 @@ QDF_STATUS hdd_init_station_mode(struct hdd_adapter *adapter) if (ret_val) hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val); + /* + * In case of USB tethering, LRO is disabled. If SSR happened + * during that time, then as part of SSR init, do not enable + * the LRO again. Keep the LRO state same as before SSR. + */ + if (!(qdf_atomic_read(&hdd_ctx->vendor_disable_lro_flag))) adapter->dev->features |= NETIF_F_LRO; /* rcpi info initialization */