Przeglądaj źródła

qcacld-3.0: Handle BEACON_REPORTING_DO_NOT_RESUME vendor attribute

Optionally set by userspace to request the driver not to resume
beacon reporting after a pause is completed, when the
QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to
QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START.

If this flag is set, the driver will not resume beacon reporting
after beacon reporting pause is completed. Userspace has to
send QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START command again in order
to initiate beacon reporting again.

If this flag is set in the recent
QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START command, then in the
subsequent QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE event (if any)
the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES shall not be
set by the driver.

Change-Id: I371a218cb513dcb077b7df675c549818c2b657b2
CRs-Fixed: 2466480
Abhinav Kumar 5 lat temu
rodzic
commit
e85ae55537

+ 6 - 6
core/hdd/inc/wlan_hdd_bcn_recv.h

@@ -28,19 +28,19 @@ struct wireless_dev;
 struct wiphy;
 
 /**
- * wlan_hdd_cfg80211_bcn_rcv_start() - Process bcn recv start ind
+ * wlan_hdd_cfg80211_bcn_rcv_op() - Process beacon report operations
  * @wiphy: Pointer to wireless phy
  * @wdev: Pointer to wireless device
  * @data: Pointer to data
  * @data_len: Length of @data
  *
- * Wrapper function of __wlan_hdd_cfg80211_bcn_rcv_start()
+ * Wrapper function of __wlan_hdd_cfg80211_bcn_rcv_op()
  *
  * Return: 0 on success, negative errno on failure
  */
-int wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
-				    struct wireless_dev *wdev,
-				    const void *data, int data_len);
+int wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy *wiphy,
+				 struct wireless_dev *wdev,
+				 const void *data, int data_len);
 
 /**
  * hdd_beacon_recv_pause_indication()- Send vendor event to user space
@@ -64,7 +64,7 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
 	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
 		 WIPHY_VENDOR_CMD_NEED_NETDEV |				\
 		 WIPHY_VENDOR_CMD_NEED_RUNNING,				\
-	.doit = wlan_hdd_cfg80211_bcn_rcv_start				\
+	.doit = wlan_hdd_cfg80211_bcn_rcv_op\
 },
 
 #define BCN_RECV_FEATURE_VENDOR_EVENTS			\

+ 82 - 28
core/hdd/src/wlan_hdd_bcn_recv.c

@@ -45,6 +45,8 @@ beacon_reporting_params[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX + 1] = {
 	[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING] = {.type =
 								     NLA_FLAG},
 	[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD] = {.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_DO_NOT_RESUME] = {.type =
+								  NLA_FLAG},
 };
 
 /**
@@ -173,13 +175,15 @@ static void hdd_send_bcn_recv_info(hdd_handle_t hdd_handle,
  * @adapter: Pointer to network adapter
  * @active_report: Active reporting flag
  * @nth_value: Beacon report period
+ * @do_not_resume: beacon reporting resume after a pause is completed
  *
  * This function process beacon reporting start operation.
  */
 static int hdd_handle_beacon_reporting_start_op(struct hdd_context *hdd_ctx,
 						struct hdd_adapter *adapter,
 						bool active_report,
-						uint32_t nth_value)
+						uint32_t nth_value,
+						bool do_not_resume)
 {
 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
 	int errno;
@@ -216,9 +220,15 @@ static int hdd_handle_beacon_reporting_start_op(struct hdd_context *hdd_ctx,
 	}
 	/* Handle beacon receive start indication */
 	qdf_status = sme_handle_bcn_recv_start(hdd_ctx->mac_handle,
-					       adapter->vdev_id, nth_value);
+					       adapter->vdev_id, nth_value,
+					       do_not_resume);
 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
 		hdd_err("bcn rcv start failed with status=%d", qdf_status);
+		if (sme_register_bcn_report_pe_cb(hdd_ctx->mac_handle, NULL))
+			hdd_err("bcn report cb deregistration failed");
+		if (sme_register_bcn_recv_pause_ind_cb(hdd_ctx->mac_handle,
+						       NULL))
+			hdd_err("bcn pause ind cb deregistration failed");
 		errno = qdf_status_to_os_return(qdf_status);
 		return errno;
 	}
