ソースを参照

qcacld-3.0: Fix to pre CAC interface clean up

If is_pre_cac_on is set, in __wlan_hdd_del_virtual_intf firstly
frees the sap context by calling hdd_clean_up_interface and then
frees the pre cac by calling hdd_clean_up_pre_cac_interface this
will fails to access the sap context which is already freed.

So, replace order of calling, firstly hdd_clean_up_pre_cac_interface
and then hdd_clean_up_interface.

cds flush work will cancel the work which will not delete the pre cac
vdev. Replace with qdf_flush_work will wait for a work to finish,
executing the last queueing instance.

Assign NULL to fn and arg of pre cac work to ensure proper cleanup
of work

Change-Id: I093bf627ce7a73e7c4f7c4cf30e2ec56814a80ed
CRs-Fixed: 3286477
Vinod Kumar Myadam 2 年 前
コミット
bc164e3ba0

+ 19 - 2
components/pre_cac/core/src/wlan_pre_cac_main.c

@@ -34,9 +34,9 @@ void pre_cac_stop(struct wlan_objmgr_psoc *psoc)
 
 	if (!psoc_priv)
 		return;
-	pre_cac_debug("cancel pre_cac_work");
+	pre_cac_debug("flush pre_cac_work");
 	if (psoc_priv->pre_cac_work.fn)
-		qdf_cancel_work(&psoc_priv->pre_cac_work);
+		qdf_flush_work(&psoc_priv->pre_cac_work);
 }
 
 void pre_cac_set_freq(struct wlan_objmgr_vdev *vdev,
@@ -206,6 +206,10 @@ void pre_cac_clean_up(struct wlan_objmgr_psoc *psoc)
 	if (!pre_cac_is_active(psoc))
 		return;
 
+	if (pre_cac_is_active(psoc) && psoc_priv->pre_cac_work.fn) {
+		pre_cac_debug("pre_cac_work already shceduled");
+		return;
+	}
 	pre_cac_get_vdev_id(psoc, &vdev_id);
 	pre_cac_debug("schedue pre_cac_work vdev %d", vdev_id);
 	psoc_priv->pre_cac_vdev_id = vdev_id;
@@ -373,6 +377,19 @@ bool pre_cac_is_active(struct wlan_objmgr_psoc *psoc)
 	return is_pre_cac_on;
 }
 
+void pre_cac_clear_work(struct wlan_objmgr_psoc *psoc)
+{
+	struct pre_cac_psoc_priv *psoc_priv = pre_cac_psoc_get_priv(psoc);
+
+	if (!psoc_priv)
+		return;
+
+	psoc_priv->pre_cac_work.fn = NULL;
+	psoc_priv->pre_cac_work.arg = NULL;
+
+	return;
+}
+
 struct pre_cac_vdev_priv *
 pre_cac_vdev_get_priv_fl(struct wlan_objmgr_vdev *vdev,
 			 const char *func, uint32_t line)

+ 8 - 0
components/pre_cac/core/src/wlan_pre_cac_main.h

@@ -200,6 +200,14 @@ void pre_cac_set_osif_cb(struct pre_cac_ops *osif_pre_cac_ops);
  */
 bool pre_cac_is_active(struct wlan_objmgr_psoc *psoc);
 
+/**
+ * pre_cac_clear_work(): clear pre cac work fn and arg
+ * @psoc: psoc object manager
+ *
+ * Return: None
+ */
+void pre_cac_clear_work(struct wlan_objmgr_psoc *psoc);
+
 /**
  * pre_cac_validate_and_get_freq() - Validate and get pre cac frequency
  * @pdev: pdev object manager

+ 13 - 0
components/pre_cac/dispatcher/inc/wlan_pre_cac_ucfg_api.h

@@ -56,6 +56,14 @@ void ucfg_pre_cac_deinit(void);
  */
 void ucfg_pre_cac_set_osif_cb(struct pre_cac_ops *pre_cac_ops);
 
+/**
+ * ucfg_pre_cac_clear_work() - clear pre cac work fn and arg.
+ * @psoc: psoc object manager
+ *
+ * Return: None
+ */
+void ucfg_pre_cac_clear_work(struct wlan_objmgr_psoc *psoc);
+
 /**
  * ucfg_pre_cac_is_active(): status of pre_cac
  * @psoc: psoc object manager
@@ -203,6 +211,11 @@ ucfg_pre_cac_set_osif_cb(struct pre_cac_ops *pre_cac_ops)
 {
 }
 
+static inline
+void ucfg_pre_cac_clear_work(struct wlan_objmgr_psoc *psoc)
+{
+}
+
 static inline bool
 ucfg_pre_cac_is_active(struct wlan_objmgr_psoc *psoc)
 {

+ 5 - 0
components/pre_cac/dispatcher/src/wlan_pre_cac_ucfg_api.c

@@ -96,6 +96,11 @@ void ucfg_pre_cac_set_osif_cb(struct pre_cac_ops *osif_pre_cac_ops)
 	pre_cac_set_osif_cb(osif_pre_cac_ops);
 }
 
+void ucfg_pre_cac_clear_work(struct wlan_objmgr_psoc *psoc)
+{
+	return pre_cac_clear_work(psoc);
+}
+
 QDF_STATUS ucfg_pre_cac_init(void)
 {
 	return pre_cac_init();

+ 1 - 1
core/hdd/src/wlan_hdd_p2p.c

@@ -949,8 +949,8 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 
 	if (adapter->device_mode == QDF_SAP_MODE &&
 	    ucfg_pre_cac_is_active(hdd_ctx->psoc)) {
-		hdd_clean_up_interface(hdd_ctx, adapter);
 		ucfg_pre_cac_clean_up(hdd_ctx->psoc);
+		hdd_clean_up_interface(hdd_ctx, adapter);
 	} else if (wlan_hdd_is_session_type_monitor(
 					adapter->device_mode) &&
 		   ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=

+ 1 - 0
core/hdd/src/wlan_hdd_pre_cac.c

@@ -116,6 +116,7 @@ void hdd_close_pre_cac_adapter(struct hdd_context *hdd_ctx)
 	if (!pre_cac_adapter)
 		return;
 
+	ucfg_pre_cac_clear_work(hdd_ctx->psoc);
 	errno = osif_vdev_sync_trans_start_wait(pre_cac_adapter->dev,
 						&vdev_sync);
 	if (errno)