[WCNCR00168085] power-save: add WiFi KeepFullPwr control

[Description]
During airtime utilization and noise histogram collection,
MT7668 will keep in a full power mode.
If enter suspending in that time, the power consumption is high.

[Solution]
Add new CMD_ID_KEEP_FULL_PWR (0x2A) for driver to control KeepFullPwr.
Need the corresponding firmware to handle 0x2A command.

[Test]
1. Passed suspend/resume 50 times and confirm KeepFullPwr is disabled
   when airtime utilization or noise histogram is collecting.
2. Passed 2G/5G AP scan/connection.

Change-Id: I2649ffdbc23a9af29461db37e78dd246453577ee
CR-Id: WCNCR00168085
Feature: power-save
Signed-off-by: ZD Hu <zd.hu@mediatek.com>
diff --git a/common/wlan_lib.c b/common/wlan_lib.c
index 840eeba..1c3d4da 100644
--- a/common/wlan_lib.c
+++ b/common/wlan_lib.c
@@ -2237,6 +2237,33 @@
 
 /*----------------------------------------------------------------------------*/
 /*!
+* \brief This function is called to set g_fgKeepFullPwr flag in firmware
+*
+* \param[IN] prAdapter        Pointer to the Adapter structure.
+* \param[IN] fgEnable         Boolean of enable
+*                             True: wlan stays awake and keeps working in full power state
+*                             False: wlan may go to sleep and consumes less power.
+*
+* \return WLAN_STATUS_SUCCESS
+* \return WLAN_STATUS_FAILURE
+*/
+/*----------------------------------------------------------------------------*/
+WLAN_STATUS wlanKeepFullPwr(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable)
+{
+	struct CMD_KEEP_FULL_PWR_T rCmdKeepFullPwr;
+
+	ASSERT(prAdapter);
+
+	rCmdKeepFullPwr.ucEnable = fgEnable;
+	DBGLOG(HAL, STATE, "KeepFullPwr: %d\n", rCmdKeepFullPwr.ucEnable);
+
+	return wlanSendSetQueryCmd(prAdapter,
+				   CMD_ID_KEEP_FULL_PWR, TRUE, FALSE, FALSE, NULL, NULL,
+				   sizeof(struct CMD_KEEP_FULL_PWR_T), (PUINT_8)&rCmdKeepFullPwr, NULL, 0);
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
 * \brief This function is called to check if it is RF test mode and
 *        the OID is allowed to be called or not
 *
@@ -9547,6 +9574,9 @@
 	PARAM_POWER_MODE ePwrMode;
 	P_BSS_INFO_T prBssInfo;
 
+	if (prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap)
+		wlanKeepFullPwr(prGlueInfo->prAdapter, FALSE);
+
 	/* if wifi.cfg EAPOL offload is 0, we set rekey offload when enter wow */
 	if (!prGlueInfo->prAdapter->rWifiVar.ucEapolOffload) {
 		wlanSuspendRekeyOffload(prGlueInfo, FALSE);
@@ -9614,5 +9644,8 @@
 				prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, ePwrMode, FALSE, FALSE);
 		}
 	}
+
+	if (prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap)
+		wlanKeepFullPwr(prGlueInfo->prAdapter, TRUE);
 }
 
diff --git a/include/nic/adapter.h b/include/nic/adapter.h
index a184640..2a55cc3 100644
--- a/include/nic/adapter.h
+++ b/include/nic/adapter.h
@@ -1166,6 +1166,12 @@
 	UINT_32 u4CtiaPowerMode;
 	BOOLEAN fgEnCtiaPowerMode;
 
+	/* Bitmap is defined as #define KEEP_FULL_PWR_{FEATURE}_BIT in wlan_lib.h
+	 * Each feature controls KeepFullPwr(CMD_ID_KEEP_FULL_PWR) should
+	 * register bitmap to ensure low power during suspend.
+	 */
+	UINT_32 u4IsKeepFullPwrBitmap;
+
 	UINT_32 fgEnArpFilter;
 
 	UINT_32 u4UapsdAcBmp;
diff --git a/include/nic_cmd_event.h b/include/nic_cmd_event.h
index 7beea0a..2e8e3e4 100644
--- a/include/nic_cmd_event.h
+++ b/include/nic_cmd_event.h
@@ -447,6 +447,8 @@
 	CMD_ID_P2P_ABORT,	/* 0x26 (Set) */
 	CMD_ID_SET_DBDC_PARMS = 0x28,	/* 0x28 (Set) */
 