@@ -274,7 +284,7 @@ static int hdd_handle_beacon_reporting_stop_op(struct hdd_context *hdd_ctx,
 }
 
 /**
- * __wlan_hdd_cfg80211_bcn_rcv_start() - enable/disable beacon reporting
+ * __wlan_hdd_cfg80211_bcn_rcv_op() - enable/disable beacon reporting
  * indication
  * @wiphy: Pointer to wireless phy
  * @wdev: Pointer to wireless device
@@ -286,9 +296,9 @@ static int hdd_handle_beacon_reporting_stop_op(struct hdd_context *hdd_ctx,
  *
  * Return: 0 on success, negative errno on failure
  */
-static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
-					     struct wireless_dev *wdev,
-					     const void *data, int data_len)
+static int __wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy *wiphy,
+					  struct wireless_dev *wdev,
+					  const void *data, int data_len)
 {
 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
 	struct net_device *dev = wdev->netdev;
@@ -296,7 +306,7 @@ static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX + 1];
 	uint32_t bcn_report, nth_value = 1;
 	int errno;
-	bool active_report;
+	bool active_report, do_not_resume;
 
 	hdd_enter_dev(dev);
 
@@ -319,8 +329,9 @@ static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
 				   QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX,
 				   data, data_len, beacon_reporting_params);
 	if (errno) {
-		hdd_err("Invalid ATTR");
-		return -EINVAL;
+		hdd_err("Failed to parse the beacon reporting params %d",
+			errno);
+		return errno;
 	}
 
 	/* Parse and fetch OP Type */
@@ -328,38 +339,56 @@ static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
 		hdd_err("attr beacon report OP type failed");
 		return -EINVAL;
 	}
-	active_report =
-		!!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING];
-	hdd_debug("attr active_report %d", active_report);
-
 	bcn_report =
 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE]);
 	hdd_debug("Bcn Report: OP type:%d", bcn_report);
 
-	if (tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD])
-		nth_value =
-			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD]);
-	hdd_debug("Beacon Report: Period: %d", nth_value);
-
 	switch (bcn_report) {
 	case QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START:
+		active_report =
+			!!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING];
+		hdd_debug("attr active_report %d", active_report);
+
+		do_not_resume =
+			!!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_DO_NOT_RESUME];
+		hdd_debug("Attr beacon report do not resume %d", do_not_resume);
+
+		if (tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD])
+			nth_value =
+				nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD]);
+		hdd_debug("Beacon Report: Period: %d", nth_value);
+
 		if (sme_is_beacon_report_started(hdd_ctx->mac_handle,
 						 adapter->vdev_id)) {
-			hdd_debug("Start cmd already in progress");
-			return errno;
+			hdd_debug("Start cmd already in progress, issue the stop to FW, before new start");
+			if (hdd_handle_beacon_reporting_stop_op(hdd_ctx,
+								adapter)) {
+				hdd_err("Failed to stop the beacon reporting before starting new start");
+				return -EAGAIN;
+			}
 		}
 		errno = hdd_handle_beacon_reporting_start_op(hdd_ctx,
 							     adapter,
 							     active_report,
-							     nth_value);
+							     nth_value,
+							     do_not_resume);
+		if (errno) {
+			hdd_err("Failed to start beacon reporting %d,", errno);
+			break;
+		}
 		break;
 	case QCA_WLAN_VENDOR_BEACON_REPORTING_OP_STOP:
 		if (sme_is_beacon_report_started(hdd_ctx->mac_handle,
 						 adapter->vdev_id)) {
 			errno = hdd_handle_beacon_reporting_stop_op(hdd_ctx,
 								    adapter);
+			if (errno) {
+				hdd_err("Failed to stop the beacon report, %d",
+					errno);
+			}
 		} else {
 			hdd_err_rl("BCN_RCV_STOP rej as no START CMD active");
+			errno = -EINVAL;
 		}
 		break;
 	default:
@@ -380,6 +409,7 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
 	uint32_t data_len;
 	int flags;
 	uint32_t abort_reason;
+	bool do_not_resume;
 
 	if (wlan_hdd_validate_context(hdd_ctx))
 		return;
@@ -402,6 +432,10 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
 		return;
 	}
 
