From 2b1d323609637757035eb4e2973678272752d003 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Mon, 13 Aug 2018 10:54:28 +0800 Subject: [PATCH] qcacmn: Check and then remove tx context from queue It will remove the tx context firstly and then check whether need to be deleted, which cause tx context memory leak. So, check the tx context firstly, and then remove the tx context if need. Change-Id: Icfe72318ccdd580002d269ffa8082b7f5fa4a341 CRs-Fixed: 2291867 --- core/src/wlan_p2p_off_chan_tx.c | 44 +++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/core/src/wlan_p2p_off_chan_tx.c b/core/src/wlan_p2p_off_chan_tx.c index 6f02665f1a29..a03fe0127983 100644 --- a/core/src/wlan_p2p_off_chan_tx.c +++ b/core/src/wlan_p2p_off_chan_tx.c @@ -1704,6 +1704,7 @@ QDF_STATUS p2p_process_cleanup_tx_queue(struct p2p_cleanup_param *param) qdf_list_node_t *p_node; struct p2p_soc_priv_obj *p2p_soc_obj; uint32_t vdev_id; + QDF_STATUS status, ret; if (!param || !(param->p2p_soc_obj)) { p2p_err("Invalid cleanup param"); @@ -1713,34 +1714,51 @@ QDF_STATUS p2p_process_cleanup_tx_queue(struct p2p_cleanup_param *param) 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)); + p2p_debug("clean up tx queue wait for roc, size:%d, vdev_id:%d", + qdf_list_size(&p2p_soc_obj->tx_q_roc), vdev_id); - while (qdf_list_remove_front(&p2p_soc_obj->tx_q_roc, &p_node) == - QDF_STATUS_SUCCESS) { + status = qdf_list_peek_front(&p2p_soc_obj->tx_q_roc, &p_node); + while (QDF_IS_STATUS_SUCCESS(status)) { curr_tx_ctx = qdf_container_of(p_node, struct tx_action_context, node); 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); + ret = qdf_list_remove_node(&p2p_soc_obj->tx_q_roc, + &curr_tx_ctx->node); + if (ret == QDF_STATUS_SUCCESS) { + p2p_send_tx_conf(curr_tx_ctx, false); + qdf_mem_free(curr_tx_ctx->buf); + qdf_mem_free(curr_tx_ctx); + } else + p2p_err("remove %pK from roc_q fail", + curr_tx_ctx); } + status = qdf_list_peek_next(&p2p_soc_obj->tx_q_roc, + p_node, &p_node); } p2p_debug("clean up tx queue wait for ack, size:%d", qdf_list_size(&p2p_soc_obj->tx_q_ack)); - while (qdf_list_remove_front(&p2p_soc_obj->tx_q_ack, &p_node) == - QDF_STATUS_SUCCESS) { + + status = qdf_list_peek_front(&p2p_soc_obj->tx_q_ack, &p_node); + while (QDF_IS_STATUS_SUCCESS(status)) { curr_tx_ctx = qdf_container_of(p_node, struct tx_action_context, node); 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); + ret = qdf_list_remove_node(&p2p_soc_obj->tx_q_ack, + &curr_tx_ctx->node); + if (ret == QDF_STATUS_SUCCESS) { + 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); + } else + p2p_err("remove %pK from roc_q fail", + curr_tx_ctx); } + status = qdf_list_peek_next(&p2p_soc_obj->tx_q_ack, + p_node, &p_node); } qdf_event_set(&p2p_soc_obj->cleanup_tx_done);