Parcourir la source

qcacmn: Fix memory leak during REO cmd ring drain

Fix possible REO descriptor leak while draining REO
command ring by invoking command status handlers with
special error code.

Change-Id: I2fe5f60489b57a4b0a287e67e5610112f7292677
Karunakar Dasineni il y a 7 ans
Parent
commit
31b98d4cd7
3 fichiers modifiés avec 25 ajouts et 8 suppressions
  1. 15 4
      dp/wifi3.0/dp_peer.c
  2. 7 2
      dp/wifi3.0/dp_reo.c
  3. 3 2
      hal/wifi3.0/hal_reo.h

+ 15 - 4
dp/wifi3.0/dp_peer.c

@@ -1019,7 +1019,10 @@ static void dp_rx_tid_update_cb(struct dp_soc *soc, void *cb_ctxt,
 {
 	struct dp_rx_tid *rx_tid = (struct dp_rx_tid *)cb_ctxt;
 
-	if (reo_status->queue_status.header.status) {
+	if ((reo_status->rx_queue_status.header.status !=
+		HAL_REO_CMD_SUCCESS) &&
+		(reo_status->rx_queue_status.header.status !=
+		HAL_REO_CMD_DRAIN)) {
 		/* Should not happen normally. Just print error for now */
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 			"%s: Rx tid HW desc update failed(%d): tid %d\n",
@@ -1114,7 +1117,10 @@ static void dp_reo_desc_free(struct dp_soc *soc, void *cb_ctxt,
 		(struct reo_desc_list_node *)cb_ctxt;
 	struct dp_rx_tid *rx_tid = &freedesc->rx_tid;
 
-	if (reo_status->rx_queue_status.header.status) {
+	if ((reo_status->fl_cache_status.header.status !=
+		HAL_REO_CMD_SUCCESS) &&
+		(reo_status->fl_cache_status.header.status !=
+		HAL_REO_CMD_DRAIN)) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 			"%s: Rx tid HW desc flush failed(%d): tid %d\n",
 			__func__,
@@ -1317,8 +1323,13 @@ static void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt,
 	uint32_t desc_size, tot_desc_size;
 	struct hal_reo_cmd_params params;
 
-
-	if (reo_status->rx_queue_status.header.status) {
+	if (reo_status->rx_queue_status.header.status == HAL_REO_CMD_DRAIN) {
+		qdf_mem_zero(reo_status, sizeof(*reo_status));
+		reo_status->fl_cache_status.header.status = HAL_REO_CMD_DRAIN;
+		dp_reo_desc_free(soc, (void *)freedesc, reo_status);
+		return;
+	} else if (reo_status->rx_queue_status.header.status !=
+		HAL_REO_CMD_SUCCESS) {
 		/* Should not happen normally. Just print error for now */
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 			"%s: Rx tid HW desc deletion failed(%d): tid %d\n",

+ 7 - 2
dp/wifi3.0/dp_reo.c

@@ -178,12 +178,17 @@ void dp_reo_cmdlist_destroy(struct dp_soc *soc)
 {
 	struct dp_reo_cmd_info *reo_cmd = NULL;
 	struct dp_reo_cmd_info *tmp_cmd = NULL;
+	union hal_reo_status reo_status;
+
+	reo_status.queue_status.header.status =
+		HAL_REO_CMD_DRAIN;
 
 	qdf_spin_lock_bh(&soc->rx.reo_cmd_lock);
 	TAILQ_FOREACH_SAFE(reo_cmd, &soc->rx.reo_cmd_list,
-		      reo_cmd_list_elem, tmp_cmd) {
+			reo_cmd_list_elem, tmp_cmd) {
 		TAILQ_REMOVE(&soc->rx.reo_cmd_list, reo_cmd,
-		       reo_cmd_list_elem);
+			reo_cmd_list_elem);
+		reo_cmd->handler(soc, reo_cmd->data, &reo_status);
 		qdf_mem_free(reo_cmd);
 	}
 	qdf_spin_unlock_bh(&soc->rx.reo_cmd_lock);

+ 3 - 2
hal/wifi3.0/hal_reo.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -137,7 +137,8 @@ enum reo_cmd_exec_status {
 	HAL_REO_CMD_SUCCESS = 0,
 	HAL_REO_CMD_BLOCKED = 1,
 	HAL_REO_CMD_FAILED = 2,
-	HAL_REO_CMD_RESOURCE_BLOCKED = 3
+	HAL_REO_CMD_RESOURCE_BLOCKED = 3,
+	HAL_REO_CMD_DRAIN = 0xff
 };
 
 /**