diff --git a/os_if/linux/qca_vendor.h b/os_if/linux/qca_vendor.h index d18ba23e29..9bb0174a1c 100644 --- a/os_if/linux/qca_vendor.h +++ b/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 diff --git a/pmo/core/inc/wlan_pmo_static_config.h b/pmo/core/inc/wlan_pmo_static_config.h index a504578bdb..fe4544b79c 100644 --- a/pmo/core/inc/wlan_pmo_static_config.h +++ b/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_ */ diff --git a/pmo/core/inc/wlan_pmo_wow.h b/pmo/core/inc/wlan_pmo_wow.h index ffd6805f15..47d2eb53a6 100644 --- a/pmo/core/inc/wlan_pmo_wow.h +++ b/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_ */ diff --git a/pmo/core/src/wlan_pmo_static_config.c b/pmo/core/src/wlan_pmo_static_config.c index 05e0fb98fb..90d3edd714 100644 --- a/pmo/core/src/wlan_pmo_static_config.c +++ b/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: diff --git a/pmo/core/src/wlan_pmo_suspend_resume.c b/pmo/core/src/wlan_pmo_suspend_resume.c index 550a8cb465..ec72100da6 100644 --- a/pmo/core/src/wlan_pmo_suspend_resume.c +++ b/pmo/core/src/wlan_pmo_suspend_resume.c @@ -32,7 +32,8 @@ #include "htc_api.h" #include "wlan_pmo_obj_mgmt_api.h" #include - +#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); diff --git a/pmo/core/src/wlan_pmo_wow.c b/pmo/core/src/wlan_pmo_wow.c index 44448bf4ae..95f649a482 100644 --- a/pmo/core/src/wlan_pmo_wow.c +++ b/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 - +#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); +} diff --git a/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h b/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h index f2def680df..f1dd85c641 100644 --- a/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h +++ b/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_ */ diff --git a/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h b/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h index a3ffd904da..42ee0b95dd 100644 --- a/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h +++ b/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_ */ diff --git a/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h b/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h index c09ecd626b..e28ffec21f 100644 --- a/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h +++ b/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; }; diff --git a/pmo/dispatcher/inc/wlan_pmo_tgt_api.h b/pmo/dispatcher/inc/wlan_pmo_tgt_api.h index 3b37265a55..5ed17b2d95 100644 --- a/pmo/dispatcher/inc/wlan_pmo_tgt_api.h +++ b/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. diff --git a/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h b/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h index 7217d8305a..8b92ff3a4d 100644 --- a/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h +++ b/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 diff --git a/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c b/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c index 7493d5233d..59404e60ad 100644 --- a/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c +++ b/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; } diff --git a/pmo/dispatcher/src/wlan_pmo_tgt_wow.c b/pmo/dispatcher/src/wlan_pmo_tgt_wow.c index eb826f1e09..68cd447e58 100644 --- a/pmo/dispatcher/src/wlan_pmo_tgt_wow.c +++ b/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; diff --git a/pmo/dispatcher/src/wlan_pmo_ucfg_api.c b/pmo/dispatcher/src/wlan_pmo_ucfg_api.c index 24470e7697..f583399617 100644 --- a/pmo/dispatcher/src/wlan_pmo_ucfg_api.c +++ b/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) diff --git a/target_if/pmo/inc/target_if_pmo.h b/target_if/pmo/inc/target_if_pmo.h index b2dd5441b4..dc6f73187a 100644 --- a/target_if/pmo/inc/target_if_pmo.h +++ b/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. diff --git a/target_if/pmo/src/target_if_pmo_wow.c b/target_if/pmo/src/target_if_pmo_wow.c index 00c7e3e1ca..828f0cf26e 100644 --- a/target_if/pmo/src/target_if_pmo_wow.c +++ b/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; diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index 0c66fb5e27..c1101edc6e 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/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, diff --git a/wmi/inc/wmi_unified_pmo_api.h b/wmi/inc/wmi_unified_pmo_api.h index 350d4212b4..bf80b092dd 100644 --- a/wmi/inc/wmi_unified_pmo_api.h +++ b/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); /** diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 09f0db08ff..b35c2a6ed7 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/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, diff --git a/wmi/src/wmi_unified_pmo_api.c b/wmi/src/wmi_unified_pmo_api.c index 743aa6fcde..99e872cac1 100644 --- a/wmi/src/wmi_unified_pmo_api.c +++ b/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; diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 0e4a9b8ee0..37330c066f 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/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; }