Parcourir la source

qcacld-3.0: Wait for NDP_END indication from firmware

When application issues NDP end to terminate an NDP connection,
host driver sends a request to the firmware and firmware
terminates the NDP by sending NDP end frame to the peer.
Currently, driver returns immediately after posting request to
the firmware. Application might issue NDI delete immediately
after returning from NDP_END request.
But firmware might take some time to complete the NDP termination
and send NDP_END indication to driver.
When driver tries to delete the NDI before receiving NDP_END
indication from firmware, it causes inconsistency in firmware as
the NDI on which the NDP is parked is freed.
So, wait till the NDP_END indication comes from
firmware(or timeout happens) before returning from ndp_end request
context.

Change-Id: Ied7ed36451ef007e38f67d48c54290b9dd674f54
CRs-Fixed: 2616018
Srinivas Dasari il y a 5 ans
Parent
commit
62bb6191b1

+ 1 - 0
components/nan/core/inc/nan_public_structs.h

@@ -45,6 +45,7 @@ struct wlan_objmgr_vdev;
 #define NAN_PASSPHRASE_MIN_LEN 8
 #define NAN_PASSPHRASE_MAX_LEN 63
 #define NAN_CH_INFO_MAX_CHANNELS 4
+#define WLAN_WAIT_TIME_NDP_END 2000
 
 #define NAN_PSEUDO_VDEV_ID CFG_TGT_NUM_VDEV
 

+ 9 - 0
components/nan/core/src/nan_main.c

@@ -35,6 +35,7 @@
 #include "wlan_objmgr_pdev_obj.h"
 #include "wlan_objmgr_vdev_obj.h"
 #include "qdf_platform.h"
+#include "wlan_osif_request_manager.h"
 
 QDF_STATUS nan_set_discovery_state(struct wlan_objmgr_psoc *psoc,
 				   enum nan_disc_state new_state)
@@ -758,6 +759,7 @@ static QDF_STATUS nan_handle_end_ind(
 	struct nan_psoc_priv_obj *psoc_nan_obj;
 	struct wlan_objmgr_vdev *vdev_itr;
 	struct nan_vdev_priv_obj *vdev_nan_obj;
+	struct osif_request *request;
 
 	psoc = wlan_vdev_get_psoc(ind->vdev);
 	if (!psoc) {
@@ -804,6 +806,13 @@ static QDF_STATUS nan_handle_end_ind(
 	psoc_nan_obj->cb_obj.os_if_ndp_event_handler(psoc, ind->vdev,
 						     NDP_END_IND, ind);
 
+	/* Unblock the NDP_END wait */
+	request = osif_request_get(psoc_nan_obj->request_context);
+	if (request) {
+		osif_request_complete(request);
+		osif_request_put(request);
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 39 - 2
components/nan/dispatcher/src/nan_ucfg_api.c

@@ -372,6 +372,13 @@ QDF_STATUS ucfg_nan_req_processor(struct wlan_objmgr_vdev *vdev,
 	uint32_t len;
 	QDF_STATUS status;
 	struct scheduler_msg msg = {0};
+	int err;
+	struct nan_psoc_priv_obj *psoc_obj = NULL;
+	struct osif_request *request;
+	static const struct osif_request_params params = {
+		.priv_size = 0,
+		.timeout_ms = WLAN_WAIT_TIME_NDP_END,
+	};
 
 	if (!in_req) {
 		nan_alert("req is null");
@@ -387,6 +394,11 @@ QDF_STATUS ucfg_nan_req_processor(struct wlan_objmgr_vdev *vdev,
 		break;
 	case NDP_END_REQ:
 		len = sizeof(struct nan_datapath_end_req);
+		psoc_obj = nan_get_psoc_priv_obj(wlan_vdev_get_psoc(vdev));
+		if (!psoc_obj) {
+			nan_err("nan psoc priv object is NULL");
+			return QDF_STATUS_E_INVAL;
+		}
 		break;
 	case NDP_END_ALL:
 		len = sizeof(struct nan_datapath_end_all_ndps);
@@ -408,10 +420,35 @@ QDF_STATUS ucfg_nan_req_processor(struct wlan_objmgr_vdev *vdev,
 	status = scheduler_post_message(QDF_MODULE_ID_HDD,
 					QDF_MODULE_ID_NAN,
 					QDF_MODULE_ID_OS_IF, &msg);
-	if (QDF_IS_STATUS_ERROR(status))
+	if (QDF_IS_STATUS_ERROR(status)) {
+		nan_err("failed to post msg to NAN component, status: %d",
+			status);
 		qdf_mem_free(msg.bodyptr);
+		return status;
+	}
 
-	return status;
+	if (req_type == NDP_END_REQ) {
+		/* Wait for NDP_END indication */
+		if (!psoc_obj) {
+			nan_err("nan psoc priv object is NULL");
+			return QDF_STATUS_E_INVAL;
+		}
+		request = osif_request_alloc(&params);
+		if (!request) {
+			nan_err("Request allocation failure");
+			return QDF_STATUS_E_NOMEM;
+		}
+		psoc_obj->request_context = osif_request_cookie(request);
+
+		nan_debug("Wait for NDP END indication");
+		err = osif_request_wait_for_response(request);
+		if (err)
+			nan_err("NAN request timed out: %d", err);
+		osif_request_put(request);
+		psoc_obj->request_context = NULL;
+	}
+
+	return QDF_STATUS_SUCCESS;
 }
 
 void ucfg_nan_datapath_event_handler(struct wlan_objmgr_psoc *psoc,