diff --git a/configs/wear_defconfig b/configs/wear_defconfig index a8c74d2baf3a..b1e358799937 100644 --- a/configs/wear_defconfig +++ b/configs/wear_defconfig @@ -1232,3 +1232,6 @@ ifeq ($(CONFIG_FW_THERMAL_THROTTLE), y) CONFIG_WLAN_THERMAL_MULTI_CLIENT_SUPPORT := y endif endif + +#Enable Low Power Modes: Deep Sleep/Hibernate +CONFIG_ENABLE_LOW_POWER_MODE := y diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 9ebf39b513c2..4c63bfabf304 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -2239,8 +2239,12 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, } rc = wlan_hdd_validate_context(hdd_ctx); - if (0 != rc) - return rc; + if (0 != rc) { + if (pld_is_low_power_mode(hdd_ctx->parent_dev)) + hdd_debug("low power mode (Deep Sleep/Hibernate)"); + else + return rc; + } if (hdd_ctx->config->is_wow_disabled) { hdd_info_rl("wow is disabled"); diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h index dc31bc275306..04be7b202da4 100644 --- a/core/pld/inc/pld_common.h +++ b/core/pld/inc/pld_common.h @@ -756,6 +756,15 @@ int pld_qmi_send(struct device *dev, int type, void *cmd, int (*cb)(void *ctx, void *event, int event_len)); bool pld_is_fw_dump_skipped(struct device *dev); +#ifdef CONFIG_ENABLE_LOW_POWER_MODE +int pld_is_low_power_mode(struct device *dev); +#else +static inline int pld_is_low_power_mode(struct device *dev) +{ + return 0; +} +#endif + /** * pld_is_pdr() - Check WLAN PD is Restarted * diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c index 1257b701d152..13e161862b0f 100644 --- a/core/pld/src/pld_common.c +++ b/core/pld/src/pld_common.c @@ -2727,6 +2727,38 @@ int pld_is_fw_down(struct device *dev) return ret; } +#ifdef CONFIG_ENABLE_LOW_POWER_MODE +/** + * pld_is_low_power_mode() - Check WLAN fw is in low power + * @dev: device + * + * This API will be called to check if WLAN FW is in low power or not. + * Low power means either Deep Sleep or Hibernate state. + * + * Return: 0 FW is not in low power mode + * Otherwise FW is low power mode + * Always return 0 for unsupported bus type + */ +int pld_is_low_power_mode(struct device *dev) +{ + int ret = 0; + enum pld_bus_type type = pld_get_bus_type(dev); + + switch (type) { + case PLD_BUS_TYPE_SNOC: + ret = pld_snoc_is_low_power_mode(dev); + break; + case PLD_BUS_TYPE_PCIE_FW_SIM: + case PLD_BUS_TYPE_IPCI_FW_SIM: + case PLD_BUS_TYPE_SNOC_FW_SIM: + case PLD_BUS_TYPE_IPCI: + default: + break; + } + return ret; +} +#endif + /** * pld_force_assert_target() - Send a force assert request to FW. * @dev: device pointer diff --git a/core/pld/src/pld_snoc.h b/core/pld/src/pld_snoc.h index 270ac1477a24..969504dd2e6c 100644 --- a/core/pld/src/pld_snoc.h +++ b/core/pld/src/pld_snoc.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -149,6 +150,12 @@ static inline int pld_snoc_is_fw_down(struct device *dev) { return 0; } + +static inline int pld_snoc_is_low_power_mode(struct device *dev) +{ + return 0; +} + static inline int pld_snoc_set_fw_log_mode(struct device *dev, u8 fw_log_mode) { return 0; @@ -329,6 +336,18 @@ static inline int pld_snoc_is_fw_down(struct device *dev) return icnss_is_fw_down(); } +#ifdef CONFIG_ENABLE_LOW_POWER_MODE +static inline int pld_snoc_is_low_power_mode(struct device *dev) +{ + return icnss_is_low_power(); +} +#else +static inline int pld_snoc_is_low_power_mode(struct device *dev) +{ + return 0; +} +#endif + static inline int pld_snoc_is_qmi_disable(struct device *dev) { if (!dev)