diff --git a/Kbuild b/Kbuild
index 3213944a483f..5c9b2da31439 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1918,6 +1918,11 @@ ifneq (y,$(filter y,$(CONFIG_CNSS_EOS) $(CONFIG_ICNSS)))
CDEFINES += -DWLAN_ENABLE_CHNL_MATRIX_RESTRICTION
endif
+#Enable ICMP packet disable powersave feature
+ifeq ($(CONFIG_ICMP_DISABLE_PS),y)
+CDEFINES += -DWLAN_ICMP_DISABLE_PS
+endif
+
#Enable OBSS feature
CDEFINES += -DQCA_HT_2040_COEX
diff --git a/Kconfig b/Kconfig
index 9fa7f7fd7aa2..cf9ee355ca46 100644
--- a/Kconfig
+++ b/Kconfig
@@ -132,4 +132,8 @@ config WLAN_FEATURE_11AX
bool "Enable 11AX(High Efficiency) feature"
default n
+config ICMP_DISABLE_PS
+ bool "Enable ICMP packet disable powersave feature"
+ default n
+
endif # QCA_CLD_WLAN
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index 17c16fa0f490..759621bbe92d 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -9230,6 +9230,31 @@ enum hdd_wext_control {
#define CFG_AUTO_PS_ENABLE_TIMER_MAX (120)
#define CFG_AUTO_PS_ENABLE_TIMER_DEFAULT (0)
+#ifdef WLAN_ICMP_DISABLE_PS
+/*
+ *
+ * gIcmpDisablePsValue - Set ICMP packet disable power save value
+ * @Min: 0
+ * @Max: 10000
+ * @Default: 5000
+ *
+ * This ini is used to set ICMP packet disable power save value in
+ * millisecond.
+ *
+ * Related: gEnableBmps
+ *
+ * Supported Feature: Power Save
+ *
+ * Usage: External
+ *
+ *
+ */
+#define CFG_ICMP_DISABLE_PS_NAME "gIcmpDisablePsValue"
+#define CFG_ICMP_DISABLE_PS_MIN (0)
+#define CFG_ICMP_DISABLE_PS_MAX (10000)
+#define CFG_ICMP_DISABLE_PS_DEFAULT (5000)
+#endif
+
/*
*
* gBmpsMinListenInterval - Set BMPS Minimum Listen Interval
@@ -10292,6 +10317,7 @@ struct hdd_config {
bool fIsImpsEnabled;
bool is_ps_enabled;
uint32_t auto_bmps_timer_val;
+ uint32_t icmp_disable_ps_val;
uint32_t nBmpsModListenInterval;
uint32_t nBmpsMaxListenInterval;
uint32_t nBmpsMinListenInterval;
diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h
index 3dfc0eefdc65..dd9051cb357c 100644
--- a/core/hdd/inc/wlan_hdd_power.h
+++ b/core/hdd/inc/wlan_hdd_power.h
@@ -302,6 +302,17 @@ static inline
void hdd_wlan_suspend_resume_event(uint8_t state) {}
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+/**
+ * wlan_hdd_set_powersave() - Set powersave mode
+ * @adapter: adapter upon which the request was received
+ * @allow_power_save: is wlan allowed to go into power save mode
+ * @timeout: timeout period in ms
+ *
+ * Return: 0 on success, non-zero on any error
+ */
+int wlan_hdd_set_powersave(hdd_adapter_t *adapter,
+ bool allow_power_save, uint32_t timeout);
+
/**
* wlan_hdd_inc_suspend_stats() - Prints, then increments, then prints suspend
* failed statistics.
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index 9eb654ea1317..9939620858a0 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -418,6 +418,15 @@ struct reg_table_entry g_registry_table[] = {
CFG_AUTO_PS_ENABLE_TIMER_MIN,
CFG_AUTO_PS_ENABLE_TIMER_MAX),
+#ifdef WLAN_ICMP_DISABLE_PS
+ REG_VARIABLE(CFG_ICMP_DISABLE_PS_NAME, WLAN_PARAM_Integer,
+ struct hdd_config, icmp_disable_ps_val,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ICMP_DISABLE_PS_DEFAULT,
+ CFG_ICMP_DISABLE_PS_MIN,
+ CFG_ICMP_DISABLE_PS_MAX),
+#endif
+
REG_VARIABLE(CFG_BMPS_MINIMUM_LI_NAME, WLAN_PARAM_Integer,
struct hdd_config, nBmpsMinListenInterval,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c
index c2259d5b0685..b0c18c5e40b9 100644
--- a/core/hdd/src/wlan_hdd_power.c
+++ b/core/hdd/src/wlan_hdd_power.c
@@ -1514,15 +1514,7 @@ success:
return QDF_STATUS_SUCCESS;
}
-/**
- * wlan_hdd_set_powersave() - Set powersave mode
- * @adapter: adapter upon which the request was received
- * @allow_power_save: is wlan allowed to go into power save mode
- * @timeout: timeout period in ms
- *
- * Return: 0 on success, non-zero on any error
- */
-static int wlan_hdd_set_powersave(hdd_adapter_t *adapter,
+int wlan_hdd_set_powersave(hdd_adapter_t *adapter,
bool allow_power_save, uint32_t timeout)
{
tHalHandle hal;
diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c
index 764c7f5026ec..0acff08a7a1e 100644
--- a/core/hdd/src/wlan_hdd_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_tx_rx.c
@@ -62,6 +62,7 @@
#include "pld_common.h"
#include
#include "wlan_hdd_rx_monitor.h"
+#include "wlan_hdd_power.h"
#ifdef QCA_LL_TX_FLOW_CONTROL_V2
/*
@@ -377,9 +378,43 @@ void wlan_hdd_classify_pkt(struct sk_buff *skb)
else if (qdf_nbuf_is_ipv4_wapi_pkt(skb))
QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
QDF_NBUF_CB_PACKET_TYPE_WAPI;
+ else if (qdf_nbuf_is_icmp_pkt(skb))
+ QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
+ QDF_NBUF_CB_PACKET_TYPE_ICMP;
}
+/**
+ * wlan_hdd_latency_opt()- latency option
+ * @adapter: pointer to the adapter structure
+ * @skb: pointer to sk buff
+ *
+ * Function to disable power save for icmp packets.
+ *
+ * Return: None
+ */
+#ifdef WLAN_ICMP_DISABLE_PS
+static inline void
+wlan_hdd_latency_opt(hdd_adapter_t *adapter, struct sk_buff *skb)
+{
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+ if (hdd_ctx->config->icmp_disable_ps_val <= 0)
+ return;
+
+ if (QDF_NBUF_CB_GET_PACKET_TYPE(skb) ==
+ QDF_NBUF_CB_PACKET_TYPE_ICMP) {
+ wlan_hdd_set_powersave(adapter, false,
+ hdd_ctx->config->icmp_disable_ps_val);
+ }
+}
+#else
+static inline void
+wlan_hdd_latency_opt(hdd_adapter_t *adapter, struct sk_buff *skb)
+{
+}
+#endif
+
/**
* hdd_get_transmit_sta_id() - function to retrieve station id to be used for
* sending traffic towards a particular destination address. The destination
@@ -509,6 +544,7 @@ static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
wlan_hdd_classify_pkt(skb);
+ wlan_hdd_latency_opt(pAdapter, skb);
STAId = HDD_WLAN_INVALID_STA_ID;