Browse Source

qcacld-3.0: Reconfig OBSS periodicity upon NDP create/delete

When STA is connected to an 11ax AP, driver issues a scan request(OBSS)
to firmware with certain periodicity(it's 120 seconds currently).
Firmware shall do a scan for every 120 seconds irrespective of the
device activity. This causes data glitches throughout the scan duration
when data is going on a concurrent interface.
It's observed that the OBSS scan interrupts NDP data traffic from NDP
applications and causes glitches in file sharing/music sharing use cases.

Configure the OBSS scan periodicity with a larger value(1200 seconds) to
mitigate the glitches when first NDP forms. Reconfigure the original
scan duration(120 seconds) once all NDPs tear down.

Change-Id: Ie0c8228ff3b26f8d9a091909c710928e7ae2a787
CRs-Fixed: 3323193
Rahul Gusain 2 years ago
parent
commit
5c9d7e5c13

+ 11 - 0
core/hdd/inc/wlan_hdd_assoc.h

@@ -268,6 +268,17 @@ void hdd_abort_ongoing_sta_connection(struct hdd_context *hdd_ctx);
  */
 bool hdd_is_any_sta_connected(struct hdd_context *hdd_ctx);
 
+/**
+ * hdd_get_first_connected_sta_vdev_id() - check if any sta in connected state
+ * and exteact the vdev id of connected STA.
+ * @hdd_ctx: hdd context
+ * @vdev_id: pointer to vdev id
+ *
+ * Return: QDF_STATUS enumeration
+ */
+QDF_STATUS hdd_get_first_connected_sta_vdev_id(struct hdd_context *hdd_ctx,
+					       uint32_t *vdev_id);
+
 /**
  * hdd_sme_roam_callback() - hdd sme roam callback
  * @context: pointer to adapter context

+ 30 - 0
core/hdd/src/wlan_hdd_assoc.c

@@ -510,6 +510,36 @@ bool hdd_is_any_sta_connected(struct hdd_context *hdd_ctx)
 	return false;
 }
 
+QDF_STATUS hdd_get_first_connected_sta_vdev_id(struct hdd_context *hdd_ctx,
+					       uint32_t *vdev_id)
+{
+	struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
+	wlan_net_dev_ref_dbgid dbgid =
+				NET_DEV_HOLD_IS_ANY_STA_CONNECTED;
+
+	if (!hdd_ctx) {
+		hdd_err("HDD context is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
+					   dbgid) {
+		if (adapter->device_mode == QDF_STA_MODE ||
+		    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
+			if (hdd_cm_is_vdev_connected(adapter)) {
+				*vdev_id = adapter->vdev_id;
+				hdd_adapter_dev_put_debug(adapter, dbgid);
+				if (next_adapter)
+					hdd_adapter_dev_put_debug(next_adapter,
+								  dbgid);
+				return QDF_STATUS_SUCCESS;
+			}
+		}
+		hdd_adapter_dev_put_debug(adapter, dbgid);
+	}
+	return QDF_STATUS_E_FAILURE;
+}
+
 /**
  * hdd_remove_beacon_filter() - remove beacon filter
  * @adapter: Pointer to the hdd adapter

+ 25 - 0
core/hdd/src/wlan_hdd_nan_datapath.c

@@ -1079,6 +1079,29 @@ void hdd_ndp_session_end_handler(struct hdd_adapter *adapter)
 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_NAN_ID);
 }
 
+/**
+ * hdd_send_obss_scan_req() - send OBSS scan request to SME layer.
+ * @hdd_ctx: hdd context pointer
+ * @val: true if new NDP peer is added and false when last peer NDP is deleted.
+ *
+ * Return: void
+ */
+static void hdd_send_obss_scan_req(struct hdd_context *hdd_ctx, bool val)
+{
+	QDF_STATUS status;
+	uint32_t sta_vdev_id = 0;
+
+	status = hdd_get_first_connected_sta_vdev_id(hdd_ctx, &sta_vdev_id);
+
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		hdd_debug("reconfig OBSS scan param: %d", val);
+		sme_reconfig_obss_scan_param(hdd_ctx->mac_handle, sta_vdev_id,
+					     val);
+	} else {
+		hdd_debug("Connected STA not found");
+	}
+}
+
 int hdd_ndp_new_peer_handler(uint8_t vdev_id, uint16_t sta_id,
 			struct qdf_mac_addr *peer_mac_addr, bool first_peer)
 {
@@ -1147,6 +1170,7 @@ int hdd_ndp_new_peer_handler(uint8_t vdev_id, uint16_t sta_id,
 		 */
 		if (!NDI_CONCURRENCY_SUPPORTED(hdd_ctx->psoc))
 			hdd_indicate_active_ndp_cnt(hdd_ctx->psoc, vdev_id, 1);
+		hdd_send_obss_scan_req(hdd_ctx, true);
 
 		wlan_twt_concurrency_update(hdd_ctx);
 	}
@@ -1227,6 +1251,7 @@ void hdd_ndp_peer_departed_handler(uint8_t vdev_id, uint16_t sta_id,
 		 */
 		if (!NDI_CONCURRENCY_SUPPORTED(hdd_ctx->psoc))
 			hdd_indicate_active_ndp_cnt(hdd_ctx->psoc, vdev_id, 0);
+		hdd_send_obss_scan_req(hdd_ctx, false);
 
 		wlan_twt_concurrency_update(hdd_ctx);
 	}

+ 14 - 0
core/mac/inc/sir_api.h

@@ -1681,6 +1681,20 @@ struct sir_set_he_bss_color {
 	uint8_t bss_color;
 };
 
+/**
+ * struct sir_cfg_obss_scan
+ * @message_type: SME message type
+ * @length: size of struct sir_cfg_obss_scan
+ * @vdev_id: vdev ID
+ * @is_scan_reconfig: true for NDP session
+ */
+struct sir_cfg_obss_scan {
+	uint16_t message_type;
+	uint16_t length;
+	uint8_t vdev_id;
+	bool is_scan_reconfig;
+};
+
 /**
  * struct sir_create_session - Used for creating session in monitor mode
  * @type: SME host message type.

+ 4 - 4
core/mac/inc/wni_api.h

@@ -68,10 +68,10 @@ enum eWniMsgTypes {
 	eWNI_SME_DELTS_RSP = SIR_SME_MSG_TYPES_BEGIN + 31,
 	eWNI_SME_DELTS_IND = SIR_SME_MSG_TYPES_BEGIN + 32,
 	eWNI_SME_MSCS_REQ = SIR_SME_MSG_TYPES_BEGIN + 33,
-	/*
-	 * unused SIR_SME_MSG_TYPES_BEGIN + 34 to
-	 * to SIR_SME_MSG_TYPES_BEGIN + 35
-	 */
+	eWNI_SME_RECONFIG_OBSS_SCAN_PARAM = SIR_SME_MSG_TYPES_BEGIN + 34,
+
+	/* unused SIR_SME_MSG_TYPES_BEGIN + 35 */
+
 	eWNI_SME_ASSOC_IND_UPPER_LAYER = SIR_SME_MSG_TYPES_BEGIN + 36,
 	eWNI_SME_WPS_PBC_PROBE_REQ_IND = SIR_SME_MSG_TYPES_BEGIN + 37,
 	eWNI_SME_UPPER_LAYER_ASSOC_CNF = SIR_SME_MSG_TYPES_BEGIN + 38,

+ 5 - 0
core/mac/src/pe/include/lim_session.h

@@ -89,6 +89,11 @@ struct reassoc_params {
 #define BSS_COLOR_SWITCH_COUNTDOWN 5
 #define OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS 120000
 #define OBSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS 120000
+/*
+ * Have OBSS scan duration as 1200 seconds(20 minutes) when there is an active
+ * NDP to avoid glitches during NDP traffic due the scan.
+ */
+#define OBSS_COLOR_COLLISION_DETECTION_NDP_PERIOD_MS 1200000
 #define OBSS_COLOR_COLLISION_SCAN_PERIOD_MS 200
 #define OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS 50000
 struct bss_color_info {

+ 19 - 0
core/mac/src/pe/lim/lim_api.c

@@ -2636,6 +2636,21 @@ end:
 	return status;
 }
 
+#ifdef WLAN_FEATURE_11AX
+static void pe_roam_fill_obss_scan_param(struct pe_session *src_session,
+					 struct pe_session *dst_session)
+{
+	dst_session->obss_color_collision_dec_evt =
+				src_session->obss_color_collision_dec_evt;
+	dst_session->he_op.bss_color = src_session->he_op.bss_color;
+}
+#else
+static inline void pe_roam_fill_obss_scan_param(struct pe_session *src_session,
+						struct pe_session *dst_session)
+{
+}
+#endif
+
 QDF_STATUS
 pe_roam_synch_callback(struct mac_context *mac_ctx,
 		       uint8_t vdev_id,
@@ -2799,6 +2814,10 @@ pe_roam_synch_callback(struct mac_context *mac_ctx,
 		lim_delete_dph_hash_entry(mac_ctx, curr_sta_ds->staAddr, aid,
 					  session_ptr);
 	}
+
+	/* update OBSS scan param */
+	pe_roam_fill_obss_scan_param(session_ptr, ft_session_ptr);
+
 	pe_delete_session(mac_ctx, session_ptr);
 	session_ptr = NULL;
 	curr_sta_ds = dph_add_hash_entry(mac_ctx,

+ 5 - 0
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -2026,6 +2026,11 @@ static void lim_process_messages(struct mac_context *mac_ctx,
 		qdf_mem_free((void *)msg->bodyptr);
 		msg->bodyptr = NULL;
 		break;
+	case eWNI_SME_RECONFIG_OBSS_SCAN_PARAM:
+		lim_reconfig_obss_scan_param(mac_ctx, msg->bodyptr);
+		qdf_mem_free((void *)msg->bodyptr);
+		msg->bodyptr = NULL;
+		break;
 	case eWNI_SME_DEL_ALL_TDLS_PEERS:
 		lim_process_sme_del_all_tdls_peers(mac_ctx, msg->bodyptr);
 		qdf_mem_free((void *)msg->bodyptr);

+ 69 - 0
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -9626,6 +9626,75 @@ void lim_process_set_he_bss_color(struct mac_context *mac_ctx, uint32_t *msg_buf
 			OBSS_COLOR_COLLISION_DETECTION_DISABLE);
 }
 
+void lim_reconfig_obss_scan_param(struct mac_context *mac_ctx,
+				  uint32_t *msg_buf)
+{
+	struct sir_cfg_obss_scan *obss_scan_param;
+	struct pe_session *session = NULL;
+	struct wmi_obss_color_collision_cfg_param *cfg_param;
+	struct scheduler_msg msg = {0};
+
+	if (!msg_buf) {
+		pe_err("Buffer is Pointing to NULL");
+		return;
+	}
+
+	obss_scan_param = (struct sir_cfg_obss_scan *)msg_buf;
+	session = pe_find_session_by_vdev_id(mac_ctx, obss_scan_param->vdev_id);
+	if (!session) {
+		pe_err("Session not found for given vdev_id %d",
+		       obss_scan_param->vdev_id);
+		return;
+	}
+
+	if (!session->he_capable ||
+	    !session->is_session_obss_color_collision_det_enabled ||
+	    session->obss_color_collision_dec_evt ==
+				OBSS_COLOR_COLLISION_DETECTION_DISABLE) {
+		pe_debug("%d: obss color det not enabled, he_cap:%d, sup:%d:%d event_type:%d",
+			 session->smeSessionId, session->he_capable,
+			 session->is_session_obss_color_collision_det_enabled,
+			 mac_ctx->mlme_cfg->obss_ht40.obss_color_collision_offload_enabled,
+			 session->obss_color_collision_dec_evt);
+		return;
+	}
+
+	cfg_param = qdf_mem_malloc(sizeof(*cfg_param));
+	if (!cfg_param)
+		return;
+
+	pe_debug("vdev_id %d: sending event:%d scan_reconfig:%d",
+		 session->smeSessionId, session->obss_color_collision_dec_evt,
+		 obss_scan_param->is_scan_reconfig);
+	cfg_param->vdev_id = session->smeSessionId;
+	cfg_param->evt_type = session->obss_color_collision_dec_evt;
+	cfg_param->current_bss_color = session->he_op.bss_color;
+
+	if (obss_scan_param->is_scan_reconfig)
+		cfg_param->detection_period_ms =
+				OBSS_COLOR_COLLISION_DETECTION_NDP_PERIOD_MS;
+	else
+		cfg_param->detection_period_ms =
+				OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS;
+	cfg_param->scan_period_ms = OBSS_COLOR_COLLISION_SCAN_PERIOD_MS;
+
+	if (session->obss_color_collision_dec_evt ==
+	    OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY)
+		cfg_param->free_slot_expiry_time_ms =
+			OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS;
+
+	msg.type = WMA_OBSS_COLOR_COLLISION_REQ;
+	msg.bodyptr = cfg_param;
+	msg.reserved = 0;
+
+	if (QDF_IS_STATUS_ERROR(scheduler_post_message(QDF_MODULE_ID_PE,
+						       QDF_MODULE_ID_WMA,
+						       QDF_MODULE_ID_WMA,
+						       &msg))) {
+		qdf_mem_free(cfg_param);
+	}
+}
+
 void lim_send_obss_color_collision_cfg(struct mac_context *mac_ctx,
 				       struct pe_session *session,
 				       enum wmi_obss_color_collision_evt_type

+ 16 - 0
core/mac/src/pe/lim/lim_types.h

@@ -741,6 +741,17 @@ static inline void lim_process_rx_scan_handler(struct wlan_objmgr_vdev *vdev,
  */
 void lim_process_set_he_bss_color(struct mac_context *mac_ctx, uint32_t *msg_buf);
 
+/**
+ * lim_reconfig_obss_scan_param() - reconfig the obss scan params
+ *
+ * @mac_ctx: global mac context pointer
+ * @msg_buf: message buffer pointer
+ *
+ * Return: void
+ */
+void lim_reconfig_obss_scan_param(struct mac_context *mac_ctx,
+				  uint32_t *msg_buf);
+
 /**
  * lim_process_obss_color_collision_info() - Process the obss color collision
  *  request.
@@ -768,6 +779,11 @@ void lim_send_obss_color_collision_cfg(struct mac_context *mac_ctx,
 static inline void lim_process_set_he_bss_color(struct mac_context *mac_ctx,
 		uint32_t *msg_buf)
 {}
+
+static inline void lim_reconfig_obss_scan_param(struct mac_context *mac_ctx,
+						uint32_t *msg_buf)
+{
+}
 static inline void lim_process_obss_color_collision_info(struct mac_context *mac_ctx,
 							 uint32_t *msg_buf)
 {}

+ 20 - 0
core/sme/inc/sme_api.h

@@ -2861,6 +2861,18 @@ QDF_STATUS sme_send_rso_connect_params(mac_handle_t mac_handle,
  */
 QDF_STATUS sme_set_he_bss_color(mac_handle_t mac_handle, uint8_t session_id,
 				uint8_t bss_color);
+/**
+ * sme_reconfig_obss_scan_param() - reconfig obss scan param
+ *
+ * @mac_handle: The handle returned by mac_open
+ * @session_id: session_id of the request
+ * @is_scan_reconfig: true if modify OBSS scan periodicity, otherwise false
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS sme_reconfig_obss_scan_param(mac_handle_t mac_handle,
+					uint8_t session_id,
+					bool is_scan_reconfig);
 #else
 static inline
 QDF_STATUS sme_set_he_bss_color(mac_handle_t mac_handle, uint8_t session_id,
@@ -2868,6 +2880,14 @@ QDF_STATUS sme_set_he_bss_color(mac_handle_t mac_handle, uint8_t session_id,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline
+QDF_STATUS sme_reconfig_obss_scan_param(mac_handle_t mac_handle,
+					uint8_t session_id,
+					bool is_scan_reconfig)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 /**

+ 24 - 0
core/sme/src/common/sme_api.c

@@ -12788,6 +12788,30 @@ QDF_STATUS sme_set_he_bss_color(mac_handle_t mac_handle, uint8_t session_id,
 	bss_color_msg->bss_color = bss_color;
 	return umac_send_mb_message_to_mac(bss_color_msg);
 }
+
+QDF_STATUS sme_reconfig_obss_scan_param(mac_handle_t mac_handle,
+					uint8_t session_id,
+					bool is_scan_reconfig)
+{
+	struct sir_cfg_obss_scan *obss_scan_msg;
+	uint8_t len;
+
+	if (!mac_handle) {
+		sme_err("Invalid mac_handle pointer");
+		return QDF_STATUS_E_FAULT;
+	}
+
+	len = sizeof(*obss_scan_msg);
+	obss_scan_msg = qdf_mem_malloc(len);
+	if (!obss_scan_msg)
+		return QDF_STATUS_E_NOMEM;
+
+	obss_scan_msg->message_type = eWNI_SME_RECONFIG_OBSS_SCAN_PARAM;
+	obss_scan_msg->length = len;
+	obss_scan_msg->vdev_id = session_id;
+	obss_scan_msg->is_scan_reconfig = is_scan_reconfig;
+	return umac_send_mb_message_to_mac(obss_scan_msg);
+}
 #endif
 
 #ifdef FEATURE_P2P_LISTEN_OFFLOAD