Explorar el Código

qcacld-3.0: Fix assert for race condition

When disconnect from wpa_supplicant and cm event from F/W happen at same
time, supplicant holds cm cm_req_lock and wait rsp of p2p cleanup roc from
scheduler thread until 2 sec timeout, sheduler thread is blocked to wait
for cm_req_lock.

When wmi peer delete of vdev0 is not sent within 1.2 sec after host send
wmi peer delete of vdev1, firmware will assert.

To fix it, don't wait rsp of p2p cleanup roc when disconnect by async way.

Change-Id: I877b7a446dfd12f621dad5049a67574359bdd322
CRs-Fixed: 3285115
Jianmin Zhu hace 2 años
padre
commit
56608e95ec

+ 1 - 1
components/p2p/core/src/wlan_p2p_main.c

@@ -889,7 +889,7 @@ QDF_STATUS p2p_psoc_stop(struct wlan_objmgr_psoc *soc)
 
 	/* clean up queue of p2p psoc private object */
 	p2p_cleanup_tx_sync(p2p_soc_obj, NULL);
-	p2p_cleanup_roc_sync(p2p_soc_obj, NULL);
+	p2p_cleanup_roc(p2p_soc_obj, NULL, true);
 
 	/* unrgister scan request id*/
 	wlan_scan_unregister_requester(soc, p2p_soc_obj->scan_req_id);

+ 8 - 4
components/p2p/core/src/wlan_p2p_roc.c

@@ -744,9 +744,9 @@ QDF_STATUS p2p_restart_roc_timer(struct p2p_roc_context *roc_ctx)
 	return status;
 }
 
-QDF_STATUS p2p_cleanup_roc_sync(
-	struct p2p_soc_priv_obj *p2p_soc_obj,
-	struct wlan_objmgr_vdev *vdev)
+QDF_STATUS p2p_cleanup_roc(struct p2p_soc_priv_obj *p2p_soc_obj,
+			   struct wlan_objmgr_vdev *vdev,
+			   bool sync)
 {
 	struct scheduler_msg msg = {0};
 	struct p2p_cleanup_param *param;
@@ -758,7 +758,8 @@ QDF_STATUS p2p_cleanup_roc_sync(
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	p2p_debug("p2p_soc_obj:%pK, vdev:%pK", p2p_soc_obj, vdev);
+	p2p_debug("p2p_soc_obj:%pK, vdev:%pK, sync:%d", p2p_soc_obj, vdev,
+		  sync);
 	param = qdf_mem_malloc(sizeof(*param));
 	if (!param)
 		return QDF_STATUS_E_NOMEM;
@@ -781,6 +782,9 @@ QDF_STATUS p2p_cleanup_roc_sync(
 		return status;
 	}
 
+	if (!sync)
+		return status;
+
 	status = qdf_wait_single_event(
 			&p2p_soc_obj->cleanup_roc_done,
 			P2P_WAIT_CLEANUP_ROC);

+ 5 - 4
components/p2p/core/src/wlan_p2p_roc.h

@@ -189,9 +189,10 @@ struct p2p_roc_context *p2p_find_roc_by_chan_freq(
 QDF_STATUS p2p_restart_roc_timer(struct p2p_roc_context *roc_ctx);
 
 /**
- * p2p_cleanup_roc_sync() - Cleanup roc context in queue
+ * p2p_cleanup_roc() - Cleanup roc context in queue
  * @p2p_soc_obj: p2p psoc private object
  * @vdev:        vdev object
+ * @sync: whether to wait for complete event
  *
  * This function cleanup roc context in queue, include the roc
  * context in progressing until cancellation done. To avoid deadlock,
@@ -199,9 +200,9 @@ QDF_STATUS p2p_restart_roc_timer(struct p2p_roc_context *roc_ctx);
  *
  * Return: QDF_STATUS_SUCCESS - in case of success
  */
-QDF_STATUS p2p_cleanup_roc_sync(
-	struct p2p_soc_priv_obj *p2p_soc_obj,
-	struct wlan_objmgr_vdev *vdev);
+QDF_STATUS p2p_cleanup_roc(struct p2p_soc_priv_obj *p2p_soc_obj,
+			   struct wlan_objmgr_vdev *vdev,
+			   bool sync);
 
 /**
  * p2p_process_cleanup_roc_queue() - process the message to cleanup roc

+ 4 - 2
components/p2p/dispatcher/inc/wlan_p2p_api.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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
@@ -44,12 +44,14 @@ bool wlan_p2p_check_oui_and_force_1x1(uint8_t *assoc_ie, uint32_t ie_len);
 /**
  * wlan_p2p_cleanup_roc_by_vdev() - Cleanup roc request by vdev
  * @vdev: pointer to vdev object
+ * @sync: whether to wait for complete event
  *
  * This function call P2P API to cleanup roc request by vdev
  *
  * Return: QDF_STATUS_SUCCESS - in case of success
  */
-QDF_STATUS wlan_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev);
+QDF_STATUS wlan_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev,
+					bool sync);
 
 /**
  * wlan_p2p_status_connect() - Update P2P connection status

+ 4 - 3
components/p2p/dispatcher/src/wlan_p2p_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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
@@ -37,7 +37,8 @@ bool wlan_p2p_check_oui_and_force_1x1(uint8_t *assoc_ie, uint32_t assoc_ie_len)
 	return p2p_check_oui_and_force_1x1(assoc_ie, assoc_ie_len);
 }
 
-QDF_STATUS wlan_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev)
+QDF_STATUS wlan_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev,
+					bool sync)
 {
 	struct p2p_soc_priv_obj *p2p_soc_obj;
 	struct wlan_objmgr_psoc *psoc;
@@ -62,7 +63,7 @@ QDF_STATUS wlan_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev)
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	return p2p_cleanup_roc_sync(p2p_soc_obj, vdev);
+	return p2p_cleanup_roc(p2p_soc_obj, vdev, sync);
 }
 
 QDF_STATUS wlan_p2p_status_connect(struct wlan_objmgr_vdev *vdev)

+ 2 - 2
components/p2p/dispatcher/src/wlan_p2p_ucfg_api.c

@@ -228,7 +228,7 @@ QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
 
 QDF_STATUS ucfg_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev)
 {
-	return wlan_p2p_cleanup_roc_by_vdev(vdev);
+	return wlan_p2p_cleanup_roc_by_vdev(vdev, true);
 }
 
 QDF_STATUS ucfg_p2p_cleanup_roc_by_psoc(struct wlan_objmgr_psoc *psoc)
@@ -246,7 +246,7 @@ QDF_STATUS ucfg_p2p_cleanup_roc_by_psoc(struct wlan_objmgr_psoc *psoc)
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	return p2p_cleanup_roc_sync(obj, NULL);
+	return p2p_cleanup_roc(obj, NULL, true);
 }
 
 QDF_STATUS ucfg_p2p_cleanup_tx_by_vdev(struct wlan_objmgr_vdev *vdev)

+ 1 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_disconnect.c

@@ -80,7 +80,7 @@ QDF_STATUS cm_disconnect_start_ind(struct wlan_objmgr_vdev *vdev,
 
 	user_disconnect = req->source == CM_OSIF_DISCONNECT ? true : false;
 	if (user_disconnect) {
-		wlan_p2p_cleanup_roc_by_vdev(vdev);
+		wlan_p2p_cleanup_roc_by_vdev(vdev, false);
 		wlan_tdls_notify_sta_disconnect(req->vdev_id, false,
 						user_disconnect, vdev);
 	}