qcacld-3.0: Move IPA RM functionalities to IPA component
IPA module has been moved to CLD component under the converged driver model. Move the legacy IPA RM APIs to the IPA component. Change-Id: Iaff12ae3cec9ee6ff20543579692385c9a555613 CRs-Fixed: 2177925
This commit is contained in:
parent
d01b445db4
commit
2e7aae9fdb
3
Kbuild
3
Kbuild
@ -1081,7 +1081,8 @@ IPA_OBJS := $(IPA_DIR)/dispatcher/src/wlan_ipa_ucfg_api.o \
|
|||||||
$(IPA_DIR)/dispatcher/src/wlan_ipa_obj_mgmt_api.o \
|
$(IPA_DIR)/dispatcher/src/wlan_ipa_obj_mgmt_api.o \
|
||||||
$(IPA_DIR)/dispatcher/src/wlan_ipa_tgt_api.o \
|
$(IPA_DIR)/dispatcher/src/wlan_ipa_tgt_api.o \
|
||||||
$(IPA_DIR)/core/src/wlan_ipa_main.o \
|
$(IPA_DIR)/core/src/wlan_ipa_main.o \
|
||||||
$(IPA_DIR)/core/src/wlan_ipa_core.o
|
$(IPA_DIR)/core/src/wlan_ipa_core.o \
|
||||||
|
$(IPA_DIR)/core/src/wlan_ipa_rm.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
########## CLD TARGET_IF #######
|
########## CLD TARGET_IF #######
|
||||||
|
@ -55,6 +55,17 @@ static inline bool wlan_ipa_uc_is_enabled(struct wlan_ipa_config *ipa_cfg)
|
|||||||
return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_UC_ENABLE_MASK);
|
return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_UC_ENABLE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_is_rm_enabled() - Is IPA RM enabled?
|
||||||
|
* @ipa_cfg: IPA config
|
||||||
|
*
|
||||||
|
* Return: true if IPA RM is enabled, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool wlan_ipa_is_rm_enabled(struct wlan_ipa_config *ipa_cfg)
|
||||||
|
{
|
||||||
|
return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_RM_ENABLE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wlan_ipa_setup - IPA initialize and setup
|
* wlan_ipa_setup - IPA initialize and setup
|
||||||
* @ipa_ctx: IPA priv obj
|
* @ipa_ctx: IPA priv obj
|
||||||
@ -65,6 +76,13 @@ static inline bool wlan_ipa_uc_is_enabled(struct wlan_ipa_config *ipa_cfg)
|
|||||||
QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
|
QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
|
||||||
struct wlan_ipa_config *ipa_cfg);
|
struct wlan_ipa_config *ipa_cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_get_obj_context - Get IPA OBJ context
|
||||||
|
*
|
||||||
|
* Return: IPA context
|
||||||
|
*/
|
||||||
|
struct wlan_ipa_priv *wlan_ipa_get_obj_context(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wlan_ipa_cleanup - IPA cleanup
|
* wlan_ipa_cleanup - IPA cleanup
|
||||||
* @ipa_ctx: IPA priv obj
|
* @ipa_ctx: IPA priv obj
|
||||||
@ -72,5 +90,124 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
|
|||||||
* Return: QDF_STATUS
|
* Return: QDF_STATUS
|
||||||
*/
|
*/
|
||||||
QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx);
|
QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_uc_enable_pipes() - Enable IPA uC pipes
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
*
|
||||||
|
* Return: QDF_STATUS
|
||||||
|
*/
|
||||||
|
QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_uc_disable_pipes() - Disable IPA uC pipes
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
*
|
||||||
|
* Return: QDF_STATUS
|
||||||
|
*/
|
||||||
|
QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx);
|
||||||
|
|
||||||
|
#ifndef CONFIG_IPA_WDI_UNIFIED_API
|
||||||
|
/**
|
||||||
|
* wlan_ipa_wdi_rm_request_resource() - IPA WDI request resource
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
* @res_name: IPA RM resource name
|
||||||
|
*
|
||||||
|
* Return: 0 on success, negative errno on error
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
int wlan_ipa_wdi_rm_request_resource(struct wlan_ipa_priv *ipa_ctx,
|
||||||
|
qdf_ipa_rm_resource_name_t res_name)
|
||||||
|
{
|
||||||
|
return qdf_ipa_rm_request_resource(res_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_wdi_rm_release_resource() - IPA WDI release resource
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
* @res_name: IPA RM resource name
|
||||||
|
*
|
||||||
|
* Return: 0 on success, negative errno on error
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
int wlan_ipa_wdi_rm_release_resource(struct wlan_ipa_priv *ipa_ctx,
|
||||||
|
qdf_ipa_rm_resource_name_t res_name)
|
||||||
|
{
|
||||||
|
return qdf_ipa_rm_release_resource(res_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_wdi_rm_request() - Request resource from IPA
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
*
|
||||||
|
* Return: QDF_STATUS
|
||||||
|
*/
|
||||||
|
QDF_STATUS wlan_ipa_wdi_rm_request(struct wlan_ipa_priv *ipa_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_wdi_rm_try_release() - Attempt to release IPA resource
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
*
|
||||||
|
* Return: QDF_STATUS
|
||||||
|
*/
|
||||||
|
QDF_STATUS wlan_ipa_wdi_rm_try_release(struct wlan_ipa_priv *ipa_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_wdi_setup_rm() - Setup IPA resource management
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
*
|
||||||
|
* Return: QDF_STATUS
|
||||||
|
*/
|
||||||
|
QDF_STATUS wlan_ipa_wdi_setup_rm(struct wlan_ipa_priv *ipa_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_wdi_destroy_rm() - Destroy IPA resources
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
*
|
||||||
|
* Destroys all resources associated with the IPA resource manager
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
void wlan_ipa_wdi_destroy_rm(struct wlan_ipa_priv *ipa_ctx);
|
||||||
|
|
||||||
|
#else /* CONFIG_IPA_WDI_UNIFIED_API */
|
||||||
|
|
||||||
|
static inline int wlan_ipa_wdi_rm_request_resource(
|
||||||
|
struct wlan_ipa_priv *ipa_ctx,
|
||||||
|
qdf_ipa_rm_resource_name_t res_name)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wlan_ipa_wdi_rm_release_resource(
|
||||||
|
struct wlan_ipa_priv *ipa_ctx,
|
||||||
|
qdf_ipa_rm_resource_name_t res_name)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QDF_STATUS wlan_ipa_wdi_setup_rm(struct wlan_ipa_priv *ipa_ctx)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wlan_ipa_wdi_destroy_rm(struct wlan_ipa_priv *ipa_ctx)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QDF_STATUS wlan_ipa_wdi_rm_request(struct wlan_ipa_priv *ipa_ctx)
|
||||||
|
{
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QDF_STATUS wlan_ipa_wdi_rm_try_release(struct wlan_ipa_priv
|
||||||
|
*ipa_ctx)
|
||||||
|
{
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_IPA_WDI_UNIFIED_API */
|
||||||
|
|
||||||
#endif /* IPA_OFFLOAD */
|
#endif /* IPA_OFFLOAD */
|
||||||
#endif /* _WLAN_IPA_CORE_H_ */
|
#endif /* _WLAN_IPA_CORE_H_ */
|
||||||
|
@ -310,6 +310,74 @@ static inline int wlan_ipa_wdi_teardown_sys_pipe(
|
|||||||
|
|
||||||
#endif /* CONFIG_IPA_WDI_UNIFIED_API */
|
#endif /* CONFIG_IPA_WDI_UNIFIED_API */
|
||||||
|
|
||||||
|
QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ipa_debug("enter");
|
||||||
|
|
||||||
|
if (!ipa_ctx->ipa_pipes_down) {
|
||||||
|
/*
|
||||||
|
* IPA WDI Pipes are already activated due to
|
||||||
|
* rm deferred resources grant
|
||||||
|
*/
|
||||||
|
ipa_warn("IPA WDI Pipes are already activated");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
|
||||||
|
ipa_ctx->dp_pdev);
|
||||||
|
if (result) {
|
||||||
|
ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
|
||||||
|
return QDF_STATUS_E_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_event_reset(&ipa_ctx->ipa_resource_comp);
|
||||||
|
ipa_ctx->ipa_pipes_down = false;
|
||||||
|
|
||||||
|
cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
|
||||||
|
ipa_ctx->dp_pdev);
|
||||||
|
|
||||||
|
end:
|
||||||
|
ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
|
||||||
|
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ipa_debug("enter");
|
||||||
|
|
||||||
|
if (ipa_ctx->ipa_pipes_down) {
|
||||||
|
/*
|
||||||
|
* This shouldn't happen :
|
||||||
|
* IPA WDI Pipes are already deactivated
|
||||||
|
*/
|
||||||
|
QDF_ASSERT(0);
|
||||||
|
ipa_warn("IPA WDI Pipes are already deactivated");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
|
||||||
|
ipa_ctx->dp_pdev);
|
||||||
|
|
||||||
|
result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
|
||||||
|
ipa_ctx->dp_pdev);
|
||||||
|
if (result) {
|
||||||
|
ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
|
||||||
|
return QDF_STATUS_E_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipa_ctx->ipa_pipes_down = true;
|
||||||
|
|
||||||
|
end:
|
||||||
|
ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
|
||||||
|
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wlan_ipa_alloc_tx_desc_list() - Allocate IPA Tx desc list
|
* wlan_ipa_alloc_tx_desc_list() - Allocate IPA Tx desc list
|
||||||
* @ipa_ctx: IPA context
|
* @ipa_ctx: IPA context
|
||||||
@ -593,6 +661,10 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
|
|||||||
qdf_mutex_create(&ipa_ctx->event_lock);
|
qdf_mutex_create(&ipa_ctx->event_lock);
|
||||||
qdf_mutex_create(&ipa_ctx->ipa_lock);
|
qdf_mutex_create(&ipa_ctx->ipa_lock);
|
||||||
|
|
||||||
|
status = wlan_ipa_wdi_setup_rm(ipa_ctx);
|
||||||
|
if (status != QDF_STATUS_SUCCESS)
|
||||||
|
goto fail_setup_rm;
|
||||||
|
|
||||||
for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
|
for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
|
||||||
qdf_mem_zero(&ipa_ctx->sys_pipe[i],
|
qdf_mem_zero(&ipa_ctx->sys_pipe[i],
|
||||||
sizeof(struct wlan_ipa_sys_pipe));
|
sizeof(struct wlan_ipa_sys_pipe));
|
||||||
@ -636,7 +708,18 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
|
|||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
|
|
||||||
fail_create_sys_pipe:
|
fail_create_sys_pipe:
|
||||||
|
wlan_ipa_wdi_destroy_rm(ipa_ctx);
|
||||||
|
|
||||||
|
fail_setup_rm:
|
||||||
qdf_spinlock_destroy(&ipa_ctx->pm_lock);
|
qdf_spinlock_destroy(&ipa_ctx->pm_lock);
|
||||||
|
qdf_spinlock_destroy(&ipa_ctx->q_lock);
|
||||||
|
for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
|
||||||
|
iface_context = &ipa_ctx->iface_context[i];
|
||||||
|
qdf_spinlock_destroy(&iface_context->interface_lock);
|
||||||
|
}
|
||||||
|
qdf_mutex_destroy(&ipa_ctx->event_lock);
|
||||||
|
qdf_mutex_destroy(&ipa_ctx->ipa_lock);
|
||||||
|
qdf_list_destroy(&ipa_ctx->pending_event);
|
||||||
gp_ipa = NULL;
|
gp_ipa = NULL;
|
||||||
ipa_debug("exit: fail");
|
ipa_debug("exit: fail");
|
||||||
|
|
||||||
@ -655,6 +738,8 @@ QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
|
|||||||
if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
|
if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
|
||||||
wlan_ipa_teardown_sys_pipe(ipa_ctx);
|
wlan_ipa_teardown_sys_pipe(ipa_ctx);
|
||||||
|
|
||||||
|
wlan_ipa_wdi_destroy_rm(ipa_ctx);
|
||||||
|
|
||||||
qdf_spinlock_destroy(&ipa_ctx->pm_lock);
|
qdf_spinlock_destroy(&ipa_ctx->pm_lock);
|
||||||
qdf_spinlock_destroy(&ipa_ctx->q_lock);
|
qdf_spinlock_destroy(&ipa_ctx->q_lock);
|
||||||
|
|
||||||
|
412
components/ipa/core/src/wlan_ipa_rm.c
Normal file
412
components/ipa/core/src/wlan_ipa_rm.c
Normal file
@ -0,0 +1,412 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include Files */
|
||||||
|
#include "wlan_ipa_core.h"
|
||||||
|
#include "wlan_ipa_main.h"
|
||||||
|
#include "host_diag_core_event.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_rm_notify() - IPA resource manager notifier callback
|
||||||
|
* @user_data: user data registered with IPA
|
||||||
|
* @event: the IPA resource manager event that occurred
|
||||||
|
* @data: the data associated with the event
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void wlan_ipa_rm_notify(void *user_data, qdf_ipa_rm_event_t event,
|
||||||
|
unsigned long data)
|
||||||
|
{
|
||||||
|
struct wlan_ipa_priv *ipa_ctx = user_data;
|
||||||
|
|
||||||
|
if (qdf_unlikely(!ipa_ctx))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!wlan_ipa_is_rm_enabled(ipa_ctx->config))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ipa_debug("Evt: %d", event);
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case QDF_IPA_RM_RESOURCE_GRANTED:
|
||||||
|
if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
|
||||||
|
/* RM Notification comes with ISR context
|
||||||
|
* it should be serialized into work queue to avoid
|
||||||
|
* ISR sleep problem
|
||||||
|
*/
|
||||||
|
ipa_ctx->uc_rm_work.event = event;
|
||||||
|
qdf_sched_work(0, &ipa_ctx->uc_rm_work.work);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
qdf_spin_lock_bh(&ipa_ctx->rm_lock);
|
||||||
|
ipa_ctx->rm_state = WLAN_IPA_RM_GRANTED;
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
ipa_ctx->stats.num_rm_grant++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QDF_IPA_RM_RESOURCE_RELEASED:
|
||||||
|
ipa_debug("RM Release");
|
||||||
|
ipa_ctx->resource_unloading = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ipa_err("Unknown RM Evt: %d", event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_rm_cons_release() - WLAN consumer resource release handler
|
||||||
|
*
|
||||||
|
* Callback function registered with IPA that is called when IPA wants
|
||||||
|
* to release the WLAN consumer resource
|
||||||
|
*
|
||||||
|
* Return: 0 if the request is granted, negative errno otherwise
|
||||||
|
*/
|
||||||
|
static int wlan_ipa_rm_cons_release(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_IPA_WDI_UNIFIED_API
|
||||||
|
/**
|
||||||
|
* wlan_ipa_wdi_rm_request() - Request resource from IPA
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
*
|
||||||
|
* Return: QDF_STATUS
|
||||||
|
*/
|
||||||
|
QDF_STATUS wlan_ipa_wdi_rm_request(struct wlan_ipa_priv *ipa_ctx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!wlan_ipa_is_rm_enabled(ipa_ctx->config))
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&ipa_ctx->rm_lock);
|
||||||
|
|
||||||
|
switch (ipa_ctx->rm_state) {
|
||||||
|
case WLAN_IPA_RM_GRANTED:
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
case WLAN_IPA_RM_GRANT_PENDING:
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
return QDF_STATUS_E_PENDING;
|
||||||
|
case WLAN_IPA_RM_RELEASED:
|
||||||
|
ipa_ctx->rm_state = WLAN_IPA_RM_GRANT_PENDING;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
|
||||||
|
ret = qdf_ipa_rm_inactivity_timer_request_resource(
|
||||||
|
QDF_IPA_RM_RESOURCE_WLAN_PROD);
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&ipa_ctx->rm_lock);
|
||||||
|
if (ret == 0) {
|
||||||
|
ipa_ctx->rm_state = WLAN_IPA_RM_GRANTED;
|
||||||
|
ipa_ctx->stats.num_rm_grant_imm++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipa_ctx->wake_lock_released) {
|
||||||
|
qdf_wake_lock_acquire(&ipa_ctx->wake_lock,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_IPA);
|
||||||
|
ipa_ctx->wake_lock_released = false;
|
||||||
|
}
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
|
||||||
|
qdf_cancel_delayed_work(&ipa_ctx->wake_lock_work);
|
||||||
|
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDF_STATUS wlan_ipa_wdi_rm_try_release(struct wlan_ipa_priv *ipa_ctx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!wlan_ipa_is_rm_enabled(ipa_ctx->config))
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (qdf_atomic_read(&ipa_ctx->tx_ref_cnt))
|
||||||
|
return QDF_STATUS_E_AGAIN;
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&ipa_ctx->pm_lock);
|
||||||
|
|
||||||
|
if (!qdf_nbuf_is_queue_empty(&ipa_ctx->pm_queue_head)) {
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
|
||||||
|
return QDF_STATUS_E_AGAIN;
|
||||||
|
}
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&ipa_ctx->rm_lock);
|
||||||
|
switch (ipa_ctx->rm_state) {
|
||||||
|
case WLAN_IPA_RM_GRANTED:
|
||||||
|
break;
|
||||||
|
case WLAN_IPA_RM_GRANT_PENDING:
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
return QDF_STATUS_E_PENDING;
|
||||||
|
case WLAN_IPA_RM_RELEASED:
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IPA driver returns immediately so set the state here to avoid any
|
||||||
|
* race condition.
|
||||||
|
*/
|
||||||
|
ipa_ctx->rm_state = WLAN_IPA_RM_RELEASED;
|
||||||
|
ipa_ctx->stats.num_rm_release++;
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
|
||||||
|
ret = qdf_ipa_rm_inactivity_timer_release_resource(
|
||||||
|
QDF_IPA_RM_RESOURCE_WLAN_PROD);
|
||||||
|
|
||||||
|
if (qdf_unlikely(ret != 0)) {
|
||||||
|
qdf_spin_lock_bh(&ipa_ctx->rm_lock);
|
||||||
|
ipa_ctx->rm_state = WLAN_IPA_RM_GRANTED;
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
QDF_ASSERT(0);
|
||||||
|
ipa_warn("rm_inactivity_timer_release_resource ret fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If wake_lock is released immediately, kernel would try to suspend
|
||||||
|
* immediately as well, Just avoid ping-pong between suspend-resume
|
||||||
|
* while there is healthy amount of data transfer going on by
|
||||||
|
* releasing the wake_lock after some delay.
|
||||||
|
*/
|
||||||
|
qdf_sched_delayed_work(&ipa_ctx->wake_lock_work,
|
||||||
|
msecs_to_jiffies
|
||||||
|
(WLAN_IPA_RX_INACTIVITY_MSEC_DELAY));
|
||||||
|
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IPA_WDI_UNIFIED_API */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_rm_cons_request() - WLAN consumer resource request handler
|
||||||
|
*
|
||||||
|
* Callback function registered with IPA that is called when IPA wants
|
||||||
|
* to access the WLAN consumer resource
|
||||||
|
*
|
||||||
|
* Return: 0 if the request is granted, negative errno otherwise
|
||||||
|
*/
|
||||||
|
static int wlan_ipa_rm_cons_request(void)
|
||||||
|
{
|
||||||
|
struct wlan_ipa_priv *ipa_ctx;
|
||||||
|
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
ipa_ctx = wlan_ipa_get_obj_context();
|
||||||
|
|
||||||
|
if (ipa_ctx->resource_loading) {
|
||||||
|
ipa_err("IPA resource loading in progress");
|
||||||
|
ipa_ctx->pending_cons_req = true;
|
||||||
|
status = QDF_STATUS_E_PENDING;
|
||||||
|
} else if (ipa_ctx->resource_unloading) {
|
||||||
|
ipa_err("IPA resource unloading in progress");
|
||||||
|
ipa_ctx->pending_cons_req = true;
|
||||||
|
status = QDF_STATUS_E_PERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return qdf_status_to_os_return(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_uc_rm_notify_handler() - IPA uC resource notification handler
|
||||||
|
* @ipa_ctx: IPA context
|
||||||
|
* @event: IPA RM event
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
wlan_ipa_uc_rm_notify_handler(struct wlan_ipa_priv *ipa_ctx,
|
||||||
|
qdf_ipa_rm_event_t event)
|
||||||
|
{
|
||||||
|
if (!wlan_ipa_is_rm_enabled(ipa_ctx->config))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ipa_debug("event code %d", event);
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case QDF_IPA_RM_RESOURCE_GRANTED:
|
||||||
|
/* Differed RM Granted */
|
||||||
|
qdf_mutex_acquire(&ipa_ctx->ipa_lock);
|
||||||
|
if ((!ipa_ctx->resource_unloading) &&
|
||||||
|
(!ipa_ctx->activated_fw_pipe)) {
|
||||||
|
wlan_ipa_uc_enable_pipes(ipa_ctx);
|
||||||
|
}
|
||||||
|
qdf_mutex_release(&ipa_ctx->ipa_lock);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QDF_IPA_RM_RESOURCE_RELEASED:
|
||||||
|
/* Differed RM Released */
|
||||||
|
ipa_ctx->resource_unloading = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ipa_err("invalid event code %d", event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_uc_rm_notify_defer() - Defer IPA uC notification
|
||||||
|
* * @data: IPA context
|
||||||
|
*
|
||||||
|
* This function is called when a resource manager event is received
|
||||||
|
* from firmware in interrupt context. This function will defer the
|
||||||
|
* handling to the OL RX thread
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void wlan_ipa_uc_rm_notify_defer(void *data)
|
||||||
|
{
|
||||||
|
struct wlan_ipa_priv *ipa_ctx = data;
|
||||||
|
qdf_ipa_rm_event_t event;
|
||||||
|
struct uc_rm_work_struct *uc_rm_work = &ipa_ctx->uc_rm_work;
|
||||||
|
|
||||||
|
event = uc_rm_work->event;
|
||||||
|
|
||||||
|
wlan_ipa_uc_rm_notify_handler(ipa_ctx, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_ipa_wake_lock_timer_func() - Wake lock work handler
|
||||||
|
* @data: IPA context
|
||||||
|
*
|
||||||
|
* When IPA resources are released in wlan_ipa_wdi_rm_try_release() we do
|
||||||
|
* not want to immediately release the wake lock since the system
|
||||||
|
* would then potentially try to suspend when there is a healthy data
|
||||||
|
* rate. Deferred work is scheduled and this function handles the
|
||||||
|
* work. When this function is called, if the IPA resource is still
|
||||||
|
* released then we release the wake lock.
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void wlan_ipa_wake_lock_timer_func(void *data)
|
||||||
|
{
|
||||||
|
struct wlan_ipa_priv *ipa_ctx = data;
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&ipa_ctx->rm_lock);
|
||||||
|
|
||||||
|
if (ipa_ctx->rm_state != WLAN_IPA_RM_RELEASED)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
ipa_ctx->wake_lock_released = true;
|
||||||
|
qdf_wake_lock_release(&ipa_ctx->wake_lock,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_IPA);
|
||||||
|
|
||||||
|
end:
|
||||||
|
qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_IPA_WDI_UNIFIED_API
|
||||||
|
QDF_STATUS wlan_ipa_wdi_setup_rm(struct wlan_ipa_priv *ipa_ctx)
|
||||||
|
{
|
||||||
|
qdf_ipa_rm_create_params_t create_params;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!wlan_ipa_is_rm_enabled(ipa_ctx->config))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
qdf_create_work(0, &ipa_ctx->uc_rm_work.work,
|
||||||
|
wlan_ipa_uc_rm_notify_defer, ipa_ctx);
|
||||||
|
qdf_mem_set(&create_params, 0, sizeof(create_params));
|
||||||
|
create_params.name = QDF_IPA_RM_RESOURCE_WLAN_PROD;
|
||||||
|
create_params.reg_params.user_data = ipa_ctx;
|
||||||
|
create_params.reg_params.notify_cb = wlan_ipa_rm_notify;
|
||||||
|
create_params.floor_voltage = QDF_IPA_VOLTAGE_LEVEL;
|
||||||
|
|
||||||
|
ret = qdf_ipa_rm_create_resource(&create_params);
|
||||||
|
if (ret) {
|
||||||
|
ipa_err("Create RM resource failed: %d", ret);
|
||||||
|
goto setup_rm_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_mem_set(&create_params, 0, sizeof(create_params));
|
||||||
|
create_params.name = QDF_IPA_RM_RESOURCE_WLAN_CONS;
|
||||||
|
create_params.request_resource = wlan_ipa_rm_cons_request;
|
||||||
|
create_params.release_resource = wlan_ipa_rm_cons_release;
|
||||||
|
create_params.floor_voltage = QDF_IPA_VOLTAGE_LEVEL;
|
||||||
|
|
||||||
|
ret = qdf_ipa_rm_create_resource(&create_params);
|
||||||
|
if (ret) {
|
||||||
|
ipa_err("Create RM CONS resource failed: %d", ret);
|
||||||
|
goto delete_prod;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_ipa_rm_add_dependency(QDF_IPA_RM_RESOURCE_WLAN_PROD,
|
||||||
|
QDF_IPA_RM_RESOURCE_APPS_CONS);
|
||||||
|
|
||||||
|
ret = qdf_ipa_rm_inactivity_timer_init(QDF_IPA_RM_RESOURCE_WLAN_PROD,
|
||||||
|
WLAN_IPA_RX_INACTIVITY_MSEC_DELAY);
|
||||||
|
if (ret) {
|
||||||
|
ipa_err("Timer init failed: %d", ret);
|
||||||
|
goto timer_init_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_wake_lock_create(&ipa_ctx->wake_lock, "wlan_ipa");
|
||||||
|
qdf_create_delayed_work(&ipa_ctx->wake_lock_work,
|
||||||
|
wlan_ipa_wake_lock_timer_func, ipa_ctx);
|
||||||
|
qdf_spinlock_create(&ipa_ctx->rm_lock);
|
||||||
|
ipa_ctx->rm_state = WLAN_IPA_RM_RELEASED;
|
||||||
|
ipa_ctx->wake_lock_released = true;
|
||||||
|
qdf_atomic_set(&ipa_ctx->tx_ref_cnt, 0);
|
||||||
|
|
||||||
|
return QDF_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
timer_init_failed:
|
||||||
|
qdf_ipa_rm_delete_resource(QDF_IPA_RM_RESOURCE_APPS_CONS);
|
||||||
|
|
||||||
|
delete_prod:
|
||||||
|
qdf_ipa_rm_delete_resource(QDF_IPA_RM_RESOURCE_WLAN_PROD);
|
||||||
|
|
||||||
|
setup_rm_fail:
|
||||||
|
return QDF_STATUS_E_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlan_ipa_wdi_destroy_rm(struct wlan_ipa_priv *ipa_ctx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!wlan_ipa_is_rm_enabled(ipa_ctx->config))
|
||||||
|
return;
|
||||||
|
|
||||||
|
qdf_cancel_delayed_work(&ipa_ctx->wake_lock_work);
|
||||||
|
qdf_wake_lock_destroy(&ipa_ctx->wake_lock);
|
||||||
|
qdf_cancel_work(&ipa_ctx->uc_rm_work.work);
|
||||||
|
qdf_spinlock_destroy(&ipa_ctx->rm_lock);
|
||||||
|
|
||||||
|
ipa_rm_inactivity_timer_destroy(QDF_IPA_RM_RESOURCE_WLAN_PROD);
|
||||||
|
|
||||||
|
ret = qdf_ipa_rm_delete_resource(QDF_IPA_RM_RESOURCE_WLAN_CONS);
|
||||||
|
if (ret)
|
||||||
|
ipa_err("RM CONS resource delete failed %d", ret);
|
||||||
|
|
||||||
|
ret = qdf_ipa_rm_delete_resource(QDF_IPA_RM_RESOURCE_WLAN_PROD);
|
||||||
|
if (ret)
|
||||||
|
ipa_err("RM PROD resource delete failed %d", ret);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IPA_WDI_UNIFIED_API */
|
Loading…
Reference in New Issue
Block a user