qcacmn: Fix potential memory leak when post scheduler msg in P2P
To avoid potential memory leak, add flush callback for some of P2P messages, handle post scheduler messages fail case. Change-Id: If700eba689bb2423ca84fbba08f7434cc75dbd14 CRs-Fixed: 2341756
这个提交包含在:
@@ -429,6 +429,7 @@ static QDF_STATUS p2p_send_noa_to_pe(struct p2p_noa_info *noa_info)
|
||||
{
|
||||
struct p2p_noa_attr *noa_attr;
|
||||
struct scheduler_msg msg = {0};
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!noa_info) {
|
||||
p2p_err("noa info is null");
|
||||
@@ -474,11 +475,16 @@ static QDF_STATUS p2p_send_noa_to_pe(struct p2p_noa_info *noa_info)
|
||||
msg.type = P2P_NOA_ATTR_IND;
|
||||
msg.bodyval = 0;
|
||||
msg.bodyptr = noa_attr;
|
||||
scheduler_post_message(QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_PE, &msg);
|
||||
status = scheduler_post_message(QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_PE,
|
||||
&msg);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(noa_attr);
|
||||
p2p_err("post msg fail:%d", status);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1044,6 +1050,72 @@ QDF_STATUS p2p_process_evt(struct scheduler_msg *msg)
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS p2p_msg_flush_callback(struct scheduler_msg *msg)
|
||||
{
|
||||
struct tx_action_context *tx_action;
|
||||
|
||||
if (!msg || !(msg->bodyptr)) {
|
||||
p2p_err("invalid msg");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
p2p_debug("flush msg, type:%d", msg->type);
|
||||
switch (msg->type) {
|
||||
case P2P_MGMT_TX:
|
||||
tx_action = (struct tx_action_context *)msg->bodyptr;
|
||||
qdf_mem_free(tx_action->buf);
|
||||
qdf_mem_free(tx_action);
|
||||
break;
|
||||
default:
|
||||
qdf_mem_free(msg->bodyptr);
|
||||
break;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS p2p_event_flush_callback(struct scheduler_msg *msg)
|
||||
{
|
||||
struct p2p_noa_event *noa_event;
|
||||
struct p2p_rx_mgmt_event *rx_mgmt_event;
|
||||
struct p2p_tx_conf_event *tx_conf_event;
|
||||
struct p2p_lo_stop_event *lo_stop_event;
|
||||
|
||||
if (!msg || !(msg->bodyptr)) {
|
||||
p2p_err("invalid msg");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
p2p_debug("flush event, type:%d", msg->type);
|
||||
switch (msg->type) {
|
||||
case P2P_EVENT_NOA:
|
||||
noa_event = (struct p2p_noa_event *)msg->bodyptr;
|
||||
qdf_mem_free(noa_event->noa_info);
|
||||
qdf_mem_free(noa_event);
|
||||
break;
|
||||
case P2P_EVENT_RX_MGMT:
|
||||
rx_mgmt_event = (struct p2p_rx_mgmt_event *)msg->bodyptr;
|
||||
qdf_mem_free(rx_mgmt_event->rx_mgmt);
|
||||
qdf_mem_free(rx_mgmt_event);
|
||||
break;
|
||||
case P2P_EVENT_MGMT_TX_ACK_CNF:
|
||||
tx_conf_event = (struct p2p_tx_conf_event *)msg->bodyptr;
|
||||
qdf_mem_free(tx_conf_event);
|
||||
qdf_nbuf_free(tx_conf_event->nbuf);
|
||||
break;
|
||||
case P2P_EVENT_LO_STOPPED:
|
||||
lo_stop_event = (struct p2p_lo_stop_event *)msg->bodyptr;
|
||||
qdf_mem_free(lo_stop_event->lo_event);
|
||||
qdf_mem_free(lo_stop_event);
|
||||
break;
|
||||
default:
|
||||
qdf_mem_free(msg->bodyptr);
|
||||
break;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
|
||||
QDF_STATUS p2p_process_lo_stop(
|
||||
struct p2p_lo_stop_event *lo_stop_event)
|
||||
|
@@ -445,6 +445,26 @@ QDF_STATUS p2p_process_cmd(struct scheduler_msg *msg);
|
||||
*/
|
||||
QDF_STATUS p2p_process_evt(struct scheduler_msg *msg);
|
||||
|
||||
/**
|
||||
* p2p_msg_flush_callback() - Callback used to flush P2P messages
|
||||
* @msg: message information
|
||||
*
|
||||
* This callback will be called when scheduler flush some of P2P messages.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - in case of success
|
||||
*/
|
||||
QDF_STATUS p2p_msg_flush_callback(struct scheduler_msg *msg);
|
||||
|
||||
/**
|
||||
* p2p_event_flush_callback() - Callback used to flush P2P events
|
||||
* @msg: event information
|
||||
*
|
||||
* This callback will be called when scheduler flush some of P2P events.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - in case of success
|
||||
*/
|
||||
QDF_STATUS p2p_event_flush_callback(struct scheduler_msg *msg);
|
||||
|
||||
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
|
||||
/**
|
||||
* p2p_process_lo_stop() - Process lo stop event
|
||||
|
@@ -80,6 +80,7 @@ QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc,
|
||||
struct p2p_lo_stop_event *lo_stop_event;
|
||||
struct scheduler_msg msg = {0};
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj;
|
||||
QDF_STATUS status;
|
||||
|
||||
p2p_debug("soc:%pK, event_info:%pK", psoc, event_info);
|
||||
|
||||
@@ -116,11 +117,18 @@ QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc,
|
||||
msg.type = P2P_EVENT_LO_STOPPED;
|
||||
msg.bodyptr = lo_stop_event;
|
||||
msg.callback = p2p_process_evt;
|
||||
msg.flush_callback = p2p_event_flush_callback;
|
||||
status = scheduler_post_message(QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_TARGET_IF,
|
||||
&msg);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(lo_stop_event->lo_event);
|
||||
qdf_mem_free(lo_stop_event);
|
||||
p2p_err("post msg fail:%d", status);
|
||||
}
|
||||
|
||||
scheduler_post_message(QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
#endif /* FEATURE_P2P_LISTEN_OFFLOAD */
|
||||
|
||||
@@ -163,7 +171,7 @@ tgt_p2p_add_mac_addr_status_event_cb(struct wlan_objmgr_psoc *psoc,
|
||||
msg.bodyptr = mac_filter_rsp;
|
||||
msg.callback = p2p_process_evt;
|
||||
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
if (status != QDF_STATUS_SUCCESS)
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
qdf_mem_free(mac_filter_rsp);
|
||||
|
||||
return status;
|
||||
@@ -261,17 +269,18 @@ QDF_STATUS tgt_p2p_mgmt_ota_comp_cb(void *context, qdf_nbuf_t buf,
|
||||
msg.type = P2P_EVENT_MGMT_TX_ACK_CNF;
|
||||
msg.bodyptr = tx_conf_event;
|
||||
msg.callback = p2p_process_evt;
|
||||
msg.flush_callback = p2p_event_flush_callback;
|
||||
ret = scheduler_post_message(QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
if (ret != QDF_STATUS_SUCCESS) {
|
||||
QDF_MODULE_ID_TARGET_IF,
|
||||
&msg);
|
||||
if (QDF_IS_STATUS_ERROR(ret)) {
|
||||
qdf_mem_free(tx_conf_event);
|
||||
qdf_mem_free(buf);
|
||||
p2p_err("failed to post message");
|
||||
return status;
|
||||
qdf_nbuf_free(buf);
|
||||
p2p_err("post msg fail:%d", status);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
|
||||
@@ -286,6 +295,7 @@ QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
uint32_t vdev_id;
|
||||
uint8_t *pdata;
|
||||
QDF_STATUS status;
|
||||
|
||||
p2p_debug("psoc:%pK, peer:%pK, type:%d", psoc, peer, frm_type);
|
||||
|
||||
@@ -349,13 +359,19 @@ QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
|
||||
msg.type = P2P_EVENT_RX_MGMT;
|
||||
msg.bodyptr = rx_mgmt_event;
|
||||
msg.callback = p2p_process_evt;
|
||||
scheduler_post_message(QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
|
||||
msg.flush_callback = p2p_event_flush_callback;
|
||||
status = scheduler_post_message(QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_TARGET_IF,
|
||||
&msg);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(rx_mgmt_event->rx_mgmt);
|
||||
qdf_mem_free(rx_mgmt_event);
|
||||
p2p_err("post msg fail:%d", status);
|
||||
}
|
||||
qdf_nbuf_free(buf);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
|
||||
@@ -364,6 +380,7 @@ QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
|
||||
struct p2p_noa_event *noa_event;
|
||||
struct scheduler_msg msg = {0};
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj;
|
||||
QDF_STATUS status;
|
||||
|
||||
p2p_debug("soc:%pK, event_info:%pK", psoc, event_info);
|
||||
|
||||
@@ -400,9 +417,16 @@ QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
|
||||
msg.type = P2P_EVENT_NOA;
|
||||
msg.bodyptr = noa_event;
|
||||
msg.callback = p2p_process_evt;
|
||||
scheduler_post_message(QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
msg.flush_callback = p2p_event_flush_callback;
|
||||
status = scheduler_post_message(QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_TARGET_IF,
|
||||
&msg);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(noa_event->noa_info);
|
||||
qdf_mem_free(noa_event);
|
||||
p2p_err("post msg fail:%d", status);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
@@ -141,7 +141,7 @@ QDF_STATUS ucfg_p2p_roc_req(struct wlan_objmgr_psoc *soc,
|
||||
}
|
||||
|
||||
status = qdf_idr_alloc(&p2p_soc_obj->p2p_idr, roc_ctx, &id);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(roc_ctx);
|
||||
p2p_err("failed to alloc idr, status %d", status);
|
||||
return status;
|
||||
@@ -159,12 +159,18 @@ QDF_STATUS ucfg_p2p_roc_req(struct wlan_objmgr_psoc *soc,
|
||||
msg.type = P2P_ROC_REQ;
|
||||
msg.bodyptr = roc_ctx;
|
||||
msg.callback = p2p_process_cmd;
|
||||
scheduler_post_message(QDF_MODULE_ID_HDD,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_OS_IF, &msg);
|
||||
status = scheduler_post_message(QDF_MODULE_ID_HDD,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_OS_IF,
|
||||
&msg);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(roc_ctx);
|
||||
qdf_idr_remove(&p2p_soc_obj->p2p_idr, id);
|
||||
p2p_err("post msg fail:%d", status);
|
||||
}
|
||||
p2p_debug("cookie = 0x%llx", *cookie);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
|
||||
@@ -174,6 +180,7 @@ QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj;
|
||||
struct cancel_roc_context *cancel_roc;
|
||||
void *roc_ctx = NULL;
|
||||
QDF_STATUS status;
|
||||
|
||||
p2p_debug("soc:%pK, cookie:0x%llx", soc, cookie);
|
||||
|
||||
@@ -189,8 +196,9 @@ QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
if (QDF_STATUS_SUCCESS != qdf_idr_find(&p2p_soc_obj->p2p_idr,
|
||||
cookie, &roc_ctx)) {
|
||||
status = qdf_idr_find(&p2p_soc_obj->p2p_idr,
|
||||
cookie, &roc_ctx);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
p2p_err("invalid id");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
@@ -206,11 +214,17 @@ QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
|
||||
msg.type = P2P_CANCEL_ROC_REQ;
|
||||
msg.bodyptr = cancel_roc;
|
||||
msg.callback = p2p_process_cmd;
|
||||
scheduler_post_message(QDF_MODULE_ID_HDD,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_OS_IF, &msg);
|
||||
status = scheduler_post_message(QDF_MODULE_ID_HDD,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_OS_IF,
|
||||
&msg);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(cancel_roc);
|
||||
p2p_err("post msg fail:%d", status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS ucfg_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev)
|
||||
@@ -342,7 +356,7 @@ QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
|
||||
else {
|
||||
status = qdf_idr_alloc(&p2p_soc_obj->p2p_idr,
|
||||
tx_action, &id);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(tx_action);
|
||||
p2p_err("failed to alloc idr, status :%d", status);
|
||||
return status;
|
||||
@@ -373,11 +387,20 @@ QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
|
||||
msg.type = P2P_MGMT_TX;
|
||||
msg.bodyptr = tx_action;
|
||||
msg.callback = p2p_process_cmd;
|
||||
scheduler_post_message(QDF_MODULE_ID_HDD,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_OS_IF, &msg);
|
||||
msg.flush_callback = p2p_msg_flush_callback;
|
||||
status = scheduler_post_message(QDF_MODULE_ID_HDD,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_OS_IF,
|
||||
&msg);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
if (id)
|
||||
qdf_idr_remove(&p2p_soc_obj->p2p_idr, id);
|
||||
qdf_mem_free(tx_action->buf);
|
||||
qdf_mem_free(tx_action);
|
||||
p2p_err("post msg fail:%d", status);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
|
||||
@@ -387,6 +410,7 @@ QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
|
||||
struct p2p_soc_priv_obj *p2p_soc_obj;
|
||||
struct cancel_roc_context *cancel_tx;
|
||||
void *tx_ctx;
|
||||
QDF_STATUS status;
|
||||
|
||||
p2p_debug("soc:%pK, cookie:0x%llx", soc, cookie);
|
||||
|
||||
@@ -402,8 +426,9 @@ QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
if (QDF_STATUS_SUCCESS != qdf_idr_find(&p2p_soc_obj->p2p_idr,
|
||||
(int32_t)cookie, &tx_ctx)) {
|
||||
status = qdf_idr_find(&p2p_soc_obj->p2p_idr,
|
||||
(int32_t)cookie, &tx_ctx);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
p2p_debug("invalid id");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
@@ -420,11 +445,16 @@ QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
|
||||
msg.type = P2P_MGMT_TX_CANCEL;
|
||||
msg.bodyptr = cancel_tx;
|
||||
msg.callback = p2p_process_cmd;
|
||||
scheduler_post_message(QDF_MODULE_ID_HDD,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_OS_IF, &msg);
|
||||
status = scheduler_post_message(QDF_MODULE_ID_HDD,
|
||||
QDF_MODULE_ID_P2P,
|
||||
QDF_MODULE_ID_OS_IF,
|
||||
&msg);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(cancel_tx);
|
||||
p2p_err("post msg fail: %d", status);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
bool ucfg_p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
|
||||
|
在新工单中引用
屏蔽一个用户