浏览代码

qcacmn: Deregister IPA handler from pdev during deinit

A htt message arrived after ipa context is freed as part of
deinitialization which was dereferenced by event handler
assigned to pdev->ipa_uc_op_cb, resulting in crash.
To fix this, during deinit pdev->ipa_uc_op_cb is deregistered
and assigned NULL before freeing up ipa context.

Change-Id: I8125cb104a538e88cda93960f7443129fabd850a
CRs-Fixed: 2793295
Ananya Gupta 4 年之前
父节点
当前提交
936ca8fe36
共有 5 个文件被更改,包括 49 次插入0 次删除
  1. 22 0
      dp/inc/cdp_txrx_ipa.h
  2. 2 0
      dp/inc/cdp_txrx_ops.h
  3. 15 0
      dp/wifi3.0/dp_ipa.c
  4. 9 0
      dp/wifi3.0/dp_ipa.h
  5. 1 0
      dp/wifi3.0/dp_main.c

+ 22 - 0
dp/inc/cdp_txrx_ipa.h

@@ -161,6 +161,28 @@ cdp_ipa_register_op_cb(ol_txrx_soc_handle soc, uint8_t pdev_id,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * cdp_ipa_deregister_op_cb() - deregister event handler function pointer
+ * @soc - data path soc handle
+ * @pdev_id - device instance id
+ *
+ * Deregister event handler function pointer from pdev
+ *
+ * return QDF_STATUS_SUCCESS
+ */
+static inline
+void cdp_ipa_deregister_op_cb(ol_txrx_soc_handle soc, uint8_t pdev_id)
+{
+	if (!soc || !soc->ops || !soc->ops->ipa_ops) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,
+			  "%s invalid instance", __func__);
+		return;
+	}
+
+	if (soc->ops->ipa_ops->ipa_deregister_op_cb)
+		soc->ops->ipa_ops->ipa_deregister_op_cb(soc, pdev_id);
+}
+
 /**
  * cdp_ipa_get_stat() - get IPA data path stats from FW
  * @soc - data path soc handle

+ 2 - 0
dp/inc/cdp_txrx_ops.h

@@ -1555,6 +1555,8 @@ struct cdp_ipa_ops {
 					 void (*ipa_uc_op_cb_type)
 					 (uint8_t *op_msg, void *osif_ctxt),
 					 void *usr_ctxt);
+	void (*ipa_deregister_op_cb)(struct cdp_soc_t *soc_hdl,
+				     uint8_t pdev_id);
 	QDF_STATUS (*ipa_get_stat)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
 	qdf_nbuf_t (*ipa_tx_data_frame)(struct cdp_soc_t *soc_hdl,
 					uint8_t vdev_id, qdf_nbuf_t skb);

+ 15 - 0
dp/wifi3.0/dp_ipa.c

@@ -845,6 +845,21 @@ QDF_STATUS dp_ipa_register_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
 	return QDF_STATUS_SUCCESS;
 }
 
+void dp_ipa_deregister_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
+{
+	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
+	struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
+
+	if (!pdev) {
+		dp_err("Invalid instance");
+		return;
+	}
+
+	dp_debug("Deregister OP handler callback");
+	pdev->ipa_uc_op_cb = NULL;
+	pdev->usr_ctxt = NULL;
+}
+
 QDF_STATUS dp_ipa_get_stat(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
 {
 	/* TBD */

+ 9 - 0
dp/wifi3.0/dp_ipa.h

@@ -95,6 +95,15 @@ QDF_STATUS dp_ipa_op_response(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
 QDF_STATUS dp_ipa_register_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
 				 ipa_uc_op_cb_type op_cb, void *usr_ctxt);
 
+/**
+ * dp_ipa_register_op_cb() - Deregister OP handler function
+ * @soc_hdl - data path soc handle
+ * @pdev_id - device instance id
+ *
+ * Return: none
+ */
+void dp_ipa_deregister_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
+
 /**
  * dp_ipa_get_stat() - Get firmware wdi status
  * @soc_hdl - data path soc handle

+ 1 - 0
dp/wifi3.0/dp_main.c

@@ -11419,6 +11419,7 @@ static struct cdp_ipa_ops dp_ops_ipa = {
 	.ipa_set_doorbell_paddr = dp_ipa_set_doorbell_paddr,
 	.ipa_op_response = dp_ipa_op_response,
 	.ipa_register_op_cb = dp_ipa_register_op_cb,
+	.ipa_deregister_op_cb = dp_ipa_deregister_op_cb,
 	.ipa_get_stat = dp_ipa_get_stat,
 	.ipa_tx_data_frame = dp_tx_send_ipa_data_frame,
 	.ipa_enable_autonomy = dp_ipa_enable_autonomy,