diff --git a/umac/p2p/core/src/wlan_p2p_main.c b/umac/p2p/core/src/wlan_p2p_main.c index db7c91351502..105449f580de 100644 --- a/umac/p2p/core/src/wlan_p2p_main.c +++ b/umac/p2p/core/src/wlan_p2p_main.c @@ -57,6 +57,10 @@ static char *p2p_get_cmd_type_str(enum p2p_cmd_type cmd_type) return "P2P mgmt tx request"; case P2P_MGMT_TX_CANCEL: return "P2P cancel mgmt tx request"; + case P2P_CLEANUP_ROC: + return "P2P cleanup roc"; + case P2P_CLEANUP_TX: + return "P2P cleanup tx"; default: return "Invalid P2P command"; } @@ -565,8 +569,8 @@ static QDF_STATUS p2p_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg) } /* clean up queue of p2p psoc private object */ - p2p_cleanup_tx_queue(p2p_soc_obj); - p2p_cleanup_roc_queue(p2p_soc_obj); + p2p_cleanup_tx_sync(p2p_soc_obj, NULL); + p2p_cleanup_roc_sync(p2p_soc_obj, NULL); p2p_debug("handle suspend complete"); @@ -818,7 +822,19 @@ QDF_STATUS p2p_psoc_object_open(struct wlan_objmgr_psoc *soc) 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; + goto fail_cancel_roc; + } + + status = qdf_event_create(&p2p_soc_obj->cleanup_roc_done); + if (status != QDF_STATUS_SUCCESS) { + p2p_err("failed to create cleanup roc done event"); + goto fail_cleanup_roc; + } + + status = qdf_event_create(&p2p_soc_obj->cleanup_tx_done); + if (status != QDF_STATUS_SUCCESS) { + p2p_err("failed to create cleanup roc done event"); + goto fail_cleanup_tx; } qdf_runtime_lock_init(&p2p_soc_obj->roc_runtime_lock); @@ -830,7 +846,13 @@ QDF_STATUS p2p_psoc_object_open(struct wlan_objmgr_psoc *soc) return QDF_STATUS_SUCCESS; -fail_event: +fail_cleanup_tx: + qdf_event_destroy(&p2p_soc_obj->cleanup_roc_done); + +fail_cleanup_roc: + qdf_event_destroy(&p2p_soc_obj->cancel_roc_done); + +fail_cancel_roc: 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); @@ -857,6 +879,8 @@ QDF_STATUS p2p_psoc_object_close(struct wlan_objmgr_psoc *soc) p2p_unregister_pmo_handler(); qdf_idr_destroy(&p2p_soc_obj->p2p_idr); qdf_runtime_lock_deinit(&p2p_soc_obj->roc_runtime_lock); + qdf_event_destroy(&p2p_soc_obj->cleanup_tx_done); + qdf_event_destroy(&p2p_soc_obj->cleanup_roc_done); 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); @@ -948,8 +972,8 @@ QDF_STATUS p2p_psoc_stop(struct wlan_objmgr_psoc *soc) p2p_mgmt_rx_action_ops(soc, false); /* clean up queue of p2p psoc private object */ - p2p_cleanup_tx_queue(p2p_soc_obj); - p2p_cleanup_roc_queue(p2p_soc_obj); + p2p_cleanup_tx_sync(p2p_soc_obj, NULL); + p2p_cleanup_roc_sync(p2p_soc_obj, NULL); /* unrgister scan request id*/ ucfg_scan_unregister_requester(soc, p2p_soc_obj->scan_req_id); @@ -1005,6 +1029,18 @@ QDF_STATUS p2p_process_cmd(struct scheduler_msg *msg) msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case P2P_CLEANUP_ROC: + status = p2p_process_cleanup_roc_queue( + (struct p2p_cleanup_param *) + msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; + case P2P_CLEANUP_TX: + status = p2p_process_cleanup_tx_queue( + (struct p2p_cleanup_param *) + msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; default: p2p_err("drop unexpected message received %d", msg->type); diff --git a/umac/p2p/core/src/wlan_p2p_main.h b/umac/p2p/core/src/wlan_p2p_main.h index 013505f652eb..2e2beecd67f8 100644 --- a/umac/p2p/core/src/wlan_p2p_main.h +++ b/umac/p2p/core/src/wlan_p2p_main.h @@ -65,12 +65,16 @@ struct tx_action_context; * @P2P_CANCEL_ROC_REQ: Cancel P2P roc request * @P2P_MGMT_TX: P2P tx action frame request * @P2P_MGMT_TX_CANCEL: Cancel tx action frame request + * @P2P_CLEANUP_ROC: Cleanup roc queue + * @P2P_CLEANUP_TX: Cleanup tx mgmt queue */ enum p2p_cmd_type { P2P_ROC_REQ = 0, P2P_CANCEL_ROC_REQ, P2P_MGMT_TX, P2P_MGMT_TX_CANCEL, + P2P_CLEANUP_ROC, + P2P_CLEANUP_TX, }; /** @@ -92,13 +96,13 @@ enum p2p_event_type { /** * struct p2p_tx_conf_event - p2p tx confirm event * @p2p_soc_obj: p2p soc private object - * @tx_cnf: p2p tx confirm structure - * @tx_ctx: tx context + * @buf: buffer address + * @status: tx status */ struct p2p_tx_conf_event { struct p2p_soc_priv_obj *p2p_soc_obj; - struct p2p_tx_cnf *tx_cnf; - struct tx_action_context *tx_ctx; + qdf_nbuf_t nbuf; + uint32_t status; }; /** @@ -167,6 +171,8 @@ enum p2p_connection_status { * @start_param: Start parameters, include callbacks and user * data to HDD * @cancel_roc_done: Cancel roc done event + * @cleanup_roc_done: Cleanup roc done event + * @cleanup_tx_done: Cleanup tx done event * @roc_runtime_lock: Runtime lock for roc request * @p2p_cb: Callbacks to protocol stack * @cur_roc_vdev_id: Vdev id of current roc @@ -181,6 +187,8 @@ struct p2p_soc_priv_obj { wlan_scan_requester scan_req_id; struct p2p_start_param *start_param; qdf_event_t cancel_roc_done; + qdf_event_t cleanup_roc_done; + qdf_event_t cleanup_tx_done; qdf_runtime_lock_t roc_runtime_lock; struct p2p_protocol_callbacks p2p_cb; uint32_t cur_roc_vdev_id; diff --git a/umac/p2p/core/src/wlan_p2p_off_chan_tx.c b/umac/p2p/core/src/wlan_p2p_off_chan_tx.c index f50b0db93fb7..c50a32b07124 100644 --- a/umac/p2p/core/src/wlan_p2p_off_chan_tx.c +++ b/umac/p2p/core/src/wlan_p2p_off_chan_tx.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "wlan_p2p_public_struct.h" #include "wlan_p2p_tgt_api.h" #include "wlan_p2p_ucfg_api.h" @@ -1649,10 +1650,68 @@ QDF_STATUS p2p_ready_to_tx_frame(struct p2p_soc_priv_obj *p2p_soc_obj, return status; } -QDF_STATUS p2p_cleanup_tx_queue(struct p2p_soc_priv_obj *p2p_soc_obj) +QDF_STATUS p2p_cleanup_tx_sync( + struct p2p_soc_priv_obj *p2p_soc_obj, + struct wlan_objmgr_vdev *vdev) +{ + struct scheduler_msg msg = {0}; + struct p2p_cleanup_param *param; + QDF_STATUS status; + uint32_t vdev_id; + + if (!p2p_soc_obj) { + p2p_err("p2p soc context is NULL"); + return QDF_STATUS_E_FAILURE; + } + + p2p_debug("p2p_soc_obj:%pK, vdev:%pK", p2p_soc_obj, vdev); + param = qdf_mem_malloc(sizeof(*param)); + if (!param) { + p2p_err("failed to allocate cleanup param"); + return QDF_STATUS_E_NOMEM; + } + + param->p2p_soc_obj = p2p_soc_obj; + if (vdev) + vdev_id = (uint32_t)wlan_vdev_get_id(vdev); + else + vdev_id = P2P_INVALID_VDEV_ID; + param->vdev_id = vdev_id; + qdf_event_reset(&p2p_soc_obj->cleanup_tx_done); + msg.type = P2P_CLEANUP_TX; + msg.bodyptr = param; + msg.callback = p2p_process_cmd; + status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg); + if (status != QDF_STATUS_SUCCESS) { + p2p_err("failed to post message"); + qdf_mem_free(param); + return status; + } + + status = qdf_wait_single_event( + &p2p_soc_obj->cleanup_tx_done, + P2P_WAIT_CLEANUP_ROC); + + if (status != QDF_STATUS_SUCCESS) + p2p_err("wait for cleanup tx timeout, %d", status); + + return status; +} + +QDF_STATUS p2p_process_cleanup_tx_queue(struct p2p_cleanup_param *param) { struct tx_action_context *curr_tx_ctx; qdf_list_node_t *p_node; + struct p2p_soc_priv_obj *p2p_soc_obj; + uint32_t vdev_id; + + if (!param || !(param->p2p_soc_obj)) { + p2p_err("Invalid cleanup param"); + return QDF_STATUS_E_FAILURE; + } + + p2p_soc_obj = param->p2p_soc_obj; + vdev_id = param->vdev_id; p2p_debug("clean up tx queue wait for roc, size:%d", qdf_list_size(&p2p_soc_obj->tx_q_roc)); @@ -1661,9 +1720,12 @@ QDF_STATUS p2p_cleanup_tx_queue(struct p2p_soc_priv_obj *p2p_soc_obj) QDF_STATUS_SUCCESS) { curr_tx_ctx = qdf_container_of(p_node, struct tx_action_context, node); - p2p_send_tx_conf(curr_tx_ctx, false); - qdf_mem_free(curr_tx_ctx->buf); - qdf_mem_free(curr_tx_ctx); + if ((vdev_id == P2P_INVALID_VDEV_ID) || + (vdev_id == curr_tx_ctx->vdev_id)) { + p2p_send_tx_conf(curr_tx_ctx, false); + qdf_mem_free(curr_tx_ctx->buf); + qdf_mem_free(curr_tx_ctx); + } } p2p_debug("clean up tx queue wait for ack, size:%d", @@ -1672,12 +1734,17 @@ QDF_STATUS p2p_cleanup_tx_queue(struct p2p_soc_priv_obj *p2p_soc_obj) QDF_STATUS_SUCCESS) { curr_tx_ctx = qdf_container_of(p_node, struct tx_action_context, node); - p2p_disable_tx_timer(curr_tx_ctx); - p2p_send_tx_conf(curr_tx_ctx, false); - qdf_mem_free(curr_tx_ctx->buf); - qdf_mem_free(curr_tx_ctx); + if ((vdev_id == P2P_INVALID_VDEV_ID) || + (vdev_id == curr_tx_ctx->vdev_id)) { + p2p_disable_tx_timer(curr_tx_ctx); + p2p_send_tx_conf(curr_tx_ctx, false); + qdf_mem_free(curr_tx_ctx->buf); + qdf_mem_free(curr_tx_ctx); + } } + qdf_event_set(&p2p_soc_obj->cleanup_tx_done); + return QDF_STATUS_SUCCESS; } @@ -1843,36 +1910,48 @@ QDF_STATUS p2p_process_mgmt_tx_cancel( QDF_STATUS p2p_process_mgmt_tx_ack_cnf( struct p2p_tx_conf_event *tx_cnf_event) { - struct p2p_tx_cnf *tx_cnf; + struct p2p_tx_cnf tx_cnf; + struct tx_action_context *tx_ctx; struct p2p_soc_priv_obj *p2p_soc_obj; struct p2p_start_param *start_param; p2p_soc_obj = tx_cnf_event->p2p_soc_obj; - tx_cnf = tx_cnf_event->tx_cnf; if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) { + qdf_nbuf_free(tx_cnf_event->nbuf); p2p_err("Invalid p2p soc object or start parameters"); - qdf_mem_free(tx_cnf); return QDF_STATUS_E_INVAL; } + tx_ctx = p2p_find_tx_ctx_by_nbuf(p2p_soc_obj, tx_cnf_event->nbuf); + qdf_nbuf_free(tx_cnf_event->nbuf); + if (!tx_ctx) { + p2p_err("can't find tx_ctx, tx ack comes late"); + return QDF_STATUS_SUCCESS; + } + + tx_cnf.vdev_id = tx_ctx->vdev_id; + tx_cnf.action_cookie = (uint64_t)tx_ctx->id; + tx_cnf.buf = tx_ctx->buf; + tx_cnf.buf_len = tx_ctx->buf_len; + tx_cnf.status = tx_cnf_event->status; + p2p_debug("soc:%pK, vdev_id:%d, action_cookie:%llx, len:%d, status:%d, buf:%pK", - p2p_soc_obj->soc, tx_cnf->vdev_id, - tx_cnf->action_cookie, tx_cnf->buf_len, - tx_cnf->status, tx_cnf->buf); + p2p_soc_obj->soc, tx_cnf.vdev_id, + tx_cnf.action_cookie, tx_cnf.buf_len, + tx_cnf.status, tx_cnf.buf); /* disable tx timer */ - p2p_disable_tx_timer(tx_cnf_event->tx_ctx); + p2p_disable_tx_timer(tx_ctx); start_param = p2p_soc_obj->start_param; if (start_param->tx_cnf_cb) start_param->tx_cnf_cb(start_param->tx_cnf_cb_data, - tx_cnf); + &tx_cnf); else p2p_debug("Got tx conf, but no valid up layer callback"); - p2p_remove_tx_context(tx_cnf_event->tx_ctx); - qdf_mem_free(tx_cnf); + p2p_remove_tx_context(tx_ctx); return QDF_STATUS_SUCCESS; } diff --git a/umac/p2p/core/src/wlan_p2p_off_chan_tx.h b/umac/p2p/core/src/wlan_p2p_off_chan_tx.h index 19287c3fedef..b7bb89876546 100644 --- a/umac/p2p/core/src/wlan_p2p_off_chan_tx.h +++ b/umac/p2p/core/src/wlan_p2p_off_chan_tx.h @@ -155,7 +155,6 @@ struct p2p_frame_info { * @off_chan: Is this off channel tx * @no_cck: Required cck or not * @no_ack: Required ack or not - * @is_deleting: Received tx ack and waiting for deleting * @duration: Duration for the RoC * @tx_timer: RoC timer * @frame_info: Frame type information @@ -173,7 +172,6 @@ struct tx_action_context { bool off_chan; bool no_cck; bool no_ack; - bool is_deleting; uint32_t duration; qdf_mc_timer_t tx_timer; struct p2p_frame_info frame_info; @@ -205,14 +203,29 @@ QDF_STATUS p2p_ready_to_tx_frame(struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie); /** - * p2p_cleanup_tx_queue() - cleanup tx queue - * @p2p_soc_obj: p2p soc private object + * p2p_cleanup_tx_sync() - Cleanup tx queue + * @p2p_soc_obj: p2p psoc private object + * @vdev: vdev object + * + * This function cleanup tx context in queue until cancellation done. + * To avoid deadlock, don't call from scheduler thread. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS p2p_cleanup_tx_sync( + struct p2p_soc_priv_obj *p2p_soc_obj, + struct wlan_objmgr_vdev *vdev); + +/** + * p2p_process_cleanup_tx_queue() - process the message to cleanup tx + * @param: pointer to cleanup parameters * * This function cleanup wait for roc queue and wait for ack queue. * * Return: QDF_STATUS_SUCCESS - in case of success */ -QDF_STATUS p2p_cleanup_tx_queue(struct p2p_soc_priv_obj *p2p_soc_obj); +QDF_STATUS p2p_process_cleanup_tx_queue( + struct p2p_cleanup_param *param); /** * p2p_process_mgmt_tx() - Process mgmt frame tx request diff --git a/umac/p2p/core/src/wlan_p2p_roc.c b/umac/p2p/core/src/wlan_p2p_roc.c index 3650af9d73e5..1ff391e4b4ea 100644 --- a/umac/p2p/core/src/wlan_p2p_roc.c +++ b/umac/p2p/core/src/wlan_p2p_roc.c @@ -652,15 +652,73 @@ QDF_STATUS p2p_restart_roc_timer(struct p2p_roc_context *roc_ctx) return status; } -QDF_STATUS p2p_cleanup_roc_queue(struct p2p_soc_priv_obj *p2p_soc_obj) +QDF_STATUS p2p_cleanup_roc_sync( + struct p2p_soc_priv_obj *p2p_soc_obj, + struct wlan_objmgr_vdev *vdev) { + struct scheduler_msg msg = {0}; + struct p2p_cleanup_param *param; + QDF_STATUS status; + uint32_t vdev_id; + + if (!p2p_soc_obj) { + p2p_err("p2p soc context is NULL"); + return QDF_STATUS_E_FAILURE; + } + + p2p_debug("p2p_soc_obj:%pK, vdev:%pK", p2p_soc_obj, vdev); + param = qdf_mem_malloc(sizeof(*param)); + if (!param) { + p2p_err("failed to allocate cleanup param"); + return QDF_STATUS_E_NOMEM; + } + + param->p2p_soc_obj = p2p_soc_obj; + if (vdev) + vdev_id = (uint32_t)wlan_vdev_get_id(vdev); + else + vdev_id = P2P_INVALID_VDEV_ID; + param->vdev_id = vdev_id; + qdf_event_reset(&p2p_soc_obj->cleanup_roc_done); + msg.type = P2P_CLEANUP_ROC; + msg.bodyptr = param; + msg.callback = p2p_process_cmd; + status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg); + if (status != QDF_STATUS_SUCCESS) { + p2p_err("failed to post message"); + qdf_mem_free(param); + return status; + } + + status = qdf_wait_single_event( + &p2p_soc_obj->cleanup_roc_done, + P2P_WAIT_CLEANUP_ROC); + + if (status != QDF_STATUS_SUCCESS) + p2p_err("wait for cleanup roc timeout, %d", status); + + return status; +} + +QDF_STATUS p2p_process_cleanup_roc_queue( + struct p2p_cleanup_param *param) +{ + uint32_t vdev_id; + QDF_STATUS status, ret; struct p2p_roc_context *roc_ctx; qdf_list_node_t *p_node; - QDF_STATUS status, ret; + struct p2p_soc_priv_obj *p2p_soc_obj; - p2p_debug("clean up idle roc request, roc queue size:%d", - qdf_list_size(&p2p_soc_obj->roc_q)); + if (!param || !(param->p2p_soc_obj)) { + p2p_err("Invalid cleanup param"); + return QDF_STATUS_E_FAILURE; + } + p2p_soc_obj = param->p2p_soc_obj; + vdev_id = param->vdev_id; + + p2p_debug("clean up idle roc request, roc queue size:%d, vdev id:%d", + qdf_list_size(&p2p_soc_obj->roc_q), vdev_id); status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node); while (QDF_IS_STATUS_SUCCESS(status)) { roc_ctx = qdf_container_of(p_node, @@ -674,13 +732,14 @@ QDF_STATUS p2p_cleanup_roc_queue(struct p2p_soc_priv_obj *p2p_soc_obj) roc_ctx->roc_type, roc_ctx->roc_state); status = qdf_list_peek_next(&p2p_soc_obj->roc_q, p_node, &p_node); - if (roc_ctx->roc_state == ROC_STATE_IDLE) { + if ((roc_ctx->roc_state == ROC_STATE_IDLE) && + ((vdev_id == P2P_INVALID_VDEV_ID) || + (vdev_id == roc_ctx->vdev_id))) { ret = qdf_list_remove_node( &p2p_soc_obj->roc_q, (qdf_list_node_t *)roc_ctx); if (ret == QDF_STATUS_SUCCESS) - p2p_destroy_roc_ctx(roc_ctx, - true, false); + qdf_mem_free(roc_ctx); else p2p_err("Failed to remove roc ctx from queue"); } @@ -693,80 +752,17 @@ QDF_STATUS p2p_cleanup_roc_queue(struct p2p_soc_priv_obj *p2p_soc_obj) roc_ctx = qdf_container_of(p_node, struct p2p_roc_context, node); - p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx_ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d", - roc_ctx->p2p_soc_obj, roc_ctx, roc_ctx->vdev_id, - roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan, - roc_ctx->phy_mode, roc_ctx->duration, - roc_ctx->roc_type, roc_ctx->roc_state); + p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d", + roc_ctx->p2p_soc_obj, roc_ctx, roc_ctx->vdev_id, + roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan, + roc_ctx->phy_mode, roc_ctx->duration, + roc_ctx->roc_type, roc_ctx->roc_state); status = qdf_list_peek_next(&p2p_soc_obj->roc_q, p_node, &p_node); - if (roc_ctx->roc_state != ROC_STATE_IDLE) { - if (roc_ctx->roc_state != - ROC_STATE_CANCEL_IN_PROG) - p2p_execute_cancel_roc_req(roc_ctx); - - ret = qdf_wait_single_event( - &p2p_soc_obj->cancel_roc_done, - P2P_WAIT_CANCEL_ROC); - p2p_debug("roc cancellation done, return:%d", ret); - } - } - - return QDF_STATUS_SUCCESS; -} - -QDF_STATUS p2p_cleanup_roc_by_vdev( - struct p2p_soc_priv_obj *p2p_soc_obj, uint32_t vdev_id) -{ - QDF_STATUS status, ret; - struct p2p_roc_context *roc_ctx; - qdf_list_node_t *p_node; - - p2p_info("clean up idle roc request, roc queue size:%d, vdev id:%d", - qdf_list_size(&p2p_soc_obj->roc_q), vdev_id); - status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node); - while (QDF_IS_STATUS_SUCCESS(status)) { - roc_ctx = qdf_container_of(p_node, - struct p2p_roc_context, node); - - p2p_info("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d", - roc_ctx->p2p_soc_obj, roc_ctx, - roc_ctx->vdev_id, roc_ctx->scan_id, - roc_ctx->tx_ctx, roc_ctx->chan, - roc_ctx->phy_mode, roc_ctx->duration, - roc_ctx->roc_type, roc_ctx->roc_state); - status = qdf_list_peek_next(&p2p_soc_obj->roc_q, - p_node, &p_node); - if (roc_ctx->roc_state == ROC_STATE_IDLE && - roc_ctx->vdev_id == vdev_id) { - ret = qdf_list_remove_node( - &p2p_soc_obj->roc_q, - (qdf_list_node_t *)roc_ctx); - if (ret == QDF_STATUS_SUCCESS) - qdf_mem_free(roc_ctx); - else - p2p_err("Failed to remove roc ctx from queue"); - } - } - - p2p_info("clean up started roc request, roc queue size:%d", - qdf_list_size(&p2p_soc_obj->roc_q)); - status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node); - while (QDF_IS_STATUS_SUCCESS(status)) { - roc_ctx = qdf_container_of(p_node, - struct p2p_roc_context, node); - - p2p_info("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d", - roc_ctx->p2p_soc_obj, roc_ctx, roc_ctx->vdev_id, - roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan, - roc_ctx->phy_mode, roc_ctx->duration, - roc_ctx->roc_type, roc_ctx->roc_state); - - status = qdf_list_peek_next(&p2p_soc_obj->roc_q, - p_node, &p_node); - if (roc_ctx->roc_state != ROC_STATE_IDLE && - roc_ctx->vdev_id == vdev_id) { + if ((roc_ctx->roc_state != ROC_STATE_IDLE) && + ((vdev_id == P2P_INVALID_VDEV_ID) || + (vdev_id == roc_ctx->vdev_id))) { if (roc_ctx->roc_state != ROC_STATE_CANCEL_IN_PROG) p2p_execute_cancel_roc_req(roc_ctx); @@ -778,6 +774,8 @@ QDF_STATUS p2p_cleanup_roc_by_vdev( } } + qdf_event_set(&p2p_soc_obj->cleanup_roc_done); + return QDF_STATUS_SUCCESS; } diff --git a/umac/p2p/core/src/wlan_p2p_roc.h b/umac/p2p/core/src/wlan_p2p_roc.h index fa40e7aa885d..3ccff8c17297 100644 --- a/umac/p2p/core/src/wlan_p2p_roc.h +++ b/umac/p2p/core/src/wlan_p2p_roc.h @@ -29,6 +29,7 @@ #define P2P_EVENT_PROPAGATE_TIME 10 #define P2P_WAIT_CANCEL_ROC 1000 +#define P2P_WAIT_CLEANUP_ROC 2000 #ifdef QCA_WIFI_3_0_EMU #define P2P_ROC_DURATION_MULTI_GO_PRESENT 2 @@ -111,6 +112,16 @@ struct cancel_roc_context { uint64_t cookie; }; +/** + * struct p2p_cleanup_param - p2p cleanup parameters + * @p2p_soc_obj: Pointer to SoC global p2p private object + * @vdev_id: vdev id + */ +struct p2p_cleanup_param { + struct p2p_soc_priv_obj *p2p_soc_obj; + uint32_t vdev_id; +}; + /** * p2p_mgmt_rx_action_ops() - register or unregister rx action callback * @psoc: psoc object @@ -162,29 +173,31 @@ struct p2p_roc_context *p2p_find_roc_by_tx_ctx( QDF_STATUS p2p_restart_roc_timer(struct p2p_roc_context *roc_ctx); /** - * p2p_cleanup_roc_queue() - Cleanup roc context in queue + * p2p_cleanup_roc_sync() - Cleanup roc context in queue * @p2p_soc_obj: p2p psoc private object + * @vdev: vdev object * * This function cleanup roc context in queue, include the roc - * context in progressing. + * context in progressing until cancellation done. To avoid deadlock, + * don't call from scheduler thread. * * Return: QDF_STATUS_SUCCESS - in case of success */ -QDF_STATUS p2p_cleanup_roc_queue( - struct p2p_soc_priv_obj *p2p_soc_obj); +QDF_STATUS p2p_cleanup_roc_sync( + struct p2p_soc_priv_obj *p2p_soc_obj, + struct wlan_objmgr_vdev *vdev); /** - * p2p_cleanup_roc_by_vdev() - Cleanup roc context by vdev id - * @p2p_soc_obj: p2p psoc private object - * @vdev_id: vdev id + * p2p_process_cleanup_roc_queue() - process the message to cleanup roc + * @param: pointer to cleanup parameters * - * This function cleanup roc context by vdev id, include the roc - * context in progressing. + * This function process the message to cleanup roc context in queue, + * include the roc context in progressing. * * Return: QDF_STATUS_SUCCESS - in case of success */ -QDF_STATUS p2p_cleanup_roc_by_vdev( - struct p2p_soc_priv_obj *p2p_soc_obj, uint32_t vdev_id); +QDF_STATUS p2p_process_cleanup_roc_queue( + struct p2p_cleanup_param *param); /** * p2p_process_roc_req() - Process roc request diff --git a/umac/p2p/dispatcher/src/wlan_p2p_tgt_api.c b/umac/p2p/dispatcher/src/wlan_p2p_tgt_api.c index 50017d7f5688..17e289de96f9 100644 --- a/umac/p2p/dispatcher/src/wlan_p2p_tgt_api.c +++ b/umac/p2p/dispatcher/src/wlan_p2p_tgt_api.c @@ -123,11 +123,9 @@ QDF_STATUS tgt_p2p_mgmt_download_comp_cb(void *context, QDF_STATUS tgt_p2p_mgmt_ota_comp_cb(void *context, qdf_nbuf_t buf, uint32_t status, void *tx_compl_params) { - struct p2p_tx_cnf *tx_cnf; struct p2p_tx_conf_event *tx_conf_event; - struct p2p_soc_priv_obj *p2p_soc_obj; - struct tx_action_context *tx_ctx; struct scheduler_msg msg = {0}; + QDF_STATUS ret; p2p_debug("context:%pK, buf:%pK, status:%d, tx complete params:%pK", context, buf, status, tx_compl_params); @@ -137,19 +135,6 @@ QDF_STATUS tgt_p2p_mgmt_ota_comp_cb(void *context, qdf_nbuf_t buf, qdf_nbuf_free(buf); return QDF_STATUS_E_INVAL; } - p2p_soc_obj = (struct p2p_soc_priv_obj *)context; - tx_ctx = p2p_find_tx_ctx_by_nbuf(p2p_soc_obj, buf); - if (!tx_ctx) { - p2p_err("can't find tx_ctx, tx ack comes late"); - qdf_nbuf_free(buf); - return QDF_STATUS_E_FAULT; - } - - if (tx_ctx->is_deleting) { - p2p_info("Received duplicate tx ack"); - return QDF_STATUS_SUCCESS; - } - tx_ctx->is_deleting = true; tx_conf_event = qdf_mem_malloc(sizeof(*tx_conf_event)); if (!tx_conf_event) { @@ -158,26 +143,19 @@ QDF_STATUS tgt_p2p_mgmt_ota_comp_cb(void *context, qdf_nbuf_t buf, return QDF_STATUS_E_NOMEM; } - tx_cnf = qdf_mem_malloc(sizeof(*tx_cnf)); - if (!tx_cnf) { - p2p_err("Failed to allocate tx cnf"); - qdf_nbuf_free(buf); - return QDF_STATUS_E_NOMEM; - } - - qdf_nbuf_free(buf); - tx_cnf->vdev_id = tx_ctx->vdev_id; - tx_cnf->action_cookie = (uint64_t)tx_ctx->id; - tx_cnf->buf = tx_ctx->buf; - tx_cnf->buf_len = tx_ctx->buf_len; - tx_cnf->status = status; - tx_conf_event->p2p_soc_obj = p2p_soc_obj; - tx_conf_event->tx_cnf = tx_cnf; - tx_conf_event->tx_ctx = tx_ctx; + tx_conf_event->status = status; + tx_conf_event->nbuf = buf; + tx_conf_event->p2p_soc_obj = (struct p2p_soc_priv_obj *)context; msg.type = P2P_EVENT_MGMT_TX_ACK_CNF; msg.bodyptr = tx_conf_event; msg.callback = p2p_process_evt; - scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg); + ret = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg); + if (ret != QDF_STATUS_SUCCESS) { + qdf_mem_free(tx_conf_event); + qdf_mem_free(buf); + p2p_err("failed to post message"); + return status; + } return QDF_STATUS_SUCCESS; } diff --git a/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c b/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c index 84366e846e16..efa74baba9de 100644 --- a/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c +++ b/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c @@ -211,9 +211,8 @@ QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc, QDF_STATUS ucfg_p2p_cleanup_roc(struct wlan_objmgr_vdev *vdev) { - struct wlan_objmgr_psoc *psoc; struct p2p_soc_priv_obj *p2p_soc_obj; - uint32_t vdev_id; + struct wlan_objmgr_psoc *psoc; p2p_debug("vdev:%pK", vdev); @@ -222,7 +221,6 @@ QDF_STATUS ucfg_p2p_cleanup_roc(struct wlan_objmgr_vdev *vdev) return QDF_STATUS_E_INVAL; } - vdev_id = (uint32_t)wlan_vdev_get_id(vdev); psoc = wlan_vdev_get_psoc(vdev); if (!psoc) { p2p_err("null psoc"); @@ -236,7 +234,7 @@ QDF_STATUS ucfg_p2p_cleanup_roc(struct wlan_objmgr_vdev *vdev) return QDF_STATUS_E_FAILURE; } - return p2p_cleanup_roc_by_vdev(p2p_soc_obj, vdev_id); + return p2p_cleanup_roc_sync(p2p_soc_obj, vdev); } QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc, @@ -293,7 +291,6 @@ QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc, tx_action->no_cck = mgmt_frm->no_cck; tx_action->no_ack = mgmt_frm->dont_wait_for_ack; tx_action->off_chan = mgmt_frm->off_chan; - tx_action->is_deleting = false; tx_action->buf = qdf_mem_malloc(tx_action->buf_len); if (!(tx_action->buf)) { p2p_err("Failed to allocate buffer for action frame");