Bladeren bron

qcacld-3.0: Peer is not deleted when delete VDEV

Failure can be observed when waiting for peer deletion
before sending WMI command. Peer deletion in VDEV stop
timeout handler also need to be handled in the scheduler
queues.

Change the logic to wait for peer delete completion
before sending message to scheduler queue to delete VDEV.

Change-Id: I78d3070a73c85d212bc33c346b3e60edf3c016f8
CRs-Fixed: 2187430
Min Liu 7 jaren geleden
bovenliggende
commit
22202b703a
3 gewijzigde bestanden met toevoegingen van 64 en 13 verwijderingen
  1. 16 0
      core/sme/src/csr/csr_api_roam.c
  2. 13 1
      core/wma/inc/wma.h
  3. 35 12
      core/wma/src/wma_dev_if.c

+ 16 - 0
core/sme/src/csr/csr_api_roam.c

@@ -16771,8 +16771,24 @@ csr_issue_del_sta_for_session_req(tpAniSirGlobal pMac, uint32_t sessionId,
 {
 	struct del_sta_self_params *del_sta_self_req;
 	struct scheduler_msg msg = {0};
+	tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
 	tSirRetStatus status;
 
+	if (!wma_handle) {
+		sme_err("wma handle is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/* Need to wait for all peer delete command sent to FW
+	 * before sending VDEV delete command
+	 * otherwise it will cause FW assert
+	 * Need to do this before sending to scheduler queue
+	 * otherwise the scheduler thread will be blocked
+	 * and fail to handle the VDEV stop timeout callback
+	 * in which peer delete command will also be sent
+	 */
+	wma_vdev_wait_for_peer_delete_completion(wma_handle, sessionId);
+
 	del_sta_self_req = qdf_mem_malloc(sizeof(struct del_sta_self_params));
 	if (NULL == del_sta_self_req) {
 		sme_err(" mem alloc failed for tDelStaSelfParams");

+ 13 - 1
core/wma/inc/wma.h

@@ -1111,7 +1111,7 @@ struct wma_txrx_node {
 	bool restore_dtim_setting;
 	uint32_t peer_count;
 	qdf_atomic_t fw_peer_count;
-	qdf_event_t fw_peer_delete;
+	qdf_event_t fw_peer_delete_completion;
 	bool roam_synch_in_progress;
 	void *plink_status_req;
 	void *psnr_req;
@@ -2659,4 +2659,16 @@ QDF_STATUS wma_config_bmiss_bcnt_params(uint32_t vdev_id, uint32_t first_cnt,
  * Return: None
  */
 void wma_check_and_set_wake_timer(uint32_t time);
+
+/**
+ * wma_vdev_wait_for_peer_delete_completion() - wait for all peers of the vdev
+ * to be deleted.
+ * @wma_handle: wma handle
+ * @vdev_id: vdev id
+ *
+ * Return: None
+ */
+void wma_vdev_wait_for_peer_delete_completion(tp_wma_handle wma_handle,
+					      uint8_t vdev_id);
+
 #endif

+ 35 - 12
core/wma/src/wma_dev_if.c

@@ -573,8 +573,6 @@ wma_cdp_vdev_detach(ol_txrx_soc_handle soc,
 	iface->is_vdev_valid = false;
 }
 
-#define WAIT_FW_PEER_DELETE_TIMEOUT (5*1000)
-
 static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle,
 			struct del_sta_self_params *del_sta_self_req_param,
 			uint8_t generate_rsp)
@@ -591,11 +589,7 @@ static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle,
 		goto out;
 	}
 
-	while (qdf_atomic_read(&iface->fw_peer_count)) {
-		qdf_wait_for_event_completion(&iface->fw_peer_delete,
-					      WAIT_FW_PEER_DELETE_TIMEOUT);
-		qdf_event_reset(&iface->fw_peer_delete);
-	}
+	QDF_BUG(qdf_atomic_read(&iface->fw_peer_count) == 0);
 
 	status = wmi_unified_vdev_delete_send(wma_handle->wmi_handle, vdev_id);
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -603,7 +597,7 @@ static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle,
 		goto out;
 	}
 
-	qdf_event_destroy(&iface->fw_peer_delete);
+	qdf_event_destroy(&iface->fw_peer_delete_completion);
 
 	WMA_LOGD("vdev_id:%hu vdev_hdl:%pK", vdev_id, iface->handle);
 	if (!generate_rsp) {
@@ -713,6 +707,30 @@ VDEV_DETACH:
 	wma_cdp_vdev_detach(soc, wma_handle, vdev_id);
 }
 
+#define WMA_WAIT_PEER_DELETE_COMPLETION_TIMEOUT (WMA_VDEV_STOP_REQUEST_TIMEOUT+ 1000)
+
+/**
+ * wma_vdev_wait_for_peer_delete_completion(): wait for all peers of the vdev
+ * to be deleted.
+ * @wma_handle: wma handle
+ * @vdev_id: vdev id
+ *
+ * Return: None
+ */
+void wma_vdev_wait_for_peer_delete_completion(tp_wma_handle wma_handle,
+					      uint8_t vdev_id)
+{
+	struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id];
+
+	if (!iface) {
+		WMA_LOGE("%s: iface of vdev-%d is NULL", __func__, vdev_id);
+		return;
+	}
+
+	qdf_wait_for_event_completion(&iface->fw_peer_delete_completion,
+				      WMA_WAIT_PEER_DELETE_COMPLETION_TIMEOUT);
+}
+
 /**
  * wma_vdev_detach() - send vdev delete command to fw
  * @wma_handle: wma handle
@@ -1426,9 +1444,10 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid,
 		bitmap = 1 << CDP_PEER_DO_NOT_START_UNMAP_TIMER;
 	} else {
 		qdf_atomic_dec(&wma->interfaces[vdev_id].fw_peer_count);
-		qdf_event_set(&wma->interfaces[vdev_id].fw_peer_delete);
 		WMA_LOGD("%s: vdev-%d fw_peer_count %d", __func__, vdev_id,
 			 qdf_atomic_read(&wma->interfaces[vdev_id].fw_peer_count));
+		if (qdf_atomic_read(&wma->interfaces[vdev_id].fw_peer_count) == 0)
+			qdf_event_set(&wma->interfaces[vdev_id].fw_peer_delete_completion);
 	}
 
 peer_detach:
@@ -1570,6 +1589,7 @@ QDF_STATUS wma_create_peer(tp_wma_handle wma, struct cdp_pdev *pdev,
 		qdf_atomic_inc(&wma->interfaces[vdev_id].fw_peer_count);
 		WMA_LOGD("%s: vdev-%d fw_peer_count %d", __func__, vdev_id,
 			 qdf_atomic_read(&wma->interfaces[vdev_id].fw_peer_count));
+		qdf_event_reset(&wma->interfaces[vdev_id].fw_peer_delete_completion);
 	}
 
 	WMA_LOGD("%s: Created peer %pK with peer_addr %pM vdev_id %d, peer_count - %d",
@@ -2236,9 +2256,12 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 	qdf_atomic_init(&wma_handle->interfaces
 			[self_sta_req->session_id].fw_peer_count);
 	status = qdf_event_create(&wma_handle->interfaces
-				  [self_sta_req->session_id].fw_peer_delete);
-	if (status != QDF_STATUS_SUCCESS)
-		WMA_LOGE("%s: Failed to create fw_peer_delete event", __func__);
+				  [self_sta_req->session_id].fw_peer_delete_completion);
+	if (status != QDF_STATUS_SUCCESS) {
+		WMA_LOGE("%s: Failed to create fw_peer_delete_completion", __func__);
+		goto end;
+	}
+	qdf_event_set(&wma_handle->interfaces[vdev_id].fw_peer_delete_completion);
 
 	if (((self_sta_req->type == WMI_VDEV_TYPE_AP) &&
 	    (self_sta_req->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) ||