From 466cb5b6195ad715df3d7cec4a732faa37a1b575 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 10 Nov 2015 16:49:12 -0800 Subject: [PATCH] qcacld-3.0: Coordinate runtime suspend from hdd HDD interfaces with the platform driver. Runtime suspend is a callback registered with the platform driver. Coordinate runtime suspend from hdd since it is both the logical entry point and knows what other layers need to participate in a runtime suspend. Change-Id: I80b71e504d0cd31bd5a8e47895db7e0bd233f6c3 CRs-Fixed: 935300 --- core/hdd/src/wlan_hdd_driver_ops.c | 153 +++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 39cd2111e8..dc9d1ea26a 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -43,6 +43,7 @@ #include "cds_sched.h" #include "osdep.h" #include "hif.h" +#include "htc.h" #include "epping_main.h" #include "wlan_hdd_main.h" #include "wlan_hdd_power.h" @@ -524,6 +525,120 @@ static int wlan_hdd_bus_resume(void) return ret; } +#ifdef FEATURE_RUNTIME_PM + +/** + * __wlan_hdd_runtime_suspend() - suspend the wlan bus without apps suspend + * + * Each layer is responsible for its own suspend actions. wma_runtime_suspend + * takes care of the parts of the 802.11 suspend that we want to do for runtime + * suspend. + * + * Return: 0 or errno + */ +static int __wlan_hdd_runtime_suspend(void) +{ + void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + int status = wlan_hdd_validate_context(hdd_ctx); + + if (0 != status) + return status; + + if (!hif_can_suspend_link()) { + hdd_err("Runtime PM not supported for link up suspend"); + return -EINVAL; + } + + hif_runtime_pm_set_state_inprogress(); + status = htc_runtime_suspend(); + if (status) + goto set_state; + + status = wma_runtime_suspend(); + if (status) + goto resume_htc; + + status = hif_runtime_suspend(); + if (status) + goto resume_wma; + + status = cnss_auto_suspend(); + if (status) + goto resume_hif; + + hif_runtime_pm_set_state_suspended(); + return status; + +resume_hif: + CDF_BUG(!hif_runtime_resume()); +resume_wma: + CDF_BUG(!wma_runtime_resume()); +resume_htc: + CDF_BUG(!htc_runtime_resume()); +set_state: + hif_runtime_pm_set_state_on(); + return status; +} + + +/** + * wlan_hdd_runtime_suspend() - suspend the wlan bus without apps suspend + * + * This function is called by the platform driver to suspend the + * wlan bus separately from system suspend + * + * Return: 0 or errno + */ +static int wlan_hdd_runtime_suspend(void) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_runtime_suspend(); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_runtime_resume() - resume the wlan bus from runtime suspend + * + * Sets the runtime pm state and coordinates resume between hif wma and + * ol_txrx. + * + * Return: success since failure is a bug + */ +static int __wlan_hdd_runtime_resume(void) +{ + hif_runtime_pm_set_state_inprogress(); + CDF_BUG(!cnss_auto_resume()); + CDF_BUG(!hif_runtime_resume()); + CDF_BUG(!wma_runtime_resume()); + CDF_BUG(!htc_runtime_resume()); + hif_runtime_pm_set_state_on(); + return 0; +} + +/** + * wlan_hdd_runtime_resume() - resume the wlan bus from runtime suspend + * + * This function is called by the platform driver to resume the + * wlan bus separately from system suspend + * + * Return: success since failure is a bug + */ +static int wlan_hdd_runtime_resume(void) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_runtime_resume(); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + #ifdef HIF_PCI /** * wlan_hdd_pci_probe() - probe callback for pci platform driver @@ -618,6 +733,32 @@ static int wlan_hdd_pci_resume(struct pci_dev *pdev) { return wlan_hdd_bus_resume(); } + +#ifdef FEATURE_RUNTIME_PM +/** + * wlan_hdd_pci_runtime_suspend() - wlan_hdd_pci_suspend + * @pdev: pdev + * @state: state + * + * Return: success or errno + */ +static int wlan_hdd_pci_runtime_suspend(struct pci_dev *pdev) +{ + return wlan_hdd_runtime_suspend(); +} + +/** + * wlan_hdd_pci_runtime_resume() - runtime resume callback to register with pci + * @pdev: pci device id + * + * Return: success or errno + */ +static int wlan_hdd_pci_runtime_resume(struct pci_dev *pdev) +{ + return wlan_hdd_runtime_resume(); +} +#endif + #else /** * wlan_hdd_snoc_probe() - wlan_hdd_snoc_probe @@ -709,6 +850,14 @@ static struct pci_device_id wlan_hdd_pci_id_table[] = { }; #ifdef CONFIG_CNSS + +#ifdef FEATURE_RUNTIME_PM +struct cnss_wlan_runtime_ops runtime_pm_ops = { + .runtime_suspend = wlan_hdd_pci_runtime_suspend, + .runtime_resume = wlan_hdd_pci_runtime_resume, +}; +#endif + struct cnss_wlan_driver wlan_drv_ops = { .name = "wlan_hdd_pci", .id_table = wlan_hdd_pci_id_table, @@ -722,6 +871,9 @@ struct cnss_wlan_driver wlan_drv_ops = { .suspend = wlan_hdd_pci_suspend, .resume = wlan_hdd_pci_resume, #endif /* ATH_BUS_PM */ +#ifdef FEATURE_RUNTIME_PM + .runtime_ops = &runtime_pm_ops, +#endif }; #else MODULE_DEVICE_TABLE(pci, wlan_hdd_pci_id_table); @@ -734,6 +886,7 @@ struct pci_driver wlan_drv_ops = { .suspend = wlan_hdd_pci_suspend, .resume = wlan_hdd_pci_resume, #endif /* ATH_BUS_PM */ + }; #endif /* CONFIG_CNSS */ #else