Browse Source

qcacmn: Auto Detect SoC Power Collapse Failure changes

Add host support for detecting SOC power collapse failures in FW and
communicating the same to framework.

Change-Id: Icee39c896802c4d7136e0b8ef442a33feeb4799c
CRs-Fixed: 2016580
Ravi Kumar Bokka 8 years ago
parent
commit
4a517a223e

+ 35 - 32
os_if/linux/qca_vendor.h

@@ -726,6 +726,7 @@ enum qca_nl80211_vendor_subcmds_index {
 	QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
 	QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX,
 	QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
+	QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX,
 };
 
 /**
@@ -772,6 +773,40 @@ enum qca_wlan_vendor_attr_tdls_disable {
 		QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_AFTER_LAST - 1,
 };
 
+/**
+ * qca_chip_power_save_failure_reason: Power save failure reason
+ * @QCA_CHIP_POWER_SAVE_FAILURE_REASON_PROTOCOL: Indicates power save failure
+ * due to protocol/module.
+ * @QCA_CHIP_POWER_SAVE_FAILURE_REASON_HARDWARE: power save failure
+ * due to hardware
+ */
+enum qca_chip_power_save_failure_reason {
+	QCA_CHIP_POWER_SAVE_FAILURE_REASON_PROTOCOL = 0,
+	QCA_CHIP_POWER_SAVE_FAILURE_REASON_HARDWARE = 1,
+};
+
+/**
+ * qca_attr_chip_power_save_failure: attributes to vendor subcmd
+ * @QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE. This carry the requisite
+ * information leading to the power save failure.
+ * @QCA_ATTR_CHIP_POWER_SAVE_FAILURE_INVALID : invalid
+ * @QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON : power save failure reason
+ * represented by enum qca_chip_power_save_failure_reason
+ * @QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST : Last
+ * @QCA_ATTR_CHIP_POWER_SAVE_FAILURE_MAX : Max value
+ */
+enum qca_attr_chip_power_save_failure {
+	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_INVALID = 0,
+
+	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON = 1,
+
+	/* keep last */
+	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST,
+	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_MAX =
+		QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST - 1,
+};
+
+
 /**
  * enum qca_wlan_vendor_attr_tdls_get_status - tdls get status attribute
  *
@@ -2403,38 +2438,6 @@ enum qca_wlan_vendor_channel_prop_flags_ext {
 	QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CAC_VALID       = 1 << 9,
 };
 
-enum qca_chip_power_save_failure_reason {
-	/*
-	 * Indicates if the reason for the failure is due to a protocol
-	 * layer/module.
-	 */
-	QCA_CHIP_POWER_SAVE_FAILURE_REASON_PROTOCOL = 0,
-	/*
-	 * Indicates if the reason for the failure is due to a hardware issue.
-	 */
-	QCA_CHIP_POWER_SAVE_FAILURE_REASON_HARDWARE = 1,
-};
-
-/**
- * qca_attr_chip_power_save_failure: Attributes to vendor subcmd
- * QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE. This carries the requisite
- * information leading to the power save failure.
- */
-enum qca_attr_chip_power_save_failure {
-	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_INVALID = 0,
-	/*
-	 * Reason to cause the power save failure.
-	 * These reasons are represented by
-	 * enum qca_chip_power_save_failure_reason.
-	 */
-	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON = 1,
-
-	/* keep last */
-	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST,
-	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_MAX =
-		QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST - 1,
-};
-
 /**
  * qca_wlan_vendor_attr_nud_stats_set: Attributes to vendor subcmd
  * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carries the requisite

+ 30 - 0
pmo/core/inc/wlan_pmo_static_config.h

@@ -84,4 +84,34 @@ void pmo_update_target_service(struct wlan_objmgr_psoc *psoc,
 void pmo_update_ra_limit(struct wlan_objmgr_psoc *psoc,
 	bool bpf_enabled);
 
+/**
+ * pmo_set_wow_event_bitmap() - Assign bitmask with wow event
+ * @event: wow event
+ * @wow_bitmap_size: wow bitmask size
+ * @bitmask: wow bitmask field
+ *
+ * Return: none
+ */
+void pmo_set_wow_event_bitmap(WOW_WAKE_EVENT_TYPE event,
+			      uint32_t wow_bitmap_size,
+			      uint32_t *bitmask);
+
+/**
+ * pmo_set_sta_wow_bitmask() - set predefined STA wow wakeup events
+ * @bitmask: bitmask field
+ * @wow_bitmask_size: bitmask field size
+ *
+ * Return: none
+ */
+void pmo_set_sta_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmask_size);
+
+/**
+ * pmo_set_sap_wow_bitmask() - set predefined SAP wow wakeup events
+ * @bitmask: bitmask field
+ * @wow_bitmask_size: bitmask field size
+ *
+ * Return: none
+ */
+void pmo_set_sap_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmask_size);
+
 #endif /* end  of _WLAN_PMO_STATIC_CONFIG_H_ */

+ 31 - 2
pmo/core/inc/wlan_pmo_wow.h

@@ -103,6 +103,8 @@
  * attempt to BMPS fails, request for WoWL will be rejected.
  */
 
