فهرست منبع

qcacld-3.0: Do txrx detach when SSR

Sometime data path is sending packets but ce handler have been
freed when SSR recovering.
Do txrx detach before driver free ce handler.

Change-Id: I0290cc6bf4e4087754fcdd7ae1fe058b8b2e68d2
CRs-Fixed: 2166232
Jiachao Wu 7 سال پیش
والد
کامیت
2c42c22fcc
2فایلهای تغییر یافته به همراه58 افزوده شده و 30 حذف شده
  1. 16 15
      core/hdd/src/wlan_hdd_main.c
  2. 42 15
      core/wma/src/wma_dev_if.c

+ 16 - 15
core/hdd/src/wlan_hdd_main.c

@@ -3573,7 +3573,7 @@ int hdd_vdev_ready(struct hdd_adapter *adapter)
 int hdd_vdev_destroy(struct hdd_adapter *adapter)
 {
 	QDF_STATUS status;
-	int errno;
+	int errno = 0;
 	struct hdd_context *hdd_ctx;
 	uint8_t vdev_id;
 
@@ -3586,16 +3586,6 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter)
 		return -EINVAL;
 	}
 	status = ucfg_reg_11d_vdev_delete_update(adapter->hdd_vdev);
-	/*
-	 * In SSR case, there is no need to destroy vdev in firmware since
-	 * it has already asserted. vdev can be released directly.
-	 */
-	if (cds_is_driver_recovering()) {
-		hdd_debug("SSR: silently release the vdev for session-id: %d",
-			  adapter->session_id);
-		clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
-		goto release_vdev;
-	}
 
 	/* close sme session (destroy vdev in firmware via legacy API) */
 	qdf_event_reset(&adapter->qdf_session_close_event);
@@ -3603,7 +3593,8 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter)
 	status = sme_close_session(hdd_ctx->hHal, adapter->session_id);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("failed to close sme session: %d", status);
-		return qdf_status_to_os_return(status);
+		errno = qdf_status_to_os_return(status);
+		goto release_vdev;
 	}
 
 	/* block on a completion variable until sme session is closed */
@@ -3617,16 +3608,26 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter)
 		adapter->session_id = HDD_SESSION_ID_INVALID;
 		if (QDF_STATUS_E_TIMEOUT != status) {
 			hdd_err("timed out waiting for close sme session: %u", status);
-			return -ETIMEDOUT;
+			errno = -ETIMEDOUT;
+			goto release_vdev;
 		} else if (adapter->qdf_session_close_event.force_set) {
 			hdd_err("Session close evt focefully set, SSR/PDR has occurred");
-			return -EINVAL;
+			errno = -EINVAL;
+			goto release_vdev;
 		} else {
 			hdd_err("Failed to close sme session (%u)", status);
-			return -EINVAL;
+			errno = -EINVAL;
+			goto release_vdev;
 		}
 	}
+
 release_vdev:
+	/* In SSR case, directly exit may cause objects leaks,
+	 * if sme_close_session failed.Free objects anyway.
+	 */
+	if (errno && !cds_is_driver_recovering())
+		return errno;
+
 	/* do vdev logical destroy via objmgr */
 	errno = hdd_objmgr_destroy_vdev(adapter);
 	if (errno) {

+ 42 - 15
core/wma/src/wma_dev_if.c

@@ -643,6 +643,24 @@ out:
 		wma_send_del_sta_self_resp(del_sta_self_req_param);
 	return status;
 }
+
+/**
+ * wma_force_vdev_cleanup() - Cleanup vdev resource when SSR
+ * @wma_handle: WMA handle
+ * @vdev_id: vdev ID
+ *
+ * Return: none
+ */
+static void wma_force_vdev_cleanup(tp_wma_handle wma_handle, uint8_t vdev_id)
+{
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id];
+
+	WMA_LOGE("SSR: force cleanup vdev(%d) resouce", vdev_id);
+	iface->vdev_active = false;
+	wma_cdp_vdev_detach(soc, wma_handle, vdev_id);
+}
+
 /**
  * wma_vdev_detach() - send vdev delete command to fw
  * @wma_handle: wma handle
@@ -660,6 +678,21 @@ QDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle,
 	struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id];
 	struct wma_target_req *req_msg;
 
+	if (!iface->handle) {
+		WMA_LOGE("handle of vdev_id %d is NULL vdev is already freed",
+			 vdev_id);
+		goto send_rsp;
+	}
+
+	/*
+	 * In SSR case, there is no need to destroy vdev in firmware since
+	 * it has already asserted.
+	 */
+	if (cds_is_driver_recovering()) {
+		wma_force_vdev_cleanup(wma_handle, vdev_id);
+		goto send_rsp;
+	}
+
 	if (qdf_atomic_read(&iface->bss_status) == WMA_BSS_STATUS_STARTED) {
 		req_msg = wma_find_vdev_req(wma_handle, vdev_id,
 				WMA_TARGET_REQ_TYPE_VDEV_STOP, false);
@@ -675,19 +708,6 @@ QDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle,
 	}
 	iface->is_del_sta_defered = false;
 
-	if (!iface->handle) {
-		WMA_LOGE("handle of vdev_id %d is NULL vdev is already freed",
-			 vdev_id);
-		pdel_sta_self_req_param->status = status;
-		if (generateRsp) {
-			wma_send_del_sta_self_resp(pdel_sta_self_req_param);
-		} else {
-			qdf_mem_free(pdel_sta_self_req_param);
-			pdel_sta_self_req_param = NULL;
-		}
-		return status;
-	}
-
 	/* P2P Device */
 	if ((iface->type == WMI_VDEV_TYPE_AP) &&
 	    (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) {
@@ -719,9 +739,16 @@ send_fail_rsp:
 			QDF_BUG(0);
 		}
 	}
+	status = QDF_STATUS_E_FAILURE;
 
-	pdel_sta_self_req_param->status = QDF_STATUS_E_FAILURE;
-	wma_send_del_sta_self_resp(pdel_sta_self_req_param);
+send_rsp:
+	if (generateRsp) {
+		pdel_sta_self_req_param->status = status;
+		wma_send_del_sta_self_resp(pdel_sta_self_req_param);
+	} else {
+		qdf_mem_free(pdel_sta_self_req_param);
+		pdel_sta_self_req_param = NULL;
+	}
 	return status;
 }