+	do_not_resume =
+		sme_is_beacon_reporting_do_not_resume(hdd_ctx->mac_handle,
+						      adapter->vdev_id);
+
 	if (is_disconnected) {
 		abort_reason =
 		     QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_DISCONNECTED;
@@ -411,8 +445,23 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
 			hdd_handle_beacon_reporting_stop_op(hdd_ctx,
 							    adapter);
 	} else {
+		/*
+		 * In case of scan, Check that auto resume of beacon reporting
+		 * is allowed or not.
+		 * If not allowed:
+		 * Deregister callbacks and Reset bcn recv start flag in order
+		 * to make sure host should not send beacon report to userspace
+		 * further.
+		 * If Auto resume allowed:
+		 * Send pause indication to userspace and continue sending
+		 * connected AP's beacon to userspace.
+		 */
+		if (do_not_resume)
+			hdd_handle_beacon_reporting_stop_op(hdd_ctx,
+							    adapter);
+
 		switch (type) {
-		case SCAN_EVENT_TYPE_STARTED:
+		case SCAN_EVENT_TYPE_FOREIGN_CHANNEL:
 			abort_reason =
 		     QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_SCAN_STARTED;
 			break;
@@ -437,8 +486,13 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
 	 * Send auto resume flag to user space to specify the driver will
 	 * automatically resume reporting beacon events only in case of
 	 * pause indication due to scan started.
+	 * If do_not_resume flag is set in the recent
+	 * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START command, then in the
+	 * subsequent QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE event (if any)
+	 * the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES shall not be
+	 * set by the driver.
 	 */
-	if (!is_disconnected)
+	if (!is_disconnected || !do_not_resume)
 		if (nla_put_flag(vendor_event,
 			QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES)) {
 			hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
@@ -449,9 +503,9 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
 	cfg80211_vendor_event(vendor_event, flags);
 }
 
-int wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
-				    struct wireless_dev *wdev,
-				    const void *data, int data_len)
+int wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy *wiphy,
+				 struct wireless_dev *wdev,
+				 const void *data, int data_len)
 {
 	int errno;
 	struct osif_vdev_sync *vdev_sync;
@@ -460,8 +514,8 @@ int wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
 	if (errno)
 		return errno;
 
-	errno = __wlan_hdd_cfg80211_bcn_rcv_start(wiphy, wdev,
-						  data, data_len);
+	errno = __wlan_hdd_cfg80211_bcn_rcv_op(wiphy, wdev,
+					       data, data_len);
 
 	osif_vdev_sync_op_stop(vdev_sync);
 

+ 2 - 0
core/sme/inc/csr_internal.h

@@ -567,6 +567,7 @@ struct csr_disconnect_stats {
  * struct csr_roam_session - CSR per-vdev context
  * @vdev_id: ID of the vdev for which this entry is applicable
  * @is_bcn_recv_start: Allow to process bcn recv indication
+ * @beacon_report_do_not_resume: Do not resume the beacon reporting after scan
  */
 struct csr_roam_session {
 	union {
@@ -642,6 +643,7 @@ struct csr_roam_session {
 	qdf_mc_timer_t hTimerRoaming;
 #ifdef WLAN_BCN_RECV_FEATURE
 	bool is_bcn_recv_start;
+	bool beacon_report_do_not_resume;
 #endif
 	/* the roamResult that is used when the roaming timer fires */
 	eCsrRoamResult roamResult;

+ 22 - 1
core/sme/inc/sme_api.h

@@ -1585,6 +1585,7 @@ QDF_STATUS sme_update_mimo_power_save(mac_handle_t mac_handle,
  * @mac_handle: Opaque handle to the global MAC context
  * @vdev_id: SME session id
  * @nth_value: Beacon report period
+ * @do_not_resume: beacon reporting resume after a pause is completed
  *
  * This function remove beacon filter. It allow fw to send
  * all beacons from connected peer to driver.
@@ -1593,7 +1594,8 @@ QDF_STATUS sme_update_mimo_power_save(mac_handle_t mac_handle,
  */
 QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
 				     uint32_t vdev_id,
-				     uint32_t nth_value);
+				     uint32_t nth_value,
+				     bool do_not_resume);
 
 /**
  * sme_is_beacon_report_started() - Check bcn recv started
@@ -1607,6 +1609,18 @@ QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
 bool sme_is_beacon_report_started(mac_handle_t mac_handle,
 				  uint32_t session_id);
 
+/**
+ * sme_is_beacon_reporting_do_not_resume() - Check auto resume allowed or not
+ * @mac_handle: Opaque handle to the global MAC context
+ * @session_id: SME session id
+ *
+ * This function is to check auto resume of beacon reporting is allowed or not.
+ *
+ * Return: true on success
+ */
+bool sme_is_beacon_reporting_do_not_resume(mac_handle_t mac_handle,
+					   uint32_t session_id);
+
 /**
  * stop_beacon_report() - To stop beacon report
  * @mac_handle: Opaque handle to the global MAC context
@@ -1625,6 +1639,13 @@ bool sme_is_beacon_report_started(mac_handle_t mac_handle,
 	return true;
 }
 
+static inline
+bool sme_is_beacon_reporting_do_not_resume(mac_handle_t mac_handle,
+					   uint32_t session_id)
+{
+	return false;
+}
+
 static inline
 void sme_stop_beacon_report(mac_handle_t mac_handle,
 			    uint32_t session_id)

+ 27 - 7
core/sme/src/common/sme_api.c

@@ -12634,7 +12634,8 @@ QDF_STATUS sme_update_mimo_power_save(mac_handle_t mac_handle,
 
 #ifdef WLAN_BCN_RECV_FEATURE
 QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
-				     uint32_t vdev_id, uint32_t nth_value)
+				     uint32_t vdev_id, uint32_t nth_value,
+				     bool do_not_resume)
 {
 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
 	struct csr_roam_session *session;
@@ -12660,6 +12661,7 @@ QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
 			return QDF_STATUS_SUCCESS;
 		}
 		session->is_bcn_recv_start = true;
+		session->beacon_report_do_not_resume = do_not_resume;
 		sme_release_global_lock(&mac_ctx->sme);
 	}
 
@@ -12676,6 +12678,7 @@ QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
 		status = sme_acquire_global_lock(&mac_ctx->sme);
 		if (QDF_IS_STATUS_SUCCESS(status)) {
 			session->is_bcn_recv_start = false;
+			session->beacon_report_do_not_resume = false;
 			sme_release_global_lock(&mac_ctx->sme);
 		}
 		sme_err("WMI_VDEV_PARAM_NTH_BEACON_TO_HOST %d", ret);
@@ -12692,16 +12695,12 @@ void sme_stop_beacon_report(mac_handle_t mac_handle, uint32_t session_id)
 	QDF_STATUS status;
 	int ret;
 
-	if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
-		sme_err("CSR session not valid: %d", session_id);
-		return;
-	}
-
 	session = CSR_GET_SESSION(mac_ctx, session_id);
 	if (!session) {
 		sme_err("vdev_id %d not found", session_id);
 		return;
 	}
+
 	ret = sme_cli_set_command(session_id,
 				  WMI_VDEV_PARAM_NTH_BEACON_TO_HOST, 0,
 				  VDEV_CMD);
@@ -12710,6 +12709,7 @@ void sme_stop_beacon_report(mac_handle_t mac_handle, uint32_t session_id)
 	status = sme_acquire_global_lock(&mac_ctx->sme);
 	if (QDF_IS_STATUS_SUCCESS(status)) {
 		session->is_bcn_recv_start = false;
+		session->beacon_report_do_not_resume = false;
 		sme_release_global_lock(&mac_ctx->sme);
 	}
 }
@@ -12719,18 +12719,38 @@ bool sme_is_beacon_report_started(mac_handle_t mac_handle, uint32_t session_id)
 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
 	struct csr_roam_session *session;
 
+	session = CSR_GET_SESSION(mac_ctx, session_id);
+	if (!session) {
+		sme_err("vdev_id %d not found", session_id);
+		return false;
+	}
+
 	if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
 		sme_err("CSR session not valid: %d", session_id);
 		return false;
 	}
 
+	return session->is_bcn_recv_start;
+}
+
+bool sme_is_beacon_reporting_do_not_resume(mac_handle_t mac_handle,
+					   uint32_t session_id)
+{
+	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
+	struct csr_roam_session *session;
+
 	session = CSR_GET_SESSION(mac_ctx, session_id);
 	if (!session) {
 		sme_err("vdev_id %d not found", session_id);
 		return false;
 	}
 
-	return session->is_bcn_recv_start;
+	if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
+		sme_err("CSR session not valid: %d", session_id);
+		return false;
+	}
+
+	return session->beacon_report_do_not_resume;
 }
 #endif