+#define PMO_WOW_MAX_EVENT_BM_LEN 4
+
 /**
  * pmo_get_and_increment_wow_default_ptrn() -Get and increment wow default ptrn
  * @vdev_ctx: pmo vdev priv ctx
@@ -241,7 +243,7 @@ QDF_STATUS pmo_core_wow_exit(struct wlan_objmgr_vdev *vdev);
  * Return: none
  */
 void pmo_core_enable_wakeup_event(struct wlan_objmgr_psoc *psoc,
-	uint32_t vdev_id, uint32_t bitmap);
+	uint32_t vdev_id, uint32_t *bitmap);
 
 /**
  * pmo_core_disable_wakeup_event() -  disable wow wakeup events
@@ -252,7 +254,7 @@ void pmo_core_enable_wakeup_event(struct wlan_objmgr_psoc *psoc,
  * Return: none
  */
 void pmo_core_disable_wakeup_event(struct wlan_objmgr_psoc *psoc,
-	uint32_t vdev_id, uint32_t bitmap);
+	uint32_t vdev_id, uint32_t *bitmap);
 
 /**
  * pmo_is_wow_applicable(): should enable wow
@@ -573,4 +575,31 @@ bool pmo_core_is_nan_enabled(struct wlan_objmgr_vdev *vdev)
 }
 #endif
 
+/**
+ * pmo_get_event_bitmap_idx() - get indices for extended wow bitmaps
+ * @event: wow event
+ * @wow_bitmap_size: WOW bitmap size
+ * @bit_idx: bit index
+ * @idx: byte index
+ *
+ * Return: none
+ */
+static inline void pmo_get_event_bitmap_idx(WOW_WAKE_EVENT_TYPE event,
+			      uint32_t wow_bitmap_size,
+			      uint32_t *bit_idx,
+			      uint32_t *idx)
+{
+
+	if (!bit_idx || !idx || wow_bitmap_size == 0) {
+		pmo_err("bit_idx:%p idx:%p wow_bitmap_size:%u",
+			 bit_idx, idx, wow_bitmap_size);
+		return;
+	}
+	if (event == 0) {
+		*idx = *bit_idx = 0;
+	} else {
+		*idx = event / (wow_bitmap_size * 8);
+		*bit_idx = event % (wow_bitmap_size * 8);
+	}
+}
 #endif /* end  of _WLAN_PMO_WOW_H_ */

+ 23 - 42
pmo/core/src/wlan_pmo_static_config.c

@@ -25,31 +25,6 @@
 #include "wlan_pmo_wow.h"
 #include "wlan_pmo_obj_mgmt_public_struct.h"
 
-#define PMO_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\
-				(1 << WOW_CLIENT_KICKOUT_EVENT) |\
-				(1 << WOW_PATTERN_MATCH_EVENT) |\
-				(1 << WOW_MAGIC_PKT_RECVD_EVENT) |\
-				(1 << WOW_DEAUTH_RECVD_EVENT) |\
-				(1 << WOW_DISASSOC_RECVD_EVENT) |\
-				(1 << WOW_BMISS_EVENT) |\
-				(1 << WOW_GTK_ERR_EVENT) |\
-				(1 << WOW_BETTER_AP_EVENT) |\
-				(1 << WOW_HTT_EVENT) |\
-				(1 << WOW_RA_MATCH_EVENT) |\
-				(1 << WOW_NLO_DETECTED_EVENT) |\
-				(1 << WOW_EXTSCAN_EVENT) |\
-				(1 << WOW_OEM_RESPONSE_EVENT)|\
-				(1 << WOW_TDLS_CONN_TRACKER_EVENT)) \
-
-#define PMO_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\
-				(1 << WOW_CLIENT_KICKOUT_EVENT) |\
-				(1 << WOW_PATTERN_MATCH_EVENT) |\
-				(1 << WOW_AUTH_REQ_EVENT) |\
-				(1 << WOW_ASSOC_REQ_EVENT) |\
-				(1 << WOW_DEAUTH_RECVD_EVENT) |\
-				(1 << WOW_DISASSOC_RECVD_EVENT) |\
-				(1 << WOW_HTT_EVENT)) \
-
 static const uint8_t arp_ptrn[] = {0x08, 0x06};
 static const uint8_t arp_mask[] = {0xff, 0xff};
 static const uint8_t ns_ptrn[] = {0x86, 0xDD};
