diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h index a725c2a4b3e9..97e91520dc0e 100644 --- a/core/hdd/inc/wlan_hdd_power.h +++ b/core/hdd/inc/wlan_hdd_power.h @@ -325,6 +325,7 @@ void wlan_hdd_inc_suspend_stats(hdd_context_t *hdd_ctx, /** * wlan_hdd_unit_test_bus_suspend() - suspend the wlan bus * @state: state containing the suspend source event + * @wow_params: collection of wow enable override parameters * * This function does the same as wlan_hdd_bus_suspend, but additionally passes * the appropriate flags to FW, indicating this is a unit-test suspend and it @@ -332,7 +333,8 @@ void wlan_hdd_inc_suspend_stats(hdd_context_t *hdd_ctx, * * Return: 0 for success or error code */ -int wlan_hdd_unit_test_bus_suspend(pm_message_t state); +int wlan_hdd_unit_test_bus_suspend(pm_message_t state, + struct wow_enable_params wow_params); /** * hdd_wlan_fake_apps_resume() - Resume from unit-test triggered suspend @@ -347,10 +349,14 @@ int hdd_wlan_fake_apps_resume(struct wiphy *wiphy, struct net_device *dev); * hdd_wlan_fake_apps_suspend() - Initiate a unit-test triggered suspend * @wiphy: the kernel wiphy struct for the device being suspended * @dev: the kernel net_device struct for the device being suspended + * @pause_setting: interface pause override setting + * @resume_setting: resume trigger override setting * * Return: Zero on success, suspend related non-zero error code on failure */ -int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev); +int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev, + enum wow_interface_pause pause_setting, + enum wow_resume_trigger resume_setting); #else static inline int hdd_wlan_fake_apps_resume(struct wiphy *wiphy, struct net_device *dev) @@ -359,7 +365,9 @@ hdd_wlan_fake_apps_resume(struct wiphy *wiphy, struct net_device *dev) } static inline int -hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev) +hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev, + enum wow_interface_pause pause_setting, + enum wow_resume_trigger resume_setting) { return 0; } diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 77ce5f05cd0d..4f670a2f083e 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -504,7 +504,7 @@ static void wlan_hdd_update_status(uint32_t status) /** * __wlan_hdd_bus_suspend() - handles platform supsend * @state: suspend message from the kernel - * @wow_flags: bitmap of WMI WOW flags to pass to FW + * @wow_params: collection of wow enable override parameters * * Does precondtion validation. Ensures that a subsystem restart isn't in * progress. Ensures that no load or unload is in progress. @@ -516,7 +516,8 @@ static void wlan_hdd_update_status(uint32_t status) * -EBUSY or -EAGAIN if another opperation is in progress and * wlan will not be ready to suspend in time. */ -static int __wlan_hdd_bus_suspend(pm_message_t state, uint32_t wow_flags) +static int __wlan_hdd_bus_suspend(pm_message_t state, + struct wow_enable_params wow_params) { hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); void *hif_ctx; @@ -524,8 +525,7 @@ static int __wlan_hdd_bus_suspend(pm_message_t state, uint32_t wow_flags) int status; void *soc = cds_get_context(QDF_MODULE_ID_SOC); - hdd_info("starting bus suspend; event:%d, flags:%u", - state.event, wow_flags); + hdd_info("starting bus suspend; event:%d", state.event); err = wlan_hdd_validate_context(hdd_ctx); if (err) { @@ -551,7 +551,7 @@ static int __wlan_hdd_bus_suspend(pm_message_t state, uint32_t wow_flags) goto done; } - err = wma_bus_suspend(wow_flags); + err = wma_bus_suspend(wow_params); if (err) { hdd_err("Failed wma bus suspend"); goto resume_oltxrx; @@ -580,22 +580,23 @@ done: int wlan_hdd_bus_suspend(pm_message_t state) { int ret; + struct wow_enable_params default_params = {0}; cds_ssr_protect(__func__); - ret = __wlan_hdd_bus_suspend(state, 0); + ret = __wlan_hdd_bus_suspend(state, default_params); cds_ssr_unprotect(__func__); return ret; } #ifdef WLAN_SUSPEND_RESUME_TEST -int wlan_hdd_unit_test_bus_suspend(pm_message_t state) +int wlan_hdd_unit_test_bus_suspend(pm_message_t state, + struct wow_enable_params wow_params) { int ret; cds_ssr_protect(__func__); - ret = __wlan_hdd_bus_suspend(state, WMI_WOW_FLAG_UNIT_TEST_ENABLE | - WMI_WOW_FLAG_DO_HTC_WAKEUP); + ret = __wlan_hdd_bus_suspend(state, wow_params); cds_ssr_unprotect(__func__); return ret; diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 43f7162e76b8..db71a14dafe5 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -2551,7 +2551,8 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev, WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, value[1], value[2], DBG_CMD); case QCSAP_SET_WLAN_SUSPEND: - ret = hdd_wlan_fake_apps_suspend(hdd_ctx->wiphy, dev); + ret = hdd_wlan_fake_apps_suspend(hdd_ctx->wiphy, dev, + value[1], value[2]); break; case QCSAP_SET_WLAN_RESUME: ret = hdd_wlan_fake_apps_resume(hdd_ctx->wiphy, dev); diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 2b02168ffce1..dbc7b516e7c1 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -2262,6 +2262,7 @@ int hdd_set_qpower_config(hdd_context_t *hddctx, hdd_adapter_t *adapter, return 0; } + #ifdef WLAN_SUSPEND_RESUME_TEST /* * On iHelium there are 12 CE irqs and #2 is the wake irq. This may not be @@ -2345,15 +2346,36 @@ static void hdd_wlan_fake_apps_resume_irq_callback(uint32_t val) g_dev = NULL; } -int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev) +int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev, + enum wow_interface_pause pause_setting, + enum wow_resume_trigger resume_setting) { qdf_device_t qdf_dev; struct hif_opaque_softc *hif_ctx; pm_message_t state; int i, resume_err, suspend_err; + struct wow_enable_params wow_params = { + .is_unit_test = true, + .interface_pause = pause_setting, + .resume_trigger = resume_setting + }; hdd_info("Unit-test suspend WLAN"); + if (pause_setting < WOW_INTERFACE_PAUSE_DEFAULT || + pause_setting >= WOW_INTERFACE_PAUSE_COUNT) { + hdd_err("Invalid interface pause %d (expected range [0, 2])", + pause_setting); + return -EINVAL; + } + + if (resume_setting < WOW_RESUME_TRIGGER_DEFAULT || + resume_setting >= WOW_RESUME_TRIGGER_COUNT) { + hdd_err("Invalid resume trigger %d (expected range [0, 2])", + resume_setting); + return -EINVAL; + } + qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); if (!qdf_dev) { hdd_err("Failed to get QDF device context"); @@ -2376,7 +2398,7 @@ int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev) goto resume_done; state.event = PM_EVENT_SUSPEND; - suspend_err = wlan_hdd_unit_test_bus_suspend(state); + suspend_err = wlan_hdd_unit_test_bus_suspend(state, wow_params); if (suspend_err) goto cfg80211_resume; diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 484ed86137b9..802e7e7c4c9f 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -12038,9 +12038,11 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, case WE_SET_MON_MODE_CHAN: ret = wlan_hdd_set_mon_chan(pAdapter, value[1], value[2]); break; - case WE_SET_WLAN_SUSPEND: - ret = hdd_wlan_fake_apps_suspend(hdd_ctx->wiphy, dev); + case WE_SET_WLAN_SUSPEND: { + ret = hdd_wlan_fake_apps_suspend(hdd_ctx->wiphy, dev, + value[1], value[2]); break; + } case WE_SET_WLAN_RESUME: ret = hdd_wlan_fake_apps_resume(hdd_ctx->wiphy, dev); break; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index f0834655fea7..da4acaa8f244 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -6827,4 +6827,48 @@ struct scan_chan_info { uint32_t tx_frame_count; uint32_t clock_freq; }; + +/** + * enum wow_resume_trigger - resume trigger override setting values + * @WOW_RESUME_TRIGGER_DEFAULT: fw to use platform default resume trigger + * @WOW_RESUME_TRIGGER_HTC_WAKEUP: force fw to use HTC Wakeup to resume + * @WOW_RESUME_TRIGGER_GPIO: force fw to use GPIO to resume + * @WOW_RESUME_TRIGGER_COUNT: number of resume trigger options + */ +enum wow_resume_trigger { + /* always first */ + WOW_RESUME_TRIGGER_DEFAULT = 0, + WOW_RESUME_TRIGGER_HTC_WAKEUP, + WOW_RESUME_TRIGGER_GPIO, + /* always last */ + WOW_RESUME_TRIGGER_COUNT +}; + +/** + * enum wow_interface_pause - interface pause override setting values + * @WOW_INTERFACE_PAUSE_DEFAULT: use platform default interface pause setting + * @WOW_INTERFACE_PAUSE_ENABLE: force interface pause setting to enabled + * @WOW_INTERFACE_PAUSE_DISABLE: force interface pause setting to disabled + * @WOW_INTERFACE_PAUSE_COUNT: number of interface pause options + */ +enum wow_interface_pause { + /* always first */ + WOW_INTERFACE_PAUSE_DEFAULT = 0, + WOW_INTERFACE_PAUSE_ENABLE, + WOW_INTERFACE_PAUSE_DISABLE, + /* always last */ + WOW_INTERFACE_PAUSE_COUNT +}; + +/** + * struct wow_enable_params - A collection of wow enable override parameters + * @is_unit_test: true to notify fw this is a unit-test suspend + * @interface_pause: used to override the interface pause indication sent to fw + * @resume_trigger: used to force fw to use a particular resume method + */ +struct wow_enable_params { + bool is_unit_test; + enum wow_interface_pause interface_pause; + enum wow_resume_trigger resume_trigger; +}; #endif /* __SIR_API_H */ diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 63781efb1b16..ebe8ba2403d4 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -134,9 +134,11 @@ QDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId); QDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx, uint8_t *pVersion, uint32_t versionBufferSize); -int wma_runtime_suspend(uint32_t wow_flags); + +int wma_runtime_suspend(struct wow_enable_params wow_params); int wma_runtime_resume(void); -int wma_bus_suspend(uint32_t wow_flags); + +int wma_bus_suspend(struct wow_enable_params wow_params); int wma_is_target_wake_up_received(void); int wma_clear_target_wake_up(void); QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr); @@ -147,8 +149,10 @@ QDF_STATUS wma_resume_target(WMA_HANDLE handle); QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle); QDF_STATUS wma_disable_d0wow_in_fw(WMA_HANDLE handle); bool wma_is_wow_mode_selected(WMA_HANDLE handle); -QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle, uint32_t wow_flags); -QDF_STATUS wma_enable_d0wow_in_fw(WMA_HANDLE handle, uint32_t wow_flags); +QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle, + struct wow_enable_params wow_params); +QDF_STATUS wma_enable_d0wow_in_fw(WMA_HANDLE handle, + struct wow_enable_params wow_params); bool wma_check_scan_in_progress(WMA_HANDLE handle); void wma_set_peer_authorized_cb(void *wma_ctx, wma_peer_authorized_fp auth_cb); QDF_STATUS wma_set_peer_param(void *wma_ctx, uint8_t *peer_addr, diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index cbc061da7af3..83c81f6aee93 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3451,11 +3451,12 @@ static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val) /** * wma_enable_wow_in_fw() - wnable wow in fw * @wma: wma handle - * @wow_flags: bitmap of WMI WOW flags to pass to FW + * @wow_params: collection of wow enable override parameters * * Return: QDF status */ -QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle, uint32_t wow_flags) +QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle, + struct wow_enable_params wow_params) { tp_wma_handle wma = handle; int ret; @@ -3481,8 +3482,42 @@ QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle, uint32_t wow_flags) host_credits, wmi_pending_cmds); param.enable = true; - param.can_suspend_link = htc_can_suspend_link(wma->htc_handle); - param.flags = wow_flags; + if (wow_params.is_unit_test) + param.flags = WMI_WOW_FLAG_UNIT_TEST_ENABLE; + + switch (wow_params.interface_pause) { + default: + WMA_LOGE("Invalid interface pause setting: %d", + wow_params.interface_pause); + /* intentional fall-through to default */ + case WOW_INTERFACE_PAUSE_DEFAULT: + param.can_suspend_link = htc_can_suspend_link(wma->htc_handle); + break; + case WOW_INTERFACE_PAUSE_ENABLE: + param.can_suspend_link = true; + break; + case WOW_INTERFACE_PAUSE_DISABLE: + param.can_suspend_link = false; + break; + } + + switch (wow_params.resume_trigger) { + default: + WMA_LOGE("Invalid resume trigger setting: %d", + wow_params.resume_trigger); + /* intentional fall-through to default */ + case WOW_RESUME_TRIGGER_DEFAULT: + case WOW_RESUME_TRIGGER_GPIO: + /* + * GPIO is currently implicit. This means you can't actually + * force GPIO if a platform's default wake trigger is HTC wakeup + */ + break; + case WOW_RESUME_TRIGGER_HTC_WAKEUP: + param.flags |= WMI_WOW_FLAG_DO_HTC_WAKEUP; + break; + } + ret = wmi_unified_wow_enable_send(wma->wmi_handle, ¶m, WMA_WILDCARD_PDEV_ID); if (ret) { @@ -5492,14 +5527,15 @@ failure: /** * __wma_bus_suspend(): handles bus suspend for wma * @type: is this suspend part of runtime suspend or system suspend? - * @wow_flags: bitmap of WMI WOW flags to pass to FW + * @wow_params: collection of wow enable override parameters * * Bails if a scan is in progress. * Calls the appropriate handlers based on configuration and event. * * Return: 0 for success or error code */ -static int __wma_bus_suspend(enum qdf_suspend_type type, uint32_t wow_flags) +static int __wma_bus_suspend(enum qdf_suspend_type type, + struct wow_enable_params wow_params) { WMA_HANDLE handle = cds_get_context(QDF_MODULE_ID_WMA); if (NULL == handle) { @@ -5523,7 +5559,7 @@ static int __wma_bus_suspend(enum qdf_suspend_type type, uint32_t wow_flags) wma_is_wow_mode_selected(handle)); if (wma_is_wow_mode_selected(handle)) { - QDF_STATUS status = wma_enable_wow_in_fw(handle, wow_flags); + QDF_STATUS status = wma_enable_wow_in_fw(handle, wow_params); return qdf_status_to_os_return(status); } @@ -5532,7 +5568,7 @@ static int __wma_bus_suspend(enum qdf_suspend_type type, uint32_t wow_flags) /** * wma_runtime_suspend() - handles runtime suspend request from hdd - * @wow_flags: bitmap of WMI WOW flags to pass to FW + * @wow_params: collection of wow enable override parameters * * Calls the appropriate handler based on configuration and event. * Last busy marking should prevent race conditions between processing @@ -5544,23 +5580,22 @@ static int __wma_bus_suspend(enum qdf_suspend_type type, uint32_t wow_flags) * * Return: 0 for success or error code */ -int wma_runtime_suspend(uint32_t wow_flags) +int wma_runtime_suspend(struct wow_enable_params wow_params) { - return __wma_bus_suspend(QDF_RUNTIME_SUSPEND, wow_flags); + return __wma_bus_suspend(QDF_RUNTIME_SUSPEND, wow_params); } /** * wma_bus_suspend() - handles bus suspend request from hdd - * @wow_flags: bitmap of WMI WOW flags to pass to FW + * @wow_params: collection of wow enable override parameters * * Calls the appropriate handler based on configuration and event * * Return: 0 for success or error code */ -int wma_bus_suspend(uint32_t wow_flags) +int wma_bus_suspend(struct wow_enable_params wow_params) { - - return __wma_bus_suspend(QDF_SYSTEM_SUSPEND, wow_flags); + return __wma_bus_suspend(QDF_SYSTEM_SUSPEND, wow_params); } /**