From 4b3f7312658688d037d4db031779df687c7ebf63 Mon Sep 17 00:00:00 2001 From: "Poddar, Siddarth" Date: Thu, 2 Nov 2017 17:00:20 +0530 Subject: [PATCH] qcacld-3.0: Support for vendor issuing Enable/Disable LRO command Add support for Enable/Disable LRO at run time through vendor command. In case of USB tethering with WLAN0 as upstream, vendor command will be issued to disable LRO. On reception driver will disable LRO and enable tcpdelack. Change-Id: If64da28c040868d5b42af202c647251db1a684c0 CRs-Fixed: 2060320 --- core/hdd/inc/wlan_hdd_lro.h | 18 ++++++++++++++++ core/hdd/inc/wlan_hdd_main.h | 1 + core/hdd/src/wlan_hdd_cfg80211.c | 8 ++++++++ core/hdd/src/wlan_hdd_lro.c | 35 ++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_main.c | 6 ++++++ 5 files changed, 68 insertions(+) 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 */