@@ -58,13 +33,10 @@ static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8};
 
 void pmo_register_wow_wakeup_events(struct wlan_objmgr_vdev *vdev)
 {
-	uint32_t event_bitmap;
+	uint32_t event_bitmap[PMO_WOW_MAX_EVENT_BM_LEN] = {0};
 	uint8_t vdev_id;
-	struct wlan_objmgr_psoc *psoc;
 	enum tQDF_ADAPTER_MODE  vdev_opmode = QDF_MAX_NO_OF_MODE;
 
-	psoc = pmo_vdev_get_psoc(vdev);
-
 	vdev_opmode = pmo_get_vdev_opmode(vdev);
 	vdev_id = pmo_vdev_get_id(vdev);
 	pmo_info("vdev_opmode %d vdev_id %d", vdev_opmode, vdev_id);
@@ -73,22 +45,28 @@ void pmo_register_wow_wakeup_events(struct wlan_objmgr_vdev *vdev)
 	case QDF_STA_MODE:
 	case QDF_P2P_DEVICE_MODE:
 		/* Configure STA/P2P CLI mode specific default wake up events */
-		event_bitmap = PMO_WOW_STA_WAKE_UP_EVENTS;
-		pmo_info("STA specific default wake up event 0x%x vdev id %d",
-			event_bitmap, vdev_id);
+		pmo_set_sta_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN);
+
+		pmo_info("STA specific default wake up event 0x%x%x%x%x vdev id %d",
+			event_bitmap[0], event_bitmap[1], event_bitmap[2],
+			event_bitmap[3], vdev_id);
 		break;
 	case QDF_IBSS_MODE:
 		/* Configure IBSS mode specific default wake up events */
-		event_bitmap = (PMO_WOW_STA_WAKE_UP_EVENTS |
-				(1 << WOW_BEACON_EVENT));
-		pmo_info("IBSS specific default wake up event 0x%x vdev id %d",
-			event_bitmap, vdev_id);
+		pmo_set_sta_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN);
+		pmo_set_wow_event_bitmap(WOW_BEACON_EVENT,
+					 PMO_WOW_MAX_EVENT_BM_LEN,
+					 event_bitmap);
+		pmo_info("IBSS specific default wake up event 0x%x%x%x%x vdev id %d",
+			event_bitmap[0], event_bitmap[1], event_bitmap[2],
+			event_bitmap[3], vdev_id);
 		break;
 	case QDF_SAP_MODE:
 		/* Configure SAP/GO mode specific default wake up events */
-		event_bitmap = PMO_WOW_SAP_WAKE_UP_EVENTS;
-		pmo_info("SAP specific default wake up event 0x%x vdev id %d",
-			event_bitmap, vdev_id);
+		pmo_set_sap_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN);
+		pmo_info("IBSS specific default wake up event 0x%x%x%x%x vdev id %d",
+			event_bitmap[0], event_bitmap[1], event_bitmap[2],
+			event_bitmap[3], vdev_id);
 		break;
 	case QDF_NDI_MODE:
 		/*
@@ -96,9 +74,12 @@ void pmo_register_wow_wakeup_events(struct wlan_objmgr_vdev *vdev)
 		 * Following routine sends the command to firmware.
 		 */
 #ifdef WLAN_FEATURE_NAN_DATAPATH
-		event_bitmap = (1 << WOW_NAN_DATA_EVENT);
-		pmo_info("NDI specific default wake up event 0x%x vdev id %d",
-			event_bitmap, vdev_id);
+		pmo_set_wow_event_bitmap(WOW_NAN_DATA_EVENT,
+					 PMO_WOW_MAX_EVENT_BM_LEN,
+					 event_bitmap);
+		pmo_info("IBSS specific default wake up event 0x%x%x%x%x vdev id %d",
+			event_bitmap[0], event_bitmap[1], event_bitmap[2],
+			event_bitmap[3], vdev_id);
 #endif
 		break;
 	default:

+ 55 - 21
pmo/core/src/wlan_pmo_suspend_resume.c

@@ -32,7 +32,8 @@
 #include "htc_api.h"
 #include "wlan_pmo_obj_mgmt_api.h"
 #include <wlan_scan_ucfg_api.h>
