diff --git a/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_wake_lock.h b/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_wake_lock.h new file mode 100644 index 0000000000..768b21b78d --- /dev/null +++ b/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_wake_lock.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013-2019 The Linux Foundation. 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: target_if_vdev_mgr_wake_lock.h + * + * This file provides declaration for wakelock APIs + */ + +#ifndef __TARGET_IF_VDEV_MGR_WAKE_LOCK_H__ +#define __TARGET_IF_VDEV_MGR_WAKE_LOCK_H__ + +enum wakelock_mode { + START_WAKELOCK, + STOP_WAKELOCK, + DELETE_WAKELOCK +}; + +#ifdef FEATURE_VDEV_RSP_WAKELOCK + +/** + * target_if_wake_lock_init() - API to initialize + wakelocks:start, + stop and delete. + * @vdev: pointer to vdev + * + * This also initialize the runtime lock + * + * Return: None + */ +void target_if_wake_lock_init(struct wlan_objmgr_vdev *vdev); + +/** + * target_if_wake_lock_deinit() - API to destroy + wakelocks:start, stop and delete. + * @vdev: pointer to vdev + * + * This also destroy the runtime lock + * + * Return: None + */ +void target_if_wake_lock_deinit(struct wlan_objmgr_vdev *vdev); + +/** + * target_if_start_wake_lock_timeout_acquire() - acquire the + vdev start wakelock + * @vdev: pointer to vdev + * + * This also acquires the target_if runtime pm lock. + * + * Return: Success/Failure + */ +QDF_STATUS target_if_wake_lock_timeout_acquire(struct wlan_objmgr_vdev *vdev, + enum wakelock_mode mode); +/** + * target_if_start_wake_lock_timeout_release() - release the + start wakelock + * @vdev: pointer to vdev + * + * This also release the target_if runtime pm lock. + * + * Return: Success/Failure + */ +QDF_STATUS target_if_wake_lock_timeout_release(struct wlan_objmgr_vdev *vdev, + enum wakelock_mode mode); +#else +static inline void target_if_wake_lock_init(struct wlan_objmgr_vdev *vdev) +{ +} + +static inline void target_if_wake_lock_deinit(struct wlan_objmgr_vdev *vdev) +{ +} + +static inline QDF_STATUS target_if_wake_lock_timeout_acquire( + struct wlan_objmgr_vdev *vdev, + enum wakelock_mode mode) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS target_if_wake_lock_timeout_release( + struct wlan_objmgr_vdev *vdev, + enum wakelock_mode mode) +{ + return QDF_STATUS_SUCCESS; +} +#endif +#endif diff --git a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c index ee271bc880..8764b27d69 100644 --- a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c +++ b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -412,6 +413,7 @@ static QDF_STATUS target_if_vdev_mgr_start_send( mlme_err("VDEV_%d: Invalid response structure", vdev_id); return QDF_STATUS_E_FAILURE; } + target_if_wake_lock_timeout_acquire(vdev, START_WAKELOCK); vdev_rsp->expire_time = START_RESPONSE_TIMER; if (param->is_restart) @@ -425,6 +427,7 @@ static QDF_STATUS target_if_vdev_mgr_start_send( if (QDF_IS_STATUS_ERROR(status)) { vdev_rsp->timer_status = QDF_STATUS_E_CANCELED; vdev_rsp->expire_time = 0; + target_if_wake_lock_timeout_release(vdev, START_WAKELOCK); if (param->is_restart) target_if_vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, RESTART_RESPONSE_BIT); @@ -446,6 +449,7 @@ static QDF_STATUS target_if_vdev_mgr_delete_response_send( rsp.vdev_id = wlan_vdev_get_id(vdev); status = rx_ops->vdev_mgr_delete_response(psoc, &rsp); + target_if_wake_lock_timeout_release(vdev, DELETE_WAKELOCK); return status; } @@ -485,7 +489,7 @@ static QDF_STATUS target_if_vdev_mgr_delete_send( mlme_err("VDEV_%d: Invalid response structure", vdev_id); return QDF_STATUS_E_FAILURE; } - + target_if_wake_lock_timeout_acquire(vdev, DELETE_WAKELOCK); vdev_rsp->expire_time = DELETE_RESPONSE_TIMER; target_if_vdev_mgr_rsp_timer_start(vdev, vdev_rsp, DELETE_RESPONSE_BIT); @@ -501,6 +505,7 @@ static QDF_STATUS target_if_vdev_mgr_delete_send( WLAN_SOC_F_TESTMODE_ENABLE)) target_if_vdev_mgr_delete_response_send(vdev, rx_ops); } else { + target_if_wake_lock_timeout_release(vdev, DELETE_WAKELOCK); vdev_rsp->expire_time = 0; vdev_rsp->timer_status = QDF_STATUS_E_CANCELED; target_if_vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, @@ -547,6 +552,7 @@ static QDF_STATUS target_if_vdev_mgr_stop_send( return QDF_STATUS_E_FAILURE; } + target_if_wake_lock_timeout_acquire(vdev, STOP_WAKELOCK); vdev_rsp->expire_time = STOP_RESPONSE_TIMER; target_if_vdev_mgr_rsp_timer_start(vdev, vdev_rsp, STOP_RESPONSE_BIT); @@ -554,6 +560,7 @@ static QDF_STATUS target_if_vdev_mgr_stop_send( if (QDF_IS_STATUS_ERROR(status)) { vdev_rsp->expire_time = 0; vdev_rsp->timer_status = QDF_STATUS_E_CANCELED; + target_if_wake_lock_timeout_release(vdev, STOP_WAKELOCK); target_if_vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, STOP_RESPONSE_BIT); } @@ -580,6 +587,7 @@ static QDF_STATUS target_if_vdev_mgr_down_send( } status = wmi_unified_vdev_down_send(wmi_handle, param->vdev_id); + target_if_wake_lock_timeout_release(vdev, START_WAKELOCK); return status; } @@ -618,6 +626,7 @@ static QDF_STATUS target_if_vdev_mgr_up_send( ucfg_wlan_vdev_mgr_get_param_bssid(vdev, bssid); status = wmi_unified_vdev_up_send(wmi_handle, bssid, param); + target_if_wake_lock_timeout_release(vdev, START_WAKELOCK); return status; } diff --git a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_wake_lock.c b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_wake_lock.c new file mode 100644 index 0000000000..69c3a52f54 --- /dev/null +++ b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_wake_lock.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2013-2019 The Linux Foundation. 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: target_if_vdev_mgr_wake_lock.c + * + * This file provide definition for APIs related to wake lock + */ +#include "wlan_objmgr_vdev_obj.h" +#include "include/wlan_vdev_mlme.h" +#include "qdf_lock.h" +#include "target_if_vdev_mgr_wake_lock.h" +#include "wlan_lmac_if_def.h" +#include "host_diag_core_event.h" +#include +#include +#include +#include "target_if_vdev_mgr_rx_ops.h" + +void target_if_wake_lock_init(struct wlan_objmgr_vdev *vdev) +{ + struct vdev_mlme_wakelock *vdev_wakelock; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + if (!vdev) { + target_if_err(" VDEV is NULL"); + return; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + target_if_err("PSOC is NULL"); + return; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_get_wakelock_info) { + target_if_err("No Rx Ops"); + return; + } + + vdev_wakelock = rx_ops->vdev_mgr_get_wakelock_info(vdev); + + qdf_wake_lock_create(&vdev_wakelock->start_wakelock, "vdev_start"); + qdf_wake_lock_create(&vdev_wakelock->stop_wakelock, "vdev_stop"); + qdf_wake_lock_create(&vdev_wakelock->delete_wakelock, "vdev_delete"); + + qdf_runtime_lock_init(&vdev_wakelock->wmi_cmd_rsp_runtime_lock); +} + +void target_if_wake_lock_deinit(struct wlan_objmgr_vdev *vdev) +{ + struct vdev_mlme_wakelock *vdev_wakelock; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + if (!vdev) { + target_if_err(" VDEV is NULL"); + return; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + target_if_err("PSOC is NULL"); + return; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_get_wakelock_info) { + target_if_err("No Rx Ops"); + return; + } + + vdev_wakelock = rx_ops->vdev_mgr_get_wakelock_info(vdev); + + qdf_wake_lock_destroy(&vdev_wakelock->start_wakelock); + qdf_wake_lock_destroy(&vdev_wakelock->stop_wakelock); + qdf_wake_lock_destroy(&vdev_wakelock->delete_wakelock); + + qdf_runtime_lock_deinit(&vdev_wakelock->wmi_cmd_rsp_runtime_lock); +} + +QDF_STATUS target_if_wake_lock_timeout_acquire( + struct wlan_objmgr_vdev *vdev, + enum wakelock_mode mode) +{ + struct vdev_mlme_wakelock *vdev_wakelock; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + if (!vdev) { + target_if_err(" VDEV is NULL"); + return QDF_STATUS_E_FAILURE; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + target_if_err("PSOC is NULL"); + return QDF_STATUS_E_FAILURE; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_get_wakelock_info) { + target_if_err("No Rx Ops"); + return QDF_STATUS_E_FAILURE; + } + + vdev_wakelock = rx_ops->vdev_mgr_get_wakelock_info(vdev); + + switch (mode) { + case START_WAKELOCK: + qdf_wake_lock_timeout_acquire(&vdev_wakelock->start_wakelock, + START_RESPONSE_TIMER); + break; + case STOP_WAKELOCK: + qdf_wake_lock_timeout_acquire(&vdev_wakelock->stop_wakelock, + STOP_RESPONSE_TIMER); + break; + case DELETE_WAKELOCK: + qdf_wake_lock_timeout_acquire(&vdev_wakelock->delete_wakelock, + DELETE_RESPONSE_TIMER); + break; + default: + target_if_err("operation mode is invalid"); + return QDF_STATUS_E_FAILURE; + } + + qdf_runtime_pm_prevent_suspend( + &vdev_wakelock->wmi_cmd_rsp_runtime_lock); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_wake_lock_timeout_release( + struct wlan_objmgr_vdev *vdev, + enum wakelock_mode mode) +{ + struct vdev_mlme_wakelock *vdev_wakelock; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + if (!vdev) { + target_if_err(" VDEV is NULL"); + return QDF_STATUS_E_FAILURE; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + target_if_err("PSOC is NULL"); + return QDF_STATUS_E_FAILURE; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_get_wakelock_info) { + target_if_err("No Rx Ops"); + return QDF_STATUS_E_FAILURE; + } + + vdev_wakelock = rx_ops->vdev_mgr_get_wakelock_info(vdev); + + switch (mode) { + case START_WAKELOCK: + qdf_wake_lock_release(&vdev_wakelock->start_wakelock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + break; + case STOP_WAKELOCK: + qdf_wake_lock_release(&vdev_wakelock->stop_wakelock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + break; + case DELETE_WAKELOCK: + qdf_wake_lock_release(&vdev_wakelock->delete_wakelock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + break; + default: + target_if_err("operation mode is invalid"); + return QDF_STATUS_E_FAILURE; + } + + qdf_runtime_pm_allow_suspend(&vdev_wakelock->wmi_cmd_rsp_runtime_lock); + + return QDF_STATUS_SUCCESS; +} + 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 b061b4e3cb..03e5fb13a2 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 @@ -1473,6 +1473,10 @@ struct wlan_lmac_if_mlme_rx_ops { QDF_STATUS (*vdev_mgr_tbttoffset_update_handle)( uint32_t num_vdevs, bool is_ext); +#ifdef FEATURE_VDEV_RSP_WAKELOCK + struct vdev_mlme_wakelock *(*vdev_mgr_get_wakelock_info)( + struct wlan_objmgr_vdev *vdev); +#endif #endif }; diff --git a/umac/mlme/include/wlan_vdev_mlme.h b/umac/mlme/include/wlan_vdev_mlme.h index d12fc27e8e..2742582263 100644 --- a/umac/mlme/include/wlan_vdev_mlme.h +++ b/umac/mlme/include/wlan_vdev_mlme.h @@ -511,6 +511,22 @@ struct vdev_mlme_ops { struct vdev_mlme_obj *vdev_mlme); }; +#ifdef FEATURE_VDEV_RSP_WAKELOCK +/** + * struct wlan_vdev_wakelock - vdev wake lock sub structure + * @start_wakelock: wakelock for vdev start + * @stop_wakelock: wakelock for vdev stop + * @delete_wakelock: wakelock for vdev delete + * @wmi_cmd_rsp_runtime_lock: run time lock + */ +struct vdev_mlme_wakelock { + qdf_wake_lock_t start_wakelock; + qdf_wake_lock_t stop_wakelock; + qdf_wake_lock_t delete_wakelock; + qdf_runtime_lock_t wmi_cmd_rsp_runtime_lock; +}; +#endif + /** * struct vdev_mlme_obj - VDEV MLME component object * @proto: VDEV MLME proto substructure @@ -522,6 +538,7 @@ struct vdev_mlme_ops { * @ops: VDEV MLME callback table * @ext_vdev_ptr: VDEV MLME legacy pointer * @vdev_rt: VDEV response timer + * @vdev_wakelock: vdev wakelock sub structure */ struct vdev_mlme_obj { struct vdev_mlme_proto proto; @@ -535,6 +552,9 @@ struct vdev_mlme_obj { struct vdev_mlme_ops *ops; void *ext_vdev_ptr; struct vdev_response_timer vdev_rt; +#ifdef FEATURE_VDEV_RSP_WAKELOCK + struct vdev_mlme_wakelock vdev_wakelock; +#endif }; /** diff --git a/umac/mlme/mlme_objmgr/dispatcher/src/wlan_vdev_mlme_main.c b/umac/mlme/mlme_objmgr/dispatcher/src/wlan_vdev_mlme_main.c index ddd41b2744..e55d83c43d 100644 --- a/umac/mlme/mlme_objmgr/dispatcher/src/wlan_vdev_mlme_main.c +++ b/umac/mlme/mlme_objmgr/dispatcher/src/wlan_vdev_mlme_main.c @@ -31,6 +31,7 @@ #include "wlan_serialization_api.h" #include "wlan_utility.h" #include +#include "target_if_vdev_mgr_wake_lock.h" static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev, void *arg) @@ -83,6 +84,7 @@ static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev, (void *)vdev_mlme, QDF_STATUS_SUCCESS); + target_if_wake_lock_init(vdev); if (mlme_vdev_ops_ext_hdl_post_create(vdev_mlme) != QDF_STATUS_SUCCESS) { mlme_err("Legacy vdev object post creation failed"); @@ -130,6 +132,7 @@ static QDF_STATUS mlme_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev, mlme_err(" VDEV is NULL"); return QDF_STATUS_E_FAILURE; } + target_if_wake_lock_deinit(vdev); vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); if (!vdev_mlme) { diff --git a/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_rx_api.c b/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_rx_api.c index b7584b9d3c..e00cb35add 100644 --- a/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_rx_api.c +++ b/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_rx_api.c @@ -228,6 +228,36 @@ tgt_vdev_mgr_ext_tbttoffset_update_handle(uint32_t num_vdevs, bool is_ext) return status; } +#ifdef FEATURE_VDEV_RSP_WAKELOCK +static struct vdev_mlme_wakelock * +tgt_vdev_mgr_get_wakelock_info(struct wlan_objmgr_vdev *vdev) +{ + struct vdev_mlme_obj *vdev_mlme; + + vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); + if (!vdev_mlme) { + mlme_err("VDEV_%d: VDEV_MLME is NULL", wlan_vdev_get_id(vdev)); + return NULL; + } + + return &vdev_mlme->vdev_wakelock; +} + +static inline void +tgt_vdev_mgr_reg_wakelock_info_rx_op(struct wlan_lmac_if_mlme_rx_ops + *mlme_rx_ops) +{ + mlme_rx_ops->vdev_mgr_get_wakelock_info = + tgt_vdev_mgr_get_wakelock_info; +} +#else +static inline void +tgt_vdev_mgr_reg_wakelock_info_rx_op(struct wlan_lmac_if_mlme_rx_ops + *mlme_rx_ops) +{ +} +#endif + void tgt_vdev_mgr_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) { struct wlan_lmac_if_mlme_rx_ops *mlme_rx_ops = &rx_ops->mops; @@ -244,4 +274,6 @@ void tgt_vdev_mgr_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) tgt_vdev_mgr_delete_response_handler; mlme_rx_ops->vdev_mgr_get_response_timer_info = tgt_vdev_mgr_get_response_timer_info; + + tgt_vdev_mgr_reg_wakelock_info_rx_op(&rx_ops->mops); }