mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 15:11:48 -04:00
qcacmn: Add runtime pm lock for P2P
Add runtime pm lock for remain on channel request in P2P component. Change-Id: Ic29c5edf9e9325d1f9b65d766385327b91b0d14a CRs-Fixed: 2036085
This commit is contained in:
parent
cc21cb2e15
commit
d5fc9c0b8e
4 changed files with 124 additions and 54 deletions
|
|
@ -456,6 +456,7 @@ QDF_STATUS p2p_component_deinit(void)
|
|||
|
||||
QDF_STATUS p2p_psoc_object_open(struct wlan_objmgr_psoc *soc)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj;
|
||||
|
||||
if (!soc) {
|
||||
|
|
@ -473,11 +474,25 @@ QDF_STATUS p2p_psoc_object_open(struct wlan_objmgr_psoc *soc)
|
|||
qdf_list_create(&p2p_soc_obj->roc_q, MAX_QUEUE_LENGTH);
|
||||
qdf_list_create(&p2p_soc_obj->tx_q_roc, MAX_QUEUE_LENGTH);
|
||||
qdf_list_create(&p2p_soc_obj->tx_q_ack, MAX_QUEUE_LENGTH);
|
||||
qdf_event_create(&p2p_soc_obj->cancel_roc_done);
|
||||
|
||||
status = qdf_event_create(&p2p_soc_obj->cancel_roc_done);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
p2p_err("failed to create cancel roc done event");
|
||||
goto fail_event;
|
||||
}
|
||||
p2p_soc_obj->roc_runtime_lock = qdf_runtime_lock_init(
|
||||
P2P_MODULE_NAME);
|
||||
|
||||
p2p_debug("p2p psoc object open successful");
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
fail_event:
|
||||
qdf_list_destroy(&p2p_soc_obj->tx_q_ack);
|
||||
qdf_list_destroy(&p2p_soc_obj->tx_q_roc);
|
||||
qdf_list_destroy(&p2p_soc_obj->roc_q);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS p2p_psoc_object_close(struct wlan_objmgr_psoc *soc)
|
||||
|
|
@ -496,6 +511,7 @@ QDF_STATUS p2p_psoc_object_close(struct wlan_objmgr_psoc *soc)
|
|||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
qdf_runtime_lock_deinit(p2p_soc_obj->roc_runtime_lock);
|
||||
qdf_event_destroy(&p2p_soc_obj->cancel_roc_done);
|
||||
qdf_list_destroy(&p2p_soc_obj->tx_q_ack);
|
||||
qdf_list_destroy(&p2p_soc_obj->tx_q_roc);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <qdf_types.h>
|
||||
#include <qdf_event.h>
|
||||
#include <qdf_list.h>
|
||||
#include <qdf_lock.h>
|
||||
|
||||
#define MAX_QUEUE_LENGTH 20
|
||||
#define P2P_NOA_ATTR_IND 0x1090
|
||||
|
|
@ -138,6 +139,7 @@ struct p2p_noa_event {
|
|||
* @start_param: Start parameters, include callbacks and user
|
||||
* data to HDD
|
||||
* @cancel_roc_done: Cancel roc done event
|
||||
* @roc_runtime_lock: Runtime lock for roc request
|
||||
*/
|
||||
struct p2p_soc_priv_obj {
|
||||
struct wlan_objmgr_psoc *soc;
|
||||
|
|
@ -147,6 +149,7 @@ struct p2p_soc_priv_obj {
|
|||
uint16_t scan_req_id;
|
||||
struct p2p_start_param *start_param;
|
||||
qdf_event_t cancel_roc_done;
|
||||
qdf_runtime_lock_t roc_runtime_lock;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -855,7 +855,6 @@ static QDF_STATUS p2p_roc_req_for_tx_action(
|
|||
status = p2p_process_roc_req(roc_ctx);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
p2p_err("request roc for tx action frrame fail");
|
||||
qdf_mem_free(roc_ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -246,83 +246,6 @@ static void p2p_roc_timeout(void *pdata)
|
|||
p2p_execute_cancel_roc_req(roc_ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* p2p_execute_roc_req() - Execute roc request
|
||||
* @roc_ctx: remain on channel request
|
||||
*
|
||||
* This function init roc timer, start scan and register mgmt rx
|
||||
* callbak.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - in case of success
|
||||
*/
|
||||
static QDF_STATUS p2p_execute_roc_req(struct p2p_roc_context *roc_ctx)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
uint32_t go_num;
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
|
||||
|
||||
p2p_debug("p2p soc obj:%p, roc ctx:%p, vdev_id:%d, scan_id:%d, cookie:%llx, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
|
||||
p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
|
||||
roc_ctx->scan_id, roc_ctx->cookie, roc_ctx->chan,
|
||||
roc_ctx->phy_mode, roc_ctx->duration,
|
||||
roc_ctx->roc_type, roc_ctx->roc_state);
|
||||
|
||||
status = qdf_mc_timer_init(&roc_ctx->roc_timer,
|
||||
QDF_TIMER_TYPE_SW, p2p_roc_timeout,
|
||||
p2p_soc_obj);
|
||||
if (status != QDF_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
roc_ctx->roc_state = ROC_STATE_REQUESTED;
|
||||
go_num = policy_mgr_mode_specific_connection_count(
|
||||
p2p_soc_obj->soc, PM_P2P_GO_MODE, NULL);
|
||||
p2p_debug("present go number:%d", go_num);
|
||||
if (go_num)
|
||||
roc_ctx->duration *= P2P_ROC_DURATION_MULTI_GO_PRESENT;
|
||||
else
|
||||
roc_ctx->duration *= P2P_ROC_DURATION_MULTI_GO_ABSENT;
|
||||
|
||||
status = p2p_scan_start(roc_ctx);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
p2p_err("Failed to start scan, status:%d", status);
|
||||
}
|
||||
status = p2p_mgmt_rx_ops(roc_ctx->p2p_soc_obj->soc, true);
|
||||
if (status != QDF_STATUS_SUCCESS)
|
||||
p2p_err("Failed to register mgmt rx callback, status:%d",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* p2p_find_roc_ctx() - Find out roc context by cookie
|
||||
* @p2p_soc_obj: p2p psoc private object
|
||||
* @cookie: cookie is the key to find out roc context
|
||||
*
|
||||
* This function find out roc context by cookie from p2p psoc private
|
||||
* object
|
||||
*
|
||||
* Return: Pointer to roc context - success
|
||||
* NULL - failure
|
||||
*/
|
||||
static struct p2p_roc_context *p2p_find_roc_ctx(
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie)
|
||||
{
|
||||
struct p2p_roc_context *curr_roc_ctx;
|
||||
qdf_list_node_t *tmp, *pos;
|
||||
|
||||
p2p_debug("p2p soc obj:%p, cookie:%llx", p2p_soc_obj, cookie);
|
||||
|
||||
list_for_each_safe(pos, tmp, &p2p_soc_obj->roc_q.anchor) {
|
||||
curr_roc_ctx = list_entry(pos, struct p2p_roc_context,
|
||||
node);
|
||||
if ((uintptr_t) curr_roc_ctx == cookie)
|
||||
return curr_roc_ctx;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* p2p_send_roc_event() - Send roc event
|
||||
* @roc_ctx: remain on channel request
|
||||
|
|
@ -366,6 +289,135 @@ static QDF_STATUS p2p_send_roc_event(
|
|||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* p2p_destroy_roc_ctx() - destroy roc ctx
|
||||
* @roc_ctx: remain on channel request
|
||||
* @up_layer_event: if send uplayer event
|
||||
* @in_roc_queue: if roc context in roc queue
|
||||
*
|
||||
* This function destroy roc context.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - in case of success
|
||||
*/
|
||||
static QDF_STATUS p2p_destroy_roc_ctx(struct p2p_roc_context *roc_ctx,
|
||||
bool up_layer_event, bool in_roc_queue)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
|
||||
|
||||
p2p_debug("p2p_soc_obj:%p, roc_ctx:%p, up_layer_event:%d, in_roc_queue:%d",
|
||||
p2p_soc_obj, roc_ctx, up_layer_event, in_roc_queue);
|
||||
|
||||
if (up_layer_event) {
|
||||
p2p_send_roc_event(roc_ctx, ROC_EVENT_READY_ON_CHAN);
|
||||
p2p_send_roc_event(roc_ctx, ROC_EVENT_COMPLETED);
|
||||
}
|
||||
|
||||
if (in_roc_queue) {
|
||||
status = qdf_list_remove_node(&p2p_soc_obj->roc_q,
|
||||
(qdf_list_node_t *)roc_ctx);
|
||||
if (QDF_STATUS_SUCCESS != status)
|
||||
p2p_err("Failed to remove roc req, status %d", status);
|
||||
}
|
||||
|
||||
qdf_mem_free(roc_ctx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* p2p_execute_roc_req() - Execute roc request
|
||||
* @roc_ctx: remain on channel request
|
||||
*
|
||||
* This function init roc timer, start scan and register mgmt rx
|
||||
* callbak.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - in case of success
|
||||
*/
|
||||
static QDF_STATUS p2p_execute_roc_req(struct p2p_roc_context *roc_ctx)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
uint32_t go_num;
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
|
||||
|
||||
p2p_debug("p2p soc obj:%p, roc ctx:%p, vdev_id:%d, scan_id:%d, cookie:%llx, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
|
||||
p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
|
||||
roc_ctx->scan_id, roc_ctx->cookie, roc_ctx->chan,
|
||||
roc_ctx->phy_mode, roc_ctx->duration,
|
||||
roc_ctx->roc_type, roc_ctx->roc_state);
|
||||
|
||||
/* prevent runtime suspend */
|
||||
qdf_runtime_pm_prevent_suspend(p2p_soc_obj->roc_runtime_lock);
|
||||
|
||||
status = qdf_mc_timer_init(&roc_ctx->roc_timer,
|
||||
QDF_TIMER_TYPE_SW, p2p_roc_timeout,
|
||||
p2p_soc_obj);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
p2p_err("failed to init roc timer, status:%d", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
roc_ctx->roc_state = ROC_STATE_REQUESTED;
|
||||
go_num = policy_mgr_mode_specific_connection_count(
|
||||
p2p_soc_obj->soc, PM_P2P_GO_MODE, NULL);
|
||||
p2p_debug("present go number:%d", go_num);
|
||||
if (go_num)
|
||||
roc_ctx->duration *= P2P_ROC_DURATION_MULTI_GO_PRESENT;
|
||||
else
|
||||
roc_ctx->duration *= P2P_ROC_DURATION_MULTI_GO_ABSENT;
|
||||
|
||||
status = p2p_scan_start(roc_ctx);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
qdf_mc_timer_destroy(&roc_ctx->roc_timer);
|
||||
p2p_err("Failed to start scan, status:%d", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
p2p_destroy_roc_ctx(roc_ctx, true, true);
|
||||
qdf_runtime_pm_allow_suspend(
|
||||
p2p_soc_obj->roc_runtime_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = p2p_mgmt_rx_ops(roc_ctx->p2p_soc_obj->soc, true);
|
||||
if (status != QDF_STATUS_SUCCESS)
|
||||
p2p_err("Failed to register mgmt rx callback, status:%d",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* p2p_find_roc_ctx() - Find out roc context by cookie
|
||||
* @p2p_soc_obj: p2p psoc private object
|
||||
* @cookie: cookie is the key to find out roc context
|
||||
*
|
||||
* This function find out roc context by cookie from p2p psoc private
|
||||
* object
|
||||
*
|
||||
* Return: Pointer to roc context - success
|
||||
* NULL - failure
|
||||
*/
|
||||
static struct p2p_roc_context *p2p_find_roc_ctx(
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie)
|
||||
{
|
||||
struct p2p_roc_context *curr_roc_ctx;
|
||||
qdf_list_node_t *tmp, *pos;
|
||||
|
||||
p2p_debug("p2p soc obj:%p, cookie:%llx", p2p_soc_obj, cookie);
|
||||
|
||||
list_for_each_safe(pos, tmp, &p2p_soc_obj->roc_q.anchor) {
|
||||
curr_roc_ctx = list_entry(pos, struct p2p_roc_context,
|
||||
node);
|
||||
if ((uintptr_t) curr_roc_ctx == cookie)
|
||||
return curr_roc_ctx;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* p2p_process_scan_start_evt() - Process scan start event
|
||||
* @roc_ctx: remain on channel request
|
||||
|
|
@ -450,6 +502,9 @@ static QDF_STATUS p2p_process_scan_complete_evt(
|
|||
roc_ctx->phy_mode, roc_ctx->duration,
|
||||
roc_ctx->roc_type, roc_ctx->roc_state);
|
||||
|
||||
/* allow runtime suspend */
|
||||
qdf_runtime_pm_allow_suspend(p2p_soc_obj->roc_runtime_lock);
|
||||
|
||||
if (QDF_TIMER_STATE_RUNNING ==
|
||||
qdf_mc_timer_get_current_state(&roc_ctx->roc_timer)) {
|
||||
status = qdf_mc_timer_stop(&roc_ctx->roc_timer);
|
||||
|
|
@ -469,11 +524,7 @@ static QDF_STATUS p2p_process_scan_complete_evt(
|
|||
status = p2p_send_roc_event(roc_ctx,
|
||||
ROC_EVENT_COMPLETED);
|
||||
|
||||
status = qdf_list_remove_node(&p2p_soc_obj->roc_q,
|
||||
(qdf_list_node_t *)roc_ctx);
|
||||
if (QDF_STATUS_SUCCESS != status)
|
||||
p2p_err("Failed to remove roc req, status %d", status);
|
||||
qdf_mem_free(roc_ctx);
|
||||
p2p_destroy_roc_ctx(roc_ctx, false, true);
|
||||
qdf_event_set(&p2p_soc_obj->cancel_roc_done);
|
||||
|
||||
size = qdf_list_size(&p2p_soc_obj->roc_q);
|
||||
|
|
@ -566,7 +617,8 @@ QDF_STATUS p2p_cleanup_roc_queue(struct p2p_soc_priv_obj *p2p_soc_obj)
|
|||
&p2p_soc_obj->roc_q,
|
||||
(qdf_list_node_t *)roc_ctx);
|
||||
if (status == QDF_STATUS_SUCCESS)
|
||||
qdf_mem_free(roc_ctx);
|
||||
p2p_destroy_roc_ctx(roc_ctx,
|
||||
true, false);
|
||||
else
|
||||
p2p_err("Failed to remove roc ctx from queue");
|
||||
}
|
||||
|
|
@ -617,7 +669,7 @@ QDF_STATUS p2p_process_roc_req(struct p2p_roc_context *roc_ctx)
|
|||
status = qdf_list_insert_back(&p2p_soc_obj->roc_q,
|
||||
&roc_ctx->node);
|
||||
if (QDF_STATUS_SUCCESS != status) {
|
||||
qdf_mem_free(roc_ctx);
|
||||
p2p_destroy_roc_ctx(roc_ctx, true, false);
|
||||
p2p_debug("Failed to insert roc req, status %d", status);
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue