diff --git a/core/cds/inc/cds_config.h b/core/cds/inc/cds_config.h
index f6c456a157c3..9e9954ec6b1f 100644
--- a/core/cds/inc/cds_config.h
+++ b/core/cds/inc/cds_config.h
@@ -117,6 +117,7 @@ enum active_bpf_mode {
* mode for uc packets
* @active_mc_bc_bpf_mode: Setting that determines how BPF is applied in
* active mode for MC/BC packets
+ * @auto_power_save_fail_mode: auto detect power save failure mode
* Structure for holding cds ini parameters.
*/
@@ -172,5 +173,6 @@ struct cds_config_info {
struct ol_tx_sched_wrr_ac_specs_t ac_specs[TX_WMM_AC_NUM];
enum active_bpf_mode active_uc_bpf_mode;
enum active_bpf_mode active_mc_bc_bpf_mode;
+ bool auto_power_save_fail_mode;
};
#endif /* !defined( __CDS_CONFIG_H ) */
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index f4482edccf77..ad38d76b90b4 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -7116,6 +7116,24 @@ enum hdd_link_speed_rpt_type {
#define CFG_ENABLE_MEMORY_DEBUG_DEFAULT (1)
#endif
+/*
+ *
+ * g_auto_detect_power_failure_mode - auto detect power save failure mode
+ * @Min: 0 : Recovery
+ * @Max: 1 : WMI
+ * @Default: 0
+ *
+ * This ini specifies the behavior of FW in case of
+ * CHIP_POWER_SAVE_FAIL_DETECTED event
+ *
+ * Usage: External
+ *
+ *
+ */
+#define CFG_AUTO_DETECT_POWER_FAIL_MODE_NAME "g_auto_detect_power_failure_mode"
+#define CFG_AUTO_DETECT_POWER_FAIL_MODE_DEFAULT (0)
+#define CFG_AUTO_DETECT_POWER_FAIL_MODE_MIN (0)
+#define CFG_AUTO_DETECT_POWER_FAIL_MODE_MAX (1)
/*
*
@@ -11069,6 +11087,7 @@ struct hdd_config {
uint8_t enable_rts_sifsbursting;
uint8_t max_mpdus_inampdu;
uint16_t sap_max_mcs_txdata;
+ uint8_t auto_pwr_save_fail_mode;
};
#define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index e1ee064f6ea2..d265901b0760 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -2439,4 +2439,23 @@ int hdd_dbs_scan_selection_init(hdd_context_t *hdd_ctx);
*/
void hdd_start_complete(int ret);
+
+/**
+ * hdd_chip_pwr_save_fail_detected_cb() - chip power save failure detected
+ * callback
+ * @hddctx: HDD context
+ * @data: chip power save failure detected data
+ *
+ * This function reads the chip power save failure detected data and fill in
+ * the skb with NL attributes and send up the NL event.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
+ *
+ * Return: none
+ */
+
+void hdd_chip_pwr_save_fail_detected_cb(void *hddctx,
+ struct chip_pwr_save_fail_detected_params
+ *data);
+
#endif /* end #if !defined(WLAN_HDD_MAIN_H) */
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index 36fc46c57dfa..58b90a30af17 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -4427,6 +4427,14 @@ struct reg_table_entry g_registry_table[] = {
CFG_TX_ORPHAN_ENABLE_DEFAULT,
CFG_TX_ORPHAN_ENABLE_MIN,
CFG_TX_ORPHAN_ENABLE_MAX),
+
+ REG_VARIABLE(CFG_AUTO_DETECT_POWER_FAIL_MODE_NAME, WLAN_PARAM_Integer,
+ struct hdd_config, auto_pwr_save_fail_mode,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_AUTO_DETECT_POWER_FAIL_MODE_DEFAULT,
+ CFG_AUTO_DETECT_POWER_FAIL_MODE_MIN,
+ CFG_AUTO_DETECT_POWER_FAIL_MODE_MAX),
+
};
@@ -5928,6 +5936,10 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
hdd_info("Name = [%s] Value = [%d]",
CFG_SAP_INTERNAL_RESTART_NAME,
pHddCtx->config->sap_internal_restart);
+ hdd_debug("Name = [%s] Value = [%u]",
+ CFG_AUTO_DETECT_POWER_FAIL_MODE_NAME,
+ pHddCtx->config->auto_pwr_save_fail_mode);
+
hdd_per_roam_print_ini_config(pHddCtx);
hdd_he_print_ini_config(pHddCtx);
hdd_info("Name = [%s] Value = [%d]",
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 0c55b0e3c997..2ebc47619595 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -1275,6 +1275,11 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
.vendor_id = QCA_NL80211_VENDOR_ID,
.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
},
+ [QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
+ .vendor_id = QCA_NL80211_VENDOR_ID,
+ .subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
+ }
+
#ifdef WLAN_UMAC_CONVERGENCE
COMMON_VENDOR_EVENTS
#endif
@@ -3421,6 +3426,67 @@ wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
return ret;
}
+#define PWR_SAVE_FAIL_CMD_INDEX \
+ QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
+/**
+ * hdd_chip_pwr_save_fail_detected_cb() - chip power save failure detected
+ * callback
+ * @hddctx: HDD context
+ * @data: chip power save failure detected data
+ *
+ * This function reads the chip power save failure detected data and fill in
+ * the skb with NL attributes and send up the NL event.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
+ *
+ * Return: none
+ */
+void hdd_chip_pwr_save_fail_detected_cb(void *hddctx,
+ struct chip_pwr_save_fail_detected_params
+ *data)
+{
+ hdd_context_t *hdd_ctx = hddctx;
+ struct sk_buff *skb;
+ int flags = cds_get_gfp_flags();
+
+ ENTER();
+
+ if (wlan_hdd_validate_context(hdd_ctx))
+ return;
+
+ if (!data) {
+ hdd_notice("data is null");
+ return;
+ }
+
+ skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
+ NULL, NLMSG_HDRLEN +
+ sizeof(data->failure_reason_code) +
+ NLMSG_HDRLEN, PWR_SAVE_FAIL_CMD_INDEX,
+ flags);
+
+ if (!skb) {
+ hdd_notice("cfg80211_vendor_event_alloc failed");
+ return;
+ }
+
+ hdd_debug(FL("failure reason code: %u"),
+ data->failure_reason_code);
+
+ if (nla_put_u32(skb,
+ QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
+ data->failure_reason_code))
+ goto fail;
+
+ cfg80211_vendor_event(skb, flags);
+ EXIT();
+ return;
+
+fail:
+ kfree_skb(skb);
+}
+#undef PWR_SAVE_FAIL_CMD_INDEX
+
static const struct nla_policy
wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
+1] = {
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 1e2bca3435ac..cd59da5ed5d5 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -8013,6 +8013,8 @@ static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
cds_cfg->active_uc_bpf_mode = hdd_ctx->config->active_uc_bpf_mode;
cds_cfg->active_mc_bc_bpf_mode = hdd_ctx->config->active_mc_bc_bpf_mode;
+ cds_cfg->auto_power_save_fail_mode =
+ hdd_ctx->config->auto_pwr_save_fail_mode;
hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
@@ -9471,6 +9473,9 @@ int hdd_wlan_startup(struct device *dev)
if (hdd_ctx->config->is_force_1x1)
wma_cli_set_command(0, (int)WMI_PDEV_PARAM_SET_IOT_PATTERN,
1, PDEV_CMD);
+ /* set chip power save failure detected callback */
+ sme_set_chip_pwr_save_fail_cb(hdd_ctx->hHal,
+ hdd_chip_pwr_save_fail_detected_cb);
if (hdd_ctx->config->max_mpdus_inampdu) {
set_value = hdd_ctx->config->max_mpdus_inampdu;
@@ -11388,6 +11393,8 @@ static int hdd_update_pmo_config(hdd_context_t *hdd_ctx)
psoc_cfg.sta_max_li_mod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
psoc_cfg.power_save_mode =
hdd_ctx->config->enablePowersaveOffload;
+ psoc_cfg.auto_power_save_fail_mode =
+ hdd_ctx->config->auto_pwr_save_fail_mode;
hdd_ra_populate_pmo_config(&psoc_cfg, hdd_ctx);
hdd_nan_populate_pmo_config(&psoc_cfg, hdd_ctx);
diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c
index 76a0eda44316..6a635d88a1bb 100644
--- a/core/hdd/src/wlan_hdd_power.c
+++ b/core/hdd/src/wlan_hdd_power.c
@@ -1480,6 +1480,9 @@ QDF_STATUS hdd_wlan_re_init(void)
/* Allow the phone to go to sleep */
hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
+ /* set chip power save failure detected callback */
+ sme_set_chip_pwr_save_fail_cb(pHddCtx->hHal,
+ hdd_chip_pwr_save_fail_detected_cb);
ret = hdd_register_cb(pHddCtx);
if (ret) {
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index c7f58808591a..bb52482fba78 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -5676,6 +5676,17 @@ struct rssi_breach_event {
struct qdf_mac_addr curr_bssid;
};
+/**
+ * struct chip_pwr_save_fail_detected_params - chip power save failure detected
+ * event params
+ * @failure_reason_code:failure reason code
+ * @wake_lock_bitmap:bitmap for modules voting against sleep for long duration.
+ */
+struct chip_pwr_save_fail_detected_params {
+ uint32_t failure_reason_code;
+ uint32_t wake_lock_bitmap[4];
+};
+
#define MAX_NUM_FW_SEGMENTS 4
/**
@@ -6356,6 +6367,7 @@ struct sir_bpf_get_offload {
* @wow_pno_complete_wake_up_count: pno complete wakeup count
* @wow_pno_match_wake_up_count: pno match wakeup count
* @wow_oem_response_wake_up_count: oem response wakeup count
+ * @pwr_save_fail_detected: pwr save fail detected wakeup count
*/
struct sir_wake_lock_stats {
uint32_t wow_unspecified_wake_up_count;
@@ -6374,6 +6386,7 @@ struct sir_wake_lock_stats {
uint32_t wow_pno_complete_wake_up_count;
uint32_t wow_pno_match_wake_up_count;
uint32_t wow_oem_response_wake_up_count;
+ uint32_t pwr_save_fail_detected;
};
/**
@@ -6410,6 +6423,7 @@ struct sir_vdev_wow_stats {
uint32_t pno_complete;
uint32_t pno_match;
uint32_t oem_response;
+ uint32_t pwr_save_fail_detected;
};
/**
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index f0d69fc3a1b9..11b257ccc49e 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -1555,4 +1555,17 @@ QDF_STATUS sme_set_reorder_timeout(tHalHandle hal,
QDF_STATUS sme_set_rx_set_blocksize(tHalHandle hal,
struct sir_peer_set_rx_blocksize *req);
+/*
+ * sme_set_chip_pwr_save_fail_cb() - set chip power save failure callback
+ * @hal: global hal handle
+ * @cb: callback function pointer
+ *
+ * This function stores the chip power save failure callback function.
+ *
+ * Return: QDF_STATUS enumeration.
+ */
+
+QDF_STATUS sme_set_chip_pwr_save_fail_cb(tHalHandle hal, void (*cb)(void *,
+ struct chip_pwr_save_fail_detected_params *));
+
#endif /* #if !defined( __SME_API_H ) */
diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h
index adad9ec18584..7a13c60f1734 100644
--- a/core/sme/inc/sme_internal.h
+++ b/core/sme/inc/sme_internal.h
@@ -242,6 +242,7 @@ typedef struct tagSmeStruct {
void *encrypt_decrypt_context;
void (*lost_link_info_cb)(void *context,
struct sir_lost_link_info *lost_link_info);
+
bool (*set_connection_info_cb)(bool);
bool (*get_connection_info_cb)(uint8_t *session_id,
enum scan_reject_states *reason);
@@ -249,6 +250,8 @@ typedef struct tagSmeStruct {
struct rso_cmd_status *rso_status);
void (*congestion_cb)(void *, uint32_t congestion, uint32_t vdev_id);
void (*stats_ext2_cb)(void *, struct sir_sme_rx_aggr_hole_ind *);
+ void (*chip_power_save_fail_cb)(void *,
+ struct chip_pwr_save_fail_detected_params *);
} tSmeStruct, *tpSmeStruct;
#endif /* #if !defined( __SMEINTERNAL_H ) */
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 60dcbed2ec30..4210a4a3bd35 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -14161,6 +14161,23 @@ bool sme_is_any_session_in_connected_state(tHalHandle h_hal)
return ret;
}
+QDF_STATUS sme_set_chip_pwr_save_fail_cb(tHalHandle hal,
+ void (*cb)(void *,
+ struct chip_pwr_save_fail_detected_params *)) {
+
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+ tpAniSirGlobal mac = PMAC_STRUCT(hal);
+
+ status = sme_acquire_global_lock(&mac->sme);
+ if (status != QDF_STATUS_SUCCESS) {
+ sme_err("sme_AcquireGlobalLock failed!(status=%d)", status);
+ return status;
+ }
+ mac->sme.chip_power_save_fail_cb = cb;
+ sme_release_global_lock(&mac->sme);
+ return status;
+}
+
/**
* sme_set_rssi_monitoring() - set rssi monitoring
* @hal: global hal handle
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h
index 486693daa529..bf9290b14500 100644
--- a/core/wma/inc/wma.h
+++ b/core/wma/inc/wma.h
@@ -1015,6 +1015,7 @@ typedef struct {
* @ns_offload_req: cached ns offload request
* @wow_stats: stat counters for WoW related events
* It stores parameters per vdev in wma.
+ * @in_bmps : Whether bmps for this interface has been enabled
*/
struct wma_txrx_node {
uint8_t addr[IEEE80211_ADDR_LEN];
@@ -1092,6 +1093,7 @@ struct wma_txrx_node {
bool he_capable;
uint32_t he_ops;
#endif
+ bool in_bmps;
};
#if defined(QCA_WIFI_FTM)
@@ -1519,6 +1521,7 @@ typedef struct {
struct he_capability he_cap;
#endif
bool tx_bfee_8ss_enabled;
+ bool in_imps;
} t_wma_handle, *tp_wma_handle;
/**
@@ -2348,6 +2351,32 @@ uint16_t wma_vdev_get_pause_bitmap(uint8_t vdev_id)
return iface->pause_bitmap;
}
+/**
+ * wma_vdev_is_device_in_low_pwr_mode - is device in power save mode
+ * @vdev_id: the Id of the vdev to configure
+ *
+ * Return: true if device is in low power mode else false
+ */
+static inline bool wma_vdev_is_device_in_low_pwr_mode(uint8_t vdev_id)
+{
+ tp_wma_handle wma = (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
+ struct wma_txrx_node *iface;
+
+ if (!wma) {
+ WMA_LOGE("%s: WMA context is invald!", __func__);
+ return 0;
+ }
+
+ iface = &wma->interfaces[vdev_id];
+ if (!iface || !iface->handle) {
+ WMA_LOGE("%s: Failed to get iface handle: %p",
+ __func__, iface->handle);
+ return 0;
+ }
+
+ return iface->in_bmps || wma->in_imps;
+}
+
/**
* wma_vdev_set_pause_bit() - Set a bit in vdev pause bitmap
* @vdev_id: the Id of the vdev to configure
@@ -2521,4 +2550,16 @@ QDF_STATUS wma_set_rx_reorder_timeout_val(tp_wma_handle wma_handle,
QDF_STATUS wma_set_rx_blocksize(tp_wma_handle wma_handle,
struct sir_peer_set_rx_blocksize *peer_rx_blocksize);
+/*
+ * wma_chip_power_save_failure_detected_handler() - chip pwr save fail detected
+ * event handler
+ * @handle: wma handle
+ * @cmd_param_info: event handler data
+ * @len: length of @cmd_param_info
+ *
+ * Return: QDF_STATUS_SUCCESS on success; error code otherwise
+ */
+int wma_chip_power_save_failure_detected_handler(void *handle,
+ uint8_t *cmd_param_info,
+ uint32_t len);
#endif
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index a5f34cd9a9f3..053466557565 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -1461,6 +1461,8 @@ static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
return "NAN_EVENT_WAKE_HOST";
case WOW_REASON_DEBUG_TEST:
return "DEBUG_TEST";
+ case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
+ return "CHIP_POWER_FAILURE_DETECT";
default:
return "unknown";
}
@@ -1507,6 +1509,7 @@ static void wma_print_wow_stats(t_wma_handle *wma,
case WOW_REASON_EXTSCAN:
case WOW_REASON_RSSI_BREACH_EVENT:
case WOW_REASON_OEM_RESPONSE_EVENT:
+ case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
break;
default:
return;
@@ -1558,6 +1561,9 @@ static void wma_inc_wow_stats(t_wma_handle *wma,
case WOW_REASON_OEM_RESPONSE_EVENT:
stats->oem_response++;
break;
+ case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
+ stats->pwr_save_fail_detected++;
+ break;
}
}
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index ebd187ad7618..301058f9452d 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -2555,6 +2555,14 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, void *cds_context,
wma_rx_aggr_failure_event_handler,
WMA_RX_SERIALIZER_CTX);
+ /* Register PWR_SAVE_FAIL event only in case of recovery(1) */
+ if (cds_cfg->auto_power_save_fail_mode) {
+ wmi_unified_register_event_handler(wma_handle->wmi_handle,
+ WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID,
+ wma_chip_power_save_failure_detected_handler,
+ WMA_RX_WORK_CTX);
+ }
+
wma_ndp_register_all_event_handlers(wma_handle);
wma_register_debug_callback();
@@ -2563,6 +2571,8 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, void *cds_context,
wma_vdev_update_pause_bitmap);
pmo_register_get_pause_bitmap(wma_handle->psoc,
wma_vdev_get_pause_bitmap);
+ pmo_register_is_device_in_low_pwr_mode(wma_handle->psoc,
+ wma_vdev_is_device_in_low_pwr_mode);
wma_cbacks.wma_get_connection_info = wma_get_connection_info;
wma_cbacks.wma_is_service_enabled = wma_is_service_enabled;
qdf_status = policy_mgr_register_wma_cb(wma_handle->psoc, &wma_cbacks);
@@ -3612,16 +3622,17 @@ QDF_STATUS wma_close(void *cds_ctx)
wlan_psoc_set_tgt_if_handle(wma_handle->psoc, NULL);
}
- wlan_objmgr_psoc_release_ref(wma_handle->psoc, WLAN_LEGACY_WMA_ID);
- wma_handle->psoc = NULL;
- target_if_close();
- wma_target_if_close(wma_handle);
-
pmo_unregister_pause_bitmap_notifier(wma_handle->psoc,
wma_vdev_update_pause_bitmap);
pmo_unregister_get_pause_bitmap(wma_handle->psoc,
wma_vdev_get_pause_bitmap);
+ pmo_unregister_is_device_in_low_pwr_mode(wma_handle->psoc,
+ wma_vdev_is_device_in_low_pwr_mode);
+ wlan_objmgr_psoc_release_ref(wma_handle->psoc, WLAN_LEGACY_WMA_ID);
+ wma_handle->psoc = NULL;
+ target_if_close();
+ wma_target_if_close(wma_handle);
WMA_LOGD("%s: Exit", __func__);
return QDF_STATUS_SUCCESS;
diff --git a/core/wma/src/wma_power.c b/core/wma/src/wma_power.c
index 0f7cc71410a0..efd7e5b7073d 100644
--- a/core/wma/src/wma_power.c
+++ b/core/wma/src/wma_power.c
@@ -821,6 +821,8 @@ void wma_enable_sta_ps_mode(tp_wma_handle wma, tpEnablePsParams ps_req)
return;
}
}
+ /* power save request succeeded */
+ iface->in_bmps = true;
}
/**
@@ -834,6 +836,7 @@ void wma_disable_sta_ps_mode(tp_wma_handle wma, tpDisablePsParams ps_req)
{
QDF_STATUS ret;
uint32_t vdev_id = ps_req->sessionid;
+ struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
WMA_LOGD("Disable Sta Mode Ps vdevId %d", vdev_id);
@@ -843,6 +846,7 @@ void wma_disable_sta_ps_mode(tp_wma_handle wma, tpDisablePsParams ps_req)
WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
return;
}
+ iface->in_bmps = false;
/* Disable UAPSD incase if additional Req came */
if (eSIR_ADDON_DISABLE_UAPSD == ps_req->psSetting) {
@@ -1710,6 +1714,7 @@ QDF_STATUS wma_set_idle_ps_config(void *wma_ptr, uint32_t idle_ps)
WMA_LOGE("Fail to Set Idle Ps Config %d", idle_ps);
return QDF_STATUS_E_FAILURE;
}
+ wma->in_imps = !!idle_ps;
WMA_LOGD("Successfully Set Idle Ps Config %d", idle_ps);
return QDF_STATUS_SUCCESS;
diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c
index 1827c35a542a..ab2743a83963 100644
--- a/core/wma/src/wma_utils.c
+++ b/core/wma/src/wma_utils.c
@@ -4031,3 +4031,52 @@ tSirWifiPeerType wmi_to_sir_peer_type(enum wmi_peer_type type)
return WIFI_PEER_INVALID;
}
}
+
+int wma_chip_power_save_failure_detected_handler(void *handle,
+ uint8_t *cmd_param_info,
+ uint32_t len)
+{
+ tp_wma_handle wma = (tp_wma_handle)handle;
+ WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *param_buf;
+ wmi_chip_power_save_failure_detected_fixed_param *event;
+ struct chip_pwr_save_fail_detected_params pwr_save_fail_params;
+ tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(
+ QDF_MODULE_ID_PE);
+ if (wma == NULL) {
+ WMA_LOGE("%s: wma_handle is NULL", __func__);
+ return -EINVAL;
+ }
+ if (!mac) {
+ WMA_LOGE("%s: Invalid mac context", __func__);
+ return -EINVAL;
+ }
+ if (!mac->sme.chip_power_save_fail_cb) {
+ WMA_LOGE("%s: Callback not registered", __func__);
+ return -EINVAL;
+ }
+
+ param_buf =
+ (WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *)
+ cmd_param_info;
+ if (!param_buf) {
+ WMA_LOGE("%s: Invalid pwr_save_fail_params breached event",
+ __func__);
+ return -EINVAL;
+ }
+ event = param_buf->fixed_param;
+ pwr_save_fail_params.failure_reason_code =
+ event->power_save_failure_reason_code;
+ pwr_save_fail_params.wake_lock_bitmap[0] =
+ event->protocol_wake_lock_bitmap[0];
+ pwr_save_fail_params.wake_lock_bitmap[1] =
+ event->protocol_wake_lock_bitmap[1];
+ pwr_save_fail_params.wake_lock_bitmap[2] =
+ event->protocol_wake_lock_bitmap[2];
+ pwr_save_fail_params.wake_lock_bitmap[3] =
+ event->protocol_wake_lock_bitmap[3];
+ mac->sme.chip_power_save_fail_cb(mac->hHdd,
+ &pwr_save_fail_params);
+
+ WMA_LOGD("%s: Invoke HDD pwr_save_fail callback", __func__);
+ return 0;
+}