-
+#include "cds_api.h"
+#include "wlan_pmo_static_config.h"
 
 /**
  * pmo_core_calculate_listen_interval() - Calculate vdev listen interval
@@ -208,43 +209,75 @@ void pmo_core_update_wow_bus_suspend(struct wlan_objmgr_psoc *psoc,
 	pmo_tgt_psoc_update_wow_bus_suspend_state(psoc, val);
 }
 
+/* Define for conciseness */
+#define BM_LEN PMO_WOW_MAX_EVENT_BM_LEN
+#define EV_NLO WOW_NLO_SCAN_COMPLETE_EVENT
+#define EV_PWR WOW_CHIP_POWER_FAILURE_DETECT_EVENT
+
 void pmo_core_configure_dynamic_wake_events(struct wlan_objmgr_psoc *psoc)
 {
 	int vdev_id;
-	int enable_mask;
-	int disable_mask;
-	struct wlan_objmgr_psoc_objmgr *objmgr;
+	uint32_t adapter_type;
+	uint32_t enable_mask[BM_LEN];
+	uint32_t disable_mask[BM_LEN];
 	struct wlan_objmgr_vdev *vdev;
+	struct pmo_psoc_priv_obj *psoc_ctx;
+	bool enable_configured;
+	bool disable_configured;
 
 	/* Iterate through VDEV list */
 	for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) {
-		wlan_psoc_obj_lock(psoc);
-		objmgr = &psoc->soc_objmgr;
-		if (!objmgr->wlan_vdev_list[vdev_id]) {
-			wlan_psoc_obj_unlock(psoc);
+
+		enable_configured = false;
+		disable_configured = false;
+
+		qdf_mem_set(enable_mask,  sizeof(uint32_t) * BM_LEN, 0);
+		qdf_mem_set(disable_mask, sizeof(uint32_t) * BM_LEN, 0);
+
+		vdev = pmo_psoc_get_vdev(psoc, vdev_id);
+		if (!vdev)
 			continue;
-		}
-		vdev = objmgr->wlan_vdev_list[vdev_id];
-		wlan_psoc_obj_unlock(psoc);
 
-		enable_mask = 0;
-		disable_mask = 0;
 		if (ucfg_scan_get_pno_in_progress(vdev)) {
-			if (ucfg_scan_get_pno_match(vdev))
-				enable_mask |=
-					(1 << WOW_NLO_SCAN_COMPLETE_EVENT);
-			else
-				disable_mask |=
-					(1 << WOW_NLO_SCAN_COMPLETE_EVENT);
+			if (ucfg_scan_get_pno_match(vdev)) {
+				pmo_set_wow_event_bitmap(EV_NLO,
+							 BM_LEN,
+							 enable_mask);
+				enable_configured = true;
+			} else {
+				pmo_set_wow_event_bitmap(EV_NLO,
+							 BM_LEN,
+							 disable_mask);
+				disable_configured = true;
+			}
 		}
 
-		if (enable_mask != 0)
+		adapter_type = pmo_get_vdev_opmode(vdev);
+
+		psoc_ctx = pmo_psoc_get_priv(psoc);
+
+		if (psoc_ctx->psoc_cfg.auto_power_save_fail_mode &&
+		    (adapter_type == QDF_STA_MODE ||
+		     adapter_type == QDF_P2P_CLIENT_MODE)
+		   ) {
+			if (psoc_ctx->is_device_in_low_pwr_mode &&
+				psoc_ctx->is_device_in_low_pwr_mode(vdev_id))
+				pmo_set_wow_event_bitmap(EV_PWR,
+						 BM_LEN,
+						 enable_mask);
+				pmo_core_enable_wakeup_event(psoc, vdev_id,
+					enable_mask);
+				enable_configured = true;
+		}
+		if (enable_configured)
 			pmo_core_enable_wakeup_event(psoc, vdev_id,
 				enable_mask);
-		if (disable_mask != 0)
+
+		if (disable_configured)
 			pmo_core_disable_wakeup_event(psoc, vdev_id,
 					disable_mask);
 	}