+	CMD_ID_KEEP_FULL_PWR = 0x2A,	/* 0x2A (Set) */
+
 	/* SLT commands */
 	CMD_ID_RANDOM_RX_RESET_EN = 0x2C,	/* 0x2C (Set ) */
 	CMD_ID_RANDOM_RX_RESET_DE = 0x2D,	/* 0x2D (Set ) */
@@ -1549,6 +1551,12 @@
 	UINT_8 aucReserved[3];
 } CMD_NIC_POWER_CTRL, *P_CMD_NIC_POWER_CTRL;
 
+/* CMD_ID_KEEP_FULL_PWR */
+struct CMD_KEEP_FULL_PWR_T {
+	UINT_8 ucEnable;
+	UINT_8 aucReserved[3];
+};
+
 /* CMD_ID_POWER_SAVE_MODE */
 typedef struct _CMD_PS_PROFILE_T {
 	UINT_8 ucBssIndex;
diff --git a/include/wlan_lib.h b/include/wlan_lib.h
index 96d6516..c660539 100644
--- a/include/wlan_lib.h
+++ b/include/wlan_lib.h
@@ -203,6 +203,10 @@
 #define INVALID_WOW_WAKE_UP_REASON 255
 #endif
 
+#if CFG_SUPPORT_ADVANCE_CONTROL
+#define KEEP_FULL_PWR_TRAFFIC_REPORT_BIT BIT(0)
+#define KEEP_FULL_PWR_NOISE_HISTOGRAM_BIT BIT(1)
+#endif
 
 typedef enum _CMD_VER_T {
 	CMD_VER_1, /* Type[2]+String[32]+Value[32] */
@@ -1072,6 +1076,8 @@
 
 WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode);
 
+WLAN_STATUS wlanKeepFullPwr(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable);
+
 BOOLEAN wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo);
 
 WLAN_STATUS wlanProcessQueuedSwRfb(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead);
diff --git a/os/linux/gl_wext_priv.c b/os/linux/gl_wext_priv.c
index 10d9c8f..15f86dd 100644
--- a/os/linux/gl_wext_priv.c
+++ b/os/linux/gl_wext_priv.c
@@ -9366,9 +9366,11 @@
 	cmd->ucBand = ucBand;
 
 	if (strnicmp(apcArgv[1], "ENABLE", strlen("ENABLE")) == 0) {
+		prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap |= KEEP_FULL_PWR_TRAFFIC_REPORT_BIT;
 		cmd->ucAction = CMD_GET_REPORT_ENABLE;
 		cmd->u2Type |= CMD_ADV_CONTROL_SET;
 	} else if (strnicmp(apcArgv[1], "DISABLE", strlen("DISABLE")) == 0) {
+		prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap &= ~KEEP_FULL_PWR_TRAFFIC_REPORT_BIT;
 		cmd->ucAction = CMD_GET_REPORT_DISABLE;
 		cmd->u2Type |= CMD_ADV_CONTROL_SET;
 	} else if (strnicmp(apcArgv[1], "RESET", strlen("RESET")) == 0) {
@@ -10192,9 +10194,11 @@
 	cmd->u2Len = sizeof(*cmd);
 
 	if (strnicmp(apcArgv[1], "ENABLE", strlen("ENABLE")) == 0) {
+		prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap |= KEEP_FULL_PWR_NOISE_HISTOGRAM_BIT;
 		cmd->ucAction = CMD_NOISE_HISTOGRAM_ENABLE;
 		cmd->u2Type |= CMD_ADV_CONTROL_SET;
 	} else if (strnicmp(apcArgv[1], "DISABLE", strlen("DISABLE")) == 0) {
+		prGlueInfo->prAdapter->u4IsKeepFullPwrBitmap &= ~KEEP_FULL_PWR_NOISE_HISTOGRAM_BIT;
 		cmd->ucAction = CMD_NOISE_HISTOGRAM_DISABLE;
 		cmd->u2Type |= CMD_ADV_CONTROL_SET;
 	} else if (strnicmp(apcArgv[1], "RESET", strlen("RESET")) == 0) {