From 970aed1bcf7eb2531edaf4e5bab2c61e4ade89d1 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Mon, 29 Nov 2021 15:13:15 +0530 Subject: [PATCH] qcacld-3.0: Allow suspend in deep sleep or Hibernate Deep Sleep or Hibernate are system level mode power modes in which wlan firmware is shutdown gracefully and linux kernel is suspended. Currently, suspend is not allowed if firmware is down, with this change suspend is allowed if firmware is down due to Deep Sleep or Hibernate low power state. A new pld api is introduced to know the low power state from platform driver, this api is enabled based on CONFIG_ENABLE_LOW_POWER_MODE flag. Currently, this feature is enabled only for wearable targets. Change-Id: Iddaa4da8ee4880a4223420f59cbe9c365c30344a CRs-Fixed: 3090481 --- configs/wear_defconfig | 3 +++ core/hdd/src/wlan_hdd_power.c | 8 ++++++-- core/pld/inc/pld_common.h | 9 +++++++++ core/pld/src/pld_common.c | 32 ++++++++++++++++++++++++++++++++ core/pld/src/pld_snoc.h | 19 +++++++++++++++++++ 5 files changed, 69 insertions(+), 2 deletions(-) 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)