+
 }
 
 /**
@@ -266,6 +299,7 @@ static QDF_STATUS pmo_core_psoc_configure_suspend(struct wlan_objmgr_psoc *psoc)
 	if (pmo_core_is_wow_applicable(psoc)) {
 		pmo_info("WOW Suspend");
 		pmo_core_apply_lphb(psoc);
+
 		pmo_core_configure_dynamic_wake_events(psoc);
 		pmo_core_update_wow_enable(psoc_ctx, true);
 		pmo_core_update_wow_enable_cmd_sent(psoc_ctx, false);

+ 104 - 7
pmo/core/src/wlan_pmo_wow.c

@@ -24,7 +24,7 @@
 #include "wlan_pmo_main.h"
 #include "wlan_pmo_obj_mgmt_public_struct.h"
 #include <wlan_scan_ucfg_api.h>
-
+#include "wlan_pmo_static_config.h"
 
 static inline int pmo_find_wow_ptrn_len(const char *ptrn)
 {
@@ -62,7 +62,7 @@ QDF_STATUS pmo_core_wow_exit(struct wlan_objmgr_vdev *vdev)
 }
 
 void pmo_core_enable_wakeup_event(struct wlan_objmgr_psoc *psoc,
-	uint32_t vdev_id, uint32_t bitmap)
+	uint32_t vdev_id, uint32_t *bitmap)
 {
 	QDF_STATUS status;
 	struct wlan_objmgr_vdev *vdev;
@@ -83,8 +83,8 @@ void pmo_core_enable_wakeup_event(struct wlan_objmgr_psoc *psoc,
 	if (QDF_IS_STATUS_ERROR(status))
 		goto out;
 
-	pmo_info("enable wakeup event vdev_id %d wake up event 0x%x",
-		vdev_id, bitmap);
+	pmo_info("enable wakeup event vdev_id %d wake up event 0x%x%x%x%x",
+		vdev_id, bitmap[0], bitmap[1], bitmap[2], bitmap[3]);
 	pmo_tgt_enable_wow_wakeup_event(vdev, bitmap);
 
 	pmo_vdev_put_ref(vdev);
@@ -94,7 +94,7 @@ out:
 }
 
 void pmo_core_disable_wakeup_event(struct wlan_objmgr_psoc *psoc,
-	uint32_t vdev_id, uint32_t bitmap)
+	uint32_t vdev_id, uint32_t *bitmap)
 {
 	QDF_STATUS status;
 	struct wlan_objmgr_vdev *vdev;
@@ -115,8 +115,8 @@ void pmo_core_disable_wakeup_event(struct wlan_objmgr_psoc *psoc,
 	if (QDF_IS_STATUS_ERROR(status))
 		goto out;
 
-	pmo_info("Disable wakeup eventvdev_id %d wake up event 0x%x",
-		vdev_id, bitmap);
+	pmo_info("Disable wakeup event vdev_id %d wake up event 0x%x%x%x%x",
+		vdev_id, bitmap[0], bitmap[1], bitmap[2], bitmap[3]);
 	pmo_tgt_disable_wow_wakeup_event(vdev, bitmap);
 
 	pmo_vdev_put_ref(vdev);
@@ -245,3 +245,100 @@ bool pmo_core_is_wow_applicable(struct wlan_objmgr_psoc *psoc)
 	return false;
 }
 
+void pmo_set_wow_event_bitmap(WOW_WAKE_EVENT_TYPE event,
+			      uint32_t wow_bitmap_size,
+			      uint32_t *bitmask)
+{
+	uint32_t bit_idx = 0, idx = 0;
+
+	if (!bitmask || wow_bitmap_size < PMO_WOW_MAX_EVENT_BM_LEN) {
+		pmo_err("wow bitmask length shorter than %d",
+			 PMO_WOW_MAX_EVENT_BM_LEN);
+		return;
+	}
+	pmo_get_event_bitmap_idx(event, wow_bitmap_size, &bit_idx, &idx);
+	bitmask[idx] |= 1 << bit_idx;
+
+	pmo_debug("%s: bitmask updated %x%x%x%x",
+		 __func__, bitmask[0], bitmask[1], bitmask[2], bitmask[3]);
+}
+
+void pmo_set_sta_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmap_size)
+{
+
+	pmo_set_wow_event_bitmap(WOW_CSA_IE_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_CLIENT_KICKOUT_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_PATTERN_MATCH_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_MAGIC_PKT_RECVD_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_DEAUTH_RECVD_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_DISASSOC_RECVD_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_BMISS_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_GTK_ERR_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_BETTER_AP_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_HTT_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_RA_MATCH_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_NLO_DETECTED_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_EXTSCAN_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_OEM_RESPONSE_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_TDLS_CONN_TRACKER_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_11D_SCAN_EVENT,
+				 wow_bitmap_size,
+				 bitmask);
+
+}
+
+void pmo_set_sap_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmap_size)
+{
+
+	pmo_set_wow_event_bitmap(WOW_PROBE_REQ_WPS_IE_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_PATTERN_MATCH_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_AUTH_REQ_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_ASSOC_REQ_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_DEAUTH_RECVD_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_DISASSOC_RECVD_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+	pmo_set_wow_event_bitmap(WOW_HTT_EVENT,
+			     wow_bitmap_size,
+			     bitmask);
+}

+ 2 - 0
pmo/dispatcher/inc/wlan_pmo_common_public_struct.h

@@ -264,6 +264,7 @@ enum pmo_offload_trigger {
  * @sta_mod_dtim: station modulated DTIM value
  * @sta_max_li_mod_dtim: station max listen interval DTIM value
  * @power_save_mode: power save mode for psoc
+ * @auto_power_save_fail_mode: auto detect power save failure
  */
 struct pmo_psoc_cfg {
 	bool ptrn_match_enable_all_vdev;
@@ -289,6 +290,7 @@ struct pmo_psoc_cfg {
 	uint8_t sta_mod_dtim;
 	uint8_t sta_max_li_mod_dtim;
 	uint8_t power_save_mode;
+	bool auto_power_save_fail_mode;
 };
 
 #endif /* end  of _WLAN_PMO_COMMONP_STRUCT_H_ */

+ 23 - 0
pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h

@@ -215,4 +215,27 @@ QDF_STATUS pmo_unregister_get_pause_bitmap(struct wlan_objmgr_psoc *psoc,
 		pmo_get_pause_bitmap handler);
 
 
+/**
+ * pmo_register_is_device_in_low_pwr_mode(): API to get register device  power
+ * save check notifier.
+ * @psoc: objmgr psoc handle
+ * @handler: device power save check notifier
+ *
+ * Return QDF_STATUS status - in case of success else return error
+ */
+QDF_STATUS pmo_register_is_device_in_low_pwr_mode(struct wlan_objmgr_psoc *psoc,
+		pmo_is_device_in_low_pwr_mode handler);
+
+/**
+ * pmo_unregister_is_device_in_low_pwr_mode(): API to unregister device  power
+ * save check notifier.
+ * @psoc: objmgr psoc handle
+ * @handler: device power save check notifier
+ *
+ * Return QDF_STATUS status - in case of success else return error
+ */
+QDF_STATUS pmo_unregister_is_device_in_low_pwr_mode(
+			struct wlan_objmgr_psoc *psoc,
+			pmo_is_device_in_low_pwr_mode handler);
+
 #endif /* end  of _WLAN_PMO_OBJ_MGMT_API_H_ */

+ 6 - 0
pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h

@@ -44,6 +44,11 @@ typedef void (*pmo_notify_pause_bitmap)(
  */
 typedef  uint16_t(*pmo_get_pause_bitmap)(uint8_t vdev_id);
 
+/**
+ * typedef to know is deviec is in power save mode
+ */
+typedef  bool (*pmo_is_device_in_low_pwr_mode)(uint8_t vdev_id);
+
 /**
  * struct pmo_psoc_priv_obj - psoc related data require for pmo
  * @psoc_cfg: place holder for psoc configuration
@@ -65,6 +70,7 @@ struct pmo_psoc_priv_obj {
 	void *txrx_hdl;
 	pmo_notify_pause_bitmap pause_bitmap_notifier;
 	pmo_get_pause_bitmap get_pause_bitmap;
+	pmo_is_device_in_low_pwr_mode is_device_in_low_pwr_mode;
 	qdf_spinlock_t lock;
 };
 

+ 2 - 2
pmo/dispatcher/inc/wlan_pmo_tgt_api.h

@@ -112,7 +112,7 @@ QDF_STATUS pmo_tgt_disable_ns_offload_req(struct wlan_objmgr_vdev *vdev,
  * Return: QDF status
  */
 QDF_STATUS pmo_tgt_enable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev,
-		uint32_t bitmap);
+		uint32_t *bitmap);
 
 /**
  * pmo_tgt_disable_wow_wakeup_event() - Send Disable wow wakeup events to fwr
@@ -122,7 +122,7 @@ QDF_STATUS pmo_tgt_enable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev,
  * Return: QDF status
  */
 QDF_STATUS pmo_tgt_disable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev,
-		uint32_t bitmap);
+		uint32_t *bitmap);
 
 /**
  * pmo_tgt_send_wow_patterns_to_fw() - Sends WOW patterns to FW.

+ 1 - 1
pmo/dispatcher/inc/wlan_pmo_ucfg_api.h

@@ -91,7 +91,7 @@ QDF_STATUS pmo_ucfg_update_psoc_config(struct wlan_objmgr_psoc *psoc,
  * Return: none
  */
 void pmo_ucfg_enable_wakeup_event(struct wlan_objmgr_psoc *psoc,
-	uint32_t vdev_id, uint32_t bitmap);
+	uint32_t vdev_id, uint32_t *bitmap);
 
 /**
  * pmo_ucfg_disable_wakeup_event() -  disable wow wakeup events

+ 89 - 0
pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c

@@ -566,6 +566,7 @@ QDF_STATUS pmo_register_pause_bitmap_notifier(struct wlan_objmgr_psoc *psoc,
 		pmo_notify_pause_bitmap handler)
 {
 	struct pmo_psoc_priv_obj *psoc_ctx;
+	QDF_STATUS status;
 
 	if (!psoc) {
 		pmo_err("psoc is null");
@@ -577,10 +578,16 @@ QDF_STATUS pmo_register_pause_bitmap_notifier(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	status = pmo_psoc_get_ref(psoc);
+	if (status != QDF_STATUS_SUCCESS) {
+		pmo_err("pmo cannot get the reference out of psoc");
+		return status;
+	}
 	psoc_ctx = pmo_psoc_get_priv(psoc);
 	qdf_spin_lock_bh(&psoc_ctx->lock);
 	psoc_ctx->pause_bitmap_notifier = handler;
 	qdf_spin_unlock_bh(&psoc_ctx->lock);
+	pmo_psoc_put_ref(psoc);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -589,6 +596,7 @@ QDF_STATUS pmo_unregister_pause_bitmap_notifier(struct wlan_objmgr_psoc *psoc,
 		pmo_notify_pause_bitmap handler)
 {
 	struct pmo_psoc_priv_obj *psoc_ctx;
+	QDF_STATUS status;
 
 	if (!psoc) {
 		pmo_err("psoc is null");
@@ -600,11 +608,17 @@ QDF_STATUS pmo_unregister_pause_bitmap_notifier(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	status = pmo_psoc_get_ref(psoc);
+	if (status != QDF_STATUS_SUCCESS) {
+		pmo_err("pmo cannot get the reference out of psoc");
+		return status;
+	}
 	psoc_ctx = pmo_psoc_get_priv(psoc);
 	qdf_spin_lock_bh(&psoc_ctx->lock);
 	if (psoc_ctx->pause_bitmap_notifier == handler)
 		psoc_ctx->pause_bitmap_notifier = NULL;
 	qdf_spin_unlock_bh(&psoc_ctx->lock);
+	pmo_psoc_put_ref(psoc);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -613,6 +627,7 @@ QDF_STATUS pmo_register_get_pause_bitmap(struct wlan_objmgr_psoc *psoc,
 		pmo_get_pause_bitmap handler)
 {
 	struct pmo_psoc_priv_obj *psoc_ctx;
+	QDF_STATUS status;
 
 	if (!psoc) {
 		pmo_err("psoc is null");
@@ -624,10 +639,16 @@ QDF_STATUS pmo_register_get_pause_bitmap(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	status = pmo_psoc_get_ref(psoc);
+	if (status != QDF_STATUS_SUCCESS) {
+		pmo_err("pmo cannot get the reference out of psoc");
+		return status;
+	}
 	psoc_ctx = pmo_psoc_get_priv(psoc);
 	qdf_spin_lock_bh(&psoc_ctx->lock);
 	psoc_ctx->get_pause_bitmap = handler;
 	qdf_spin_unlock_bh(&psoc_ctx->lock);
+	pmo_psoc_put_ref(psoc);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -636,6 +657,7 @@ QDF_STATUS pmo_unregister_get_pause_bitmap(struct wlan_objmgr_psoc *psoc,
 		pmo_get_pause_bitmap handler)
 {
 	struct pmo_psoc_priv_obj *psoc_ctx;
+	QDF_STATUS status;
 
 	if (!psoc) {
 		pmo_err("psoc is null");
@@ -647,11 +669,78 @@ QDF_STATUS pmo_unregister_get_pause_bitmap(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	status = pmo_psoc_get_ref(psoc);
+	if (status != QDF_STATUS_SUCCESS) {
+		pmo_err("pmo cannot get the reference out of psoc");
+		return status;
+	}
 	psoc_ctx = pmo_psoc_get_priv(psoc);
 	qdf_spin_lock_bh(&psoc_ctx->lock);
 	if (psoc_ctx->get_pause_bitmap == handler)
 		psoc_ctx->get_pause_bitmap = NULL;
 	qdf_spin_unlock_bh(&psoc_ctx->lock);
+	pmo_psoc_put_ref(psoc);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS pmo_register_is_device_in_low_pwr_mode(struct wlan_objmgr_psoc *psoc,
+		pmo_is_device_in_low_pwr_mode handler)
+{
+	struct pmo_psoc_priv_obj *psoc_ctx;
+	QDF_STATUS status;
+
+	if (!psoc) {
+		pmo_err("psoc is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!handler) {
+		pmo_err("pmo_get_pause_bitmap is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	status = pmo_psoc_get_ref(psoc);
+	if (status != QDF_STATUS_SUCCESS) {
+		pmo_err("pmo cannot get the reference out of psoc");
+		return status;
+	}
+	psoc_ctx = pmo_psoc_get_priv(psoc);
+	qdf_spin_lock_bh(&psoc_ctx->lock);
+	psoc_ctx->is_device_in_low_pwr_mode = handler;
+	qdf_spin_unlock_bh(&psoc_ctx->lock);
+	pmo_psoc_put_ref(psoc);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS pmo_unregister_is_device_in_low_pwr_mode(
+			struct wlan_objmgr_psoc *psoc,
+			pmo_is_device_in_low_pwr_mode handler)
+{
+	struct pmo_psoc_priv_obj *psoc_ctx;
+	QDF_STATUS status;
+
+	if (!psoc) {
+		pmo_err("psoc is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!handler) {
+		pmo_err("pmo_get_pause_bitmap is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	status = pmo_psoc_get_ref(psoc);
+	if (status != QDF_STATUS_SUCCESS) {
+		pmo_err("pmo cannot get the reference out of psoc");
+		return status;
+	}
+	psoc_ctx = pmo_psoc_get_priv(psoc);
+	qdf_spin_lock_bh(&psoc_ctx->lock);
+	psoc_ctx->is_device_in_low_pwr_mode = NULL;
+	qdf_spin_unlock_bh(&psoc_ctx->lock);
+	pmo_psoc_put_ref(psoc);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 2 - 2
pmo/dispatcher/src/wlan_pmo_tgt_wow.c

@@ -25,7 +25,7 @@
 
 QDF_STATUS pmo_tgt_enable_wow_wakeup_event(
 		struct wlan_objmgr_vdev *vdev,
-		uint32_t bitmap)
+		uint32_t *bitmap)
 {
 	QDF_STATUS status;
 	struct wlan_objmgr_psoc *psoc;
@@ -52,7 +52,7 @@ out:
 
 QDF_STATUS pmo_tgt_disable_wow_wakeup_event(
 		struct wlan_objmgr_vdev *vdev,
-		uint32_t bitmap)
+		uint32_t *bitmap)
 {
 	QDF_STATUS status;
 	struct wlan_objmgr_psoc *psoc;

+ 2 - 2
pmo/dispatcher/src/wlan_pmo_ucfg_api.c

@@ -59,7 +59,7 @@ bool pmo_ucfg_is_vdev_supports_offload(struct wlan_objmgr_vdev *vdev)
 }
 
 void pmo_ucfg_enable_wakeup_event(struct wlan_objmgr_psoc *psoc,
-	uint32_t vdev_id, uint32_t bitmap)
+	uint32_t vdev_id, uint32_t *bitmap)
 {
 	pmo_core_enable_wakeup_event(psoc, vdev_id, bitmap);
 }
@@ -67,7 +67,7 @@ void pmo_ucfg_enable_wakeup_event(struct wlan_objmgr_psoc *psoc,
 void pmo_ucfg_disable_wakeup_event(struct wlan_objmgr_psoc *psoc,
 	uint32_t vdev_id, uint32_t bitmap)
 {
-	pmo_core_disable_wakeup_event(psoc, vdev_id, bitmap);
+	pmo_core_disable_wakeup_event(psoc, vdev_id, &bitmap);
 }
 
 QDF_STATUS pmo_ucfg_cache_arp_offload_req(struct pmo_arp_req *arp_req)

+ 2 - 2
target_if/pmo/inc/target_if_pmo.h

@@ -36,7 +36,7 @@
  * Return: QDF status
  */
 QDF_STATUS target_if_pmo_enable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev,
