Explorar o código

qcacld-3.0: Fix uc_op_work->msg leak from uC ready callback

Do not schedule uc_op_work inside uC ready callback, when the
uc_op_work is not initialized.
So, if the uC ready callback is invoked before hdd_ipa_ol_init(),
just set uc_loaded flag and return, without scheduling uc_op_work.

Change-Id: I9c813047ab4b1b129e4fb057d8aacbef5cc9efea
CRs-Fixed: 2169668
Yun Park %!s(int64=7) %!d(string=hai) anos
pai
achega
6edb217876
Modificáronse 1 ficheiros con 17 adicións e 5 borrados
  1. 17 5
      core/hdd/src/wlan_hdd_ipa.c

+ 17 - 5
core/hdd/src/wlan_hdd_ipa.c

@@ -577,6 +577,14 @@ static void hdd_ipa_uc_loaded_uc_cb(void *priv_ctxt)
 	}
 
 	hdd_ipa = (struct hdd_ipa_priv *)priv_ctxt;
+	hdd_ipa->uc_loaded = true;
+
+	uc_op_work = &hdd_ipa->uc_op_work[HDD_IPA_UC_OPCODE_UC_READY];
+
+	if (!list_empty(&uc_op_work->work.entry))
+		/* uc_op_work is not initialized yet */
+		return;
+
 	msg = (struct op_msg_type *)qdf_mem_malloc(sizeof(*msg));
 	if (!msg) {
 		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "op_msg allocation fails");
@@ -585,8 +593,6 @@ static void hdd_ipa_uc_loaded_uc_cb(void *priv_ctxt)
 
 	msg->op_code = HDD_IPA_UC_OPCODE_UC_READY;
 
-	uc_op_work = &hdd_ipa->uc_op_work[msg->op_code];
-
 	/* When the same uC OPCODE is already pended, just return */
 	if (uc_op_work->msg)
 		goto done;
@@ -2141,7 +2147,6 @@ static void hdd_ipa_uc_loaded_handler(struct hdd_ipa_priv *hdd_ipa)
 	}
 
 	hdd_ctx = hdd_ipa->hdd_ctx;
-	hdd_ipa->uc_loaded = true;
 
 	/* Connect pipe */
 	status = cdp_ipa_setup(soc, (struct cdp_pdev *)pdev,
@@ -3194,7 +3199,7 @@ static void hdd_ipa_cleanup_pending_event(struct hdd_ipa_priv *hdd_ipa)
 int hdd_ipa_uc_ol_deinit(struct hdd_context *hdd_ctx)
 {
 	struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa;
-	int ret = 0;
+	int i, ret = 0;
 	QDF_STATUS status;
 
 	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
@@ -3213,7 +3218,7 @@ int hdd_ipa_uc_ol_deinit(struct hdd_context *hdd_ctx)
 			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
 				    "Failure to cleanup IPA pipes (status=%d)",
 				    status);
-			return -EFAULT;
+			ret = -EFAULT;
 		}
 	}
 
@@ -3221,6 +3226,12 @@ int hdd_ipa_uc_ol_deinit(struct hdd_context *hdd_ctx)
 	hdd_ipa_cleanup_pending_event(hdd_ipa);
 	qdf_mutex_release(&hdd_ipa->ipa_lock);
 
+	for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) {
+		cancel_work_sync(&hdd_ipa->uc_op_work[i].work);
+		qdf_mem_free(hdd_ipa->uc_op_work[i].msg);
+		hdd_ipa->uc_op_work[i].msg = NULL;
+	}
+
 	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: ret=%d", ret);
 	return ret;
 }
@@ -6091,6 +6102,7 @@ static QDF_STATUS __hdd_ipa_cleanup(struct hdd_context *hdd_ctx)
 
 		for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) {
 			cancel_work_sync(&hdd_ipa->uc_op_work[i].work);
+			qdf_mem_free(hdd_ipa->uc_op_work[i].msg);
 			hdd_ipa->uc_op_work[i].msg = NULL;
 		}
 	}