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:
Wu Gao
2017-04-19 18:50:51 +08:00
committed by snandini
부모 cc21cb2e15
커밋 d5fc9c0b8e
4개의 변경된 파일156개의 추가작업 그리고 86개의 파일을 삭제

파일 보기

@@ -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;
}