-		uint32_t bitmap);
+		uint32_t *bitmap);
 
 /**
  * target_if_pmo_disable_wow_wakeup_event() -  Disable wow wakeup events.
@@ -47,7 +47,7 @@ QDF_STATUS target_if_pmo_enable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev,
  * Return: QDF status
  */
 QDF_STATUS target_if_pmo_disable_wow_wakeup_event(
-		struct wlan_objmgr_vdev *vdev, uint32_t bitmap);
+		struct wlan_objmgr_vdev *vdev, uint32_t *bitmap);
 
 /**
  * target_if_pmo_send_wow_patterns_to_fw() - Sends WOW patterns to FW.

+ 2 - 2
target_if/pmo/src/target_if_pmo_wow.c

@@ -28,7 +28,7 @@
 #include "wmi_unified_api.h"
 
 QDF_STATUS target_if_pmo_enable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev,
-		uint32_t bitmap)
+		uint32_t *bitmap)
 {
 	uint8_t vdev_id;
 	struct wlan_objmgr_psoc *psoc;
@@ -55,7 +55,7 @@ QDF_STATUS target_if_pmo_enable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev,
 }
 
 QDF_STATUS target_if_pmo_disable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev,
-		uint32_t bitmap)
+		uint32_t *bitmap)
 {
 	uint8_t vdev_id;
 	struct wlan_objmgr_psoc *psoc;

+ 2 - 2
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -201,10 +201,10 @@ struct wlan_lmac_if_pmo_tx_ops {
 						*pmo_clr_pkt_fltr_param);
 	QDF_STATUS (*send_enable_wow_wakeup_event_req)(
 			struct wlan_objmgr_vdev *vdev,
-			uint32_t bitmap);
+			uint32_t *bitmap);
 	QDF_STATUS (*send_disable_wow_wakeup_event_req)(
 			struct wlan_objmgr_vdev *vdev,
-			uint32_t bitmap);
+			uint32_t *bitmap);
 	QDF_STATUS (*send_add_wow_pattern)(
 			struct wlan_objmgr_vdev *vdev,
 			uint8_t ptrn_id, const uint8_t *ptrn, uint8_t ptrn_len,

+ 1 - 1
wmi/inc/wmi_unified_pmo_api.h

@@ -41,7 +41,7 @@
  */
 QDF_STATUS wmi_unified_add_wow_wakeup_event_cmd(void *wmi_hdl,
 					uint32_t vdev_id,
-					uint32_t bitmap,
+					uint32_t *bitmap,
 					bool enable);
 
 /**

+ 1 - 1
wmi/inc/wmi_unified_priv.h

@@ -489,7 +489,7 @@ QDF_STATUS (*send_link_status_req_cmd)(wmi_unified_t wmi_handle,
 #ifdef WLAN_PMO_ENABLE
 QDF_STATUS (*send_add_wow_wakeup_event_cmd)(wmi_unified_t wmi_handle,
 					uint32_t vdev_id,
-					uint32_t bitmap,
+					uint32_t *bitmap,
 					bool enable);
 
 QDF_STATUS (*send_wow_patterns_to_fw_cmd)(wmi_unified_t wmi_handle,

+ 1 - 1
wmi/src/wmi_unified_pmo_api.c

@@ -27,7 +27,7 @@
 
 QDF_STATUS wmi_unified_add_wow_wakeup_event_cmd(void *wmi_hdl,
 					uint32_t vdev_id,
-					uint32_t bitmap,
+					uint32_t *bitmap,
 					bool enable)
 {
 	struct wmi_unified *wmi_handle = (struct wmi_unified *) wmi_hdl;

+ 7 - 5
wmi/src/wmi_unified_tlv.c

@@ -12550,7 +12550,7 @@ send_pdev_fips_cmd_tlv(wmi_unified_t wmi_handle,
  */
 static QDF_STATUS send_add_wow_wakeup_event_cmd_tlv(wmi_unified_t wmi_handle,
 					uint32_t vdev_id,
-					uint32_t bitmap,
+					uint32_t *bitmap,
 					bool enable)
 {
 	WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *cmd;
@@ -12571,7 +12571,12 @@ static QDF_STATUS send_add_wow_wakeup_event_cmd_tlv(wmi_unified_t wmi_handle,
 			       (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param));
 	cmd->vdev_id = vdev_id;
 	cmd->is_add = enable;
-	cmd->event_bitmap = bitmap;
+	qdf_mem_copy(&(cmd->event_bitmaps[0]), bitmap, sizeof(uint32_t) *
+		     WMI_WOW_MAX_EVENT_BM_LEN);
+
+	WMI_LOGD("Wakeup pattern 0x%x%x%x%x %s in fw", cmd->event_bitmaps[0],
+		 cmd->event_bitmaps[1], cmd->event_bitmaps[2],
+		 cmd->event_bitmaps[3], enable ? "enabled" : "disabled");
 
 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
 				   WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
@@ -12581,9 +12586,6 @@ static QDF_STATUS send_add_wow_wakeup_event_cmd_tlv(wmi_unified_t wmi_handle,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	WMI_LOGD("Wakeup pattern 0x%x %s in fw", bitmap,
-		 enable ? "enabled" : "disabled");
-
 	return QDF_STATUS_SUCCESS;
 }