Procházet zdrojové kódy

qcacld-3.0: Add set link source data structure

Add new data structure to save the external/internal set link
request. The different source of request has different priority.
In some situations, a certain request may not be honored if
it conflicts with higher priority request.

Change-Id: Ib95d0c688f92dcfc294702e7deb2e3b7da13f76c
CRs-Fixed: 3650630
Liangwei Dong před 1 rokem
rodič
revize
e1e35f85c2

+ 84 - 4
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -8717,6 +8717,15 @@ void policy_mgr_activate_mlo_links_nlink(struct wlan_objmgr_psoc *psoc,
 				     reason, mode, 0,
 				     active_link_bitmap, inactive_link_bitmap,
 				     link_ctrl_flags);
+	if (active_link_bitmap)
+		ml_nlink_vendor_command_set_link(
+			psoc, session_id,
+			LINK_CONTROL_MODE_USER,
+			MLO_LINK_FORCE_REASON_CONNECT,
+			MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
+			0, active_link_bitmap,
+			inactive_link_bitmap);
+
 done:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
 }
@@ -8733,6 +8742,8 @@ void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 	struct wlan_objmgr_vdev *vdev;
 	uint8_t *link_mac_addr;
 	bool active_vdev_present = false;
+	uint16_t active_link_bitmap = 0;
+	uint16_t inactive_link_bitmap = 0;
 
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
 						    WLAN_POLICY_MGR_ID);
@@ -8766,6 +8777,8 @@ void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 					 QDF_MAC_ADDR_SIZE)) {
 				active_vdev_lst[active_vdev_cnt] =
 					wlan_vdev_get_id(tmp_vdev_lst[idx]);
+				active_link_bitmap |=
+				1 << wlan_vdev_get_link_id(tmp_vdev_lst[idx]);
 				active_vdev_cnt++;
 				active_vdev_present = true;
 				policy_mgr_debug("Link address match");
@@ -8774,6 +8787,9 @@ void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 		if (!active_vdev_present) {
 			inactive_vdev_lst[inactive_vdev_cnt] =
 					wlan_vdev_get_id(tmp_vdev_lst[idx]);
+			inactive_link_bitmap |=
+			1 << wlan_vdev_get_link_id(tmp_vdev_lst[idx]);
+
 			inactive_vdev_cnt++;
 			policy_mgr_err("No link address match");
 		}
@@ -8806,6 +8822,15 @@ void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 					    MLO_LINK_FORCE_REASON_DISCONNECT,
 					    MLO_LINK_FORCE_MODE_ACTIVE,
 					    active_vdev_cnt, active_vdev_lst);
+	if (active_link_bitmap)
+		ml_nlink_vendor_command_set_link(
+			psoc, session_id,
+			LINK_CONTROL_MODE_USER,
+			MLO_LINK_FORCE_REASON_CONNECT,
+			MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
+			0, active_link_bitmap,
+			inactive_link_bitmap);
+
 ref_release:
 	for (idx = 0; idx < ml_vdev_cnt; idx++)
 		mlo_release_vdev_ref(tmp_vdev_lst[idx]);
@@ -8832,6 +8857,9 @@ policy_mgr_update_mlo_links_based_on_linkid(struct wlan_objmgr_psoc *psoc,
 	uint8_t ml_sta_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
 	qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	uint32_t active_link_bitmap = 0;
+	uint32_t inactive_link_bitmap = 0;
+	bool update_vendor_cmd = false;
 
 	for (idx = 0; idx < num_links; idx++) {
 		if (config_state_list[idx] == 0)
@@ -8877,10 +8905,12 @@ policy_mgr_update_mlo_links_based_on_linkid(struct wlan_objmgr_psoc *psoc,
 				if (config_state_list[link]) {
 					active_vdev_lst[active_vdev_cnt] =
 						wlan_vdev_get_id(vdev_lst[idx]);
+					active_link_bitmap |= 1 << link_id;
 					active_vdev_cnt++;
 				} else {
 					inactive_vdev_lst[inactive_vdev_cnt] =
 						wlan_vdev_get_id(vdev_lst[idx]);
+					inactive_link_bitmap |= 1 << link_id;
 					inactive_vdev_cnt++;
 				}
 			}
@@ -8939,6 +8969,10 @@ policy_mgr_update_mlo_links_based_on_linkid(struct wlan_objmgr_psoc *psoc,
 					MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
 					active_vdev_cnt, active_vdev_lst,
 					inactive_vdev_cnt, inactive_vdev_lst);
+			if (status == QDF_STATUS_E_PENDING ||
+			    status == QDF_STATUS_SUCCESS)
+				update_vendor_cmd = true;
+
 			goto release_ml_vdev_ref;
 		}
 	} else {
@@ -8965,18 +8999,33 @@ policy_mgr_update_mlo_links_based_on_linkid(struct wlan_objmgr_psoc *psoc,
 		 * active vdev count, send single WMI for all active vdevs
 		 * with force mode MLO_LINK_FORCE_MODE_ACTIVE.
 		 */
-		if (active_vdev_cnt && inactive_vdev_cnt)
+		if (active_vdev_cnt && inactive_vdev_cnt) {
 			status = policy_mgr_mlo_sta_set_link_ext(psoc,
 					MLO_LINK_FORCE_REASON_CONNECT,
 					MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
 					active_vdev_cnt, active_vdev_lst,
 					inactive_vdev_cnt, inactive_vdev_lst);
-		else if (active_vdev_cnt && !inactive_vdev_cnt)
+			if (status == QDF_STATUS_E_PENDING ||
+			    status == QDF_STATUS_SUCCESS)
+				update_vendor_cmd = true;
+		} else if (active_vdev_cnt && !inactive_vdev_cnt) {
 			status = policy_mgr_mlo_sta_set_link(psoc,
 					MLO_LINK_FORCE_REASON_DISCONNECT,
 					MLO_LINK_FORCE_MODE_ACTIVE,
 					active_vdev_cnt, active_vdev_lst);
+			if (status == QDF_STATUS_E_PENDING ||
+			    status == QDF_STATUS_SUCCESS)
+				update_vendor_cmd = true;
+		}
 	}
+	if (update_vendor_cmd)
+		ml_nlink_vendor_command_set_link(
+			psoc, vdev_id,
+			LINK_CONTROL_MODE_USER,
+			MLO_LINK_FORCE_REASON_CONNECT,
+			MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
+			0, active_link_bitmap,
+			inactive_link_bitmap);
 
 release_ml_vdev_ref:
 	for (idx = 0; idx < ml_vdev_cnt; idx++)
@@ -9106,13 +9155,15 @@ QDF_STATUS policy_mgr_update_active_mlo_num_links(struct wlan_objmgr_psoc *psoc,
 						  uint8_t vdev_id,
 						  uint8_t force_active_cnt)
 {
-	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_vdev *vdev, *tmp_vdev;
 	uint8_t num_ml_sta = 0, num_disabled_ml_sta = 0, num_non_ml = 0;
 	uint8_t num_enabled_ml_sta = 0, conn_count;
 	uint8_t ml_sta_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
 	qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	uint16_t link_bitmap = 0;
+	uint8_t i;
 
 	if (policy_mgr_is_emlsr_sta_concurrency_present(psoc)) {
 		policy_mgr_debug("Concurrency exists, cannot enter EMLSR mode");
@@ -9248,8 +9299,33 @@ set_link:
 					     MLO_LINK_FORCE_MODE_ACTIVE_NUM,
 					     num_ml_sta, ml_sta_vdev_lst,
 					     force_active_cnt);
-	if (QDF_IS_STATUS_SUCCESS(status))
+	if (QDF_IS_STATUS_SUCCESS(status)) {
 		policy_mgr_debug("vdev %d: link enable allowed", vdev_id);
+		for (i = 0; i < num_ml_sta; i++) {
+			if (i >= force_active_cnt)
+				break;
+			tmp_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
+				psoc, ml_sta_vdev_lst[i],
+				WLAN_POLICY_MGR_ID);
+			if (!tmp_vdev) {
+				policy_mgr_err("vdev not found for vdev_id %d ",
+					       ml_sta_vdev_lst[i]);
+				continue;
+			}
+
+			link_bitmap |= 1 << wlan_vdev_get_link_id(tmp_vdev);
+			wlan_objmgr_vdev_release_ref(tmp_vdev,
+						     WLAN_POLICY_MGR_ID);
+		}
+		ml_nlink_vendor_command_set_link(
+			psoc, vdev_id,
+			LINK_CONTROL_MODE_MIXED,
+			MLO_LINK_FORCE_REASON_CONNECT,
+			MLO_LINK_FORCE_MODE_ACTIVE_NUM,
+			force_active_cnt,
+			link_bitmap,
+			0);
+	}
 
 release_vdev_ref:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
@@ -9293,6 +9369,10 @@ policy_mgr_clear_ml_links_settings_in_fw(struct wlan_objmgr_psoc *psoc,
 		policy_mgr_err("vdev: %d Invalid Context", vdev_id);
 		goto release_vdev_ref;
 	}
+	/* Clear all user vendor command setting for switching to "default" */
+	ml_nlink_vendor_command_set_link(psoc, vdev_id,
+					 LINK_CONTROL_MODE_DEFAULT,
+					 0, 0, 0, 0, 0);
 
 	policy_mgr_get_ml_sta_info(pm_ctx, &num_ml_sta, &num_disabled_ml_sta,
 				   ml_sta_vdev_lst, ml_freq_lst, &num_non_ml,

+ 55 - 0
components/umac/mlme/mlo_mgr/inc/wlan_mlo_link_force.h

@@ -38,6 +38,7 @@
  * @ml_nlink_ap_stopped_evt: SAP/GO bss stopped
  * @ml_nlink_connection_updated_evt: connection home channel changed
  * @ml_nlink_tdls_request_evt: tdls request link enable/disable
+ * @ml_nlink_vendor_cmd_request_evt: vendor command request
  */
 enum ml_nlink_change_event_type {
 	ml_nlink_link_switch_start_evt,
@@ -52,6 +53,26 @@ enum ml_nlink_change_event_type {
 	ml_nlink_ap_stopped_evt,
 	ml_nlink_connection_updated_evt,
 	ml_nlink_tdls_request_evt,
+	ml_nlink_vendor_cmd_request_evt,
+};
+
+/**
+ * enum link_control_modes - the types of MLO links state
+ * control modes. This enum is internal mapping of
+ * qca_wlan_vendor_link_state_control_modes.
+ * @LINK_CONTROL_MODE_DEFAULT: MLO links state controlled
+ * by the driver.
+ * @LINK_CONTROL_MODE_USER: MLO links state controlled by
+ * user space.
+ * @LINK_CONTROL_MODE_MIXED: User space provides the
+ * desired number of MLO links to operate in active state at any given time.
+ * The driver will choose which MLO links should operate in the active state.
+ * See enum qca_wlan_vendor_link_state for active state definition.
+ */
+enum link_control_modes {
+	LINK_CONTROL_MODE_DEFAULT = 0,
+	LINK_CONTROL_MODE_USER = 1,
+	LINK_CONTROL_MODE_MIXED = 2,
 };
 
 /**
@@ -59,6 +80,7 @@ enum ml_nlink_change_event_type {
  * @evt: event parameters
  * @link_switch: link switch start parameters
  * @tdls: tdls parameters
+ * @vendor: vendor command set link parameters
  */
 struct ml_nlink_change_event {
 	union {
@@ -75,6 +97,14 @@ struct ml_nlink_change_event {
 			enum mlo_link_force_mode mode;
 			enum mlo_link_force_reason reason;
 		} tdls;
+		struct {
+			enum link_control_modes link_ctrl_mode;
+			uint8_t link_num;
+			uint32_t link_bitmap;
+			uint32_t link_bitmap2;
+			enum mlo_link_force_mode mode;
+			enum mlo_link_force_reason reason;
+		} vendor;
 	} evt;
 };
 
@@ -119,6 +149,7 @@ static inline const char *link_evt_to_string(uint32_t evt)
 	CASE_RETURN_STRING(ml_nlink_ap_stopped_evt);
 	CASE_RETURN_STRING(ml_nlink_connection_updated_evt);
 	CASE_RETURN_STRING(ml_nlink_tdls_request_evt);
+	CASE_RETURN_STRING(ml_nlink_vendor_cmd_request_evt);
 	default:
 		return "Unknown";
 	}
@@ -352,6 +383,30 @@ void
 ml_nlink_clr_force_state(struct wlan_objmgr_psoc *psoc,
 			 struct wlan_objmgr_vdev *vdev);
 
+/**
+ * ml_nlink_vendor_command_set_link() - Update vendor command
+ * set link parameters
+ * @psoc: psoc object
+ * @vdev_id: vdev id
+ * @link_control_mode: link control mode: default, user, mix
+ * @reason: reason to set
+ * @mode: mode to set
+ * @link_num: number of link, valid for mode:
+ * @link_bitmap: link bitmap, valid for mode:
+ * @link_bitmap2: inactive link bitmap, only valid for mode
+ *
+ * Return: void
+ */
+void
+ml_nlink_vendor_command_set_link(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vdev_id,
+				 enum link_control_modes link_control_mode,
+				 enum mlo_link_force_reason reason,
+				 enum mlo_link_force_mode mode,
+				 uint8_t link_num,
+				 uint16_t link_bitmap,
+				 uint16_t link_bitmap2);
+
 /**
  * ml_is_nlink_service_supported() - support nlink or not
  * @psoc: psoc object

+ 157 - 0
components/umac/mlme/mlo_mgr/src/wlan_mlo_link_force.c

@@ -216,6 +216,8 @@ ml_nlink_clr_force_state(struct wlan_objmgr_psoc *psoc,
 	force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state;
 	qdf_mem_zero(force_state, sizeof(*force_state));
 	ml_nlink_dump_force_state(force_state, "");
+	qdf_mem_zero(mlo_dev_ctx->sta_ctx->link_force_ctx.reqs,
+		     sizeof(mlo_dev_ctx->sta_ctx->link_force_ctx.reqs));
 	mlo_dev_lock_release(mlo_dev_ctx);
 }
 
@@ -358,6 +360,78 @@ ml_nlink_set_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc,
 	mlo_dev_lock_release(mlo_dev_ctx);
 }
 
+static void
+ml_nlink_update_force_link_request(struct wlan_objmgr_psoc *psoc,
+				   struct wlan_objmgr_vdev *vdev,
+				   struct set_link_req *req,
+				   enum set_link_source source)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct set_link_req *old;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+	if (source >= SET_LINK_SOURCE_MAX || source < 0) {
+		mlo_err("invalid source %d", source);
+		return;
+	}
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	old = &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[source];
+	*old = *req;
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
+static void
+ml_nlink_get_force_link_request(struct wlan_objmgr_psoc *psoc,
+				struct wlan_objmgr_vdev *vdev,
+				struct set_link_req *req,
+				enum set_link_source source)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct set_link_req *old;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+	if (source >= SET_LINK_SOURCE_MAX || source < 0) {
+		mlo_err("invalid source %d", source);
+		return;
+	}
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	old = &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[source];
+	*req = *old;
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
+static void
+ml_nlink_clr_force_link_request(struct wlan_objmgr_psoc *psoc,
+				struct wlan_objmgr_vdev *vdev,
+				enum set_link_source source)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct set_link_req *req;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+	if (source >= SET_LINK_SOURCE_MAX || source < 0) {
+		mlo_err("invalid source %d", source);
+		return;
+	}
+
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	req = &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[source];
+	qdf_mem_zero(req, sizeof(*req));
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
 void
 ml_nlink_get_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc,
 				    struct wlan_objmgr_vdev *vdev,
@@ -1976,6 +2050,7 @@ ml_nlink_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
 {
 	struct ml_link_force_state curr_force_state = {0};
 	QDF_STATUS status;
+	struct set_link_req vendor_req = {0};
 
 	ml_nlink_get_curr_force_state(psoc, vdev, &curr_force_state);
 
@@ -2015,6 +2090,15 @@ ml_nlink_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
 				  curr_force_state.force_active_bitmap);
 			return QDF_STATUS_SUCCESS;
 		}
+		ml_nlink_get_force_link_request(psoc, vdev, &vendor_req,
+						SET_LINK_FROM_VENDOR_CMD);
+		if (data->evt.tdls.link_bitmap &
+		    vendor_req.force_active_bitmap) {
+			mlo_debug("link_bitmap 0x%x active hold by vendor cmd, 0x%x",
+				  data->evt.tdls.link_bitmap,
+				  vendor_req.force_active_bitmap);
+			return QDF_STATUS_SUCCESS;
+		}
 		break;
 	default:
 		mlo_err("unhandled for tdls force mode %d",
@@ -2042,6 +2126,50 @@ ml_nlink_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
 	return status;
 }
 
+static QDF_STATUS
+ml_nlink_vendor_cmd_handler(struct wlan_objmgr_psoc *psoc,
+			    struct wlan_objmgr_vdev *vdev,
+			    enum ml_nlink_change_event_type evt,
+			    struct ml_nlink_change_event *data)
+{
+	struct set_link_req req = {0};
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	mlo_debug("link ctrl %d mode %d reason %d num %d 0x%x 0x%x",
+		  data->evt.vendor.link_ctrl_mode,
+		  data->evt.vendor.mode,
+		  data->evt.vendor.reason,
+		  data->evt.vendor.link_num,
+		  data->evt.vendor.link_bitmap,
+		  data->evt.vendor.link_bitmap2);
+	switch (data->evt.vendor.link_ctrl_mode) {
+	case LINK_CONTROL_MODE_DEFAULT:
+		ml_nlink_clr_force_link_request(psoc, vdev,
+						SET_LINK_FROM_VENDOR_CMD);
+		break;
+	case LINK_CONTROL_MODE_USER:
+		req.mode = data->evt.vendor.mode;
+		req.reason = data->evt.vendor.reason;
+		req.force_active_bitmap = data->evt.vendor.link_bitmap;
+		req.force_inactive_bitmap = data->evt.vendor.link_bitmap2;
+		ml_nlink_update_force_link_request(psoc, vdev, &req,
+						   SET_LINK_FROM_VENDOR_CMD);
+		break;
+	case LINK_CONTROL_MODE_MIXED:
+		req.mode = data->evt.vendor.mode;
+		req.reason = data->evt.vendor.reason;
+		req.force_active_num = data->evt.vendor.link_num;
+		req.force_active_num_bitmap = data->evt.vendor.link_bitmap;
+		ml_nlink_update_force_link_request(psoc, vdev, &req,
+						   SET_LINK_FROM_VENDOR_CMD);
+		break;
+	default:
+		status = QDF_STATUS_E_INVAL;
+	}
+
+	return status;
+}
+
 static QDF_STATUS
 ml_nlink_swtich_dynamic_inactive_link(struct wlan_objmgr_psoc *psoc,
 				      struct wlan_objmgr_vdev *vdev)
@@ -2215,6 +2343,10 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 		status = ml_nlink_tdls_event_handler(
 			psoc, vdev, evt, data);
 		break;
+	case ml_nlink_vendor_cmd_request_evt:
+		status = ml_nlink_vendor_cmd_handler(
+			psoc, vdev, evt, data);
+		break;
 	default:
 		break;
 	}
@@ -2224,3 +2356,28 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 
 	return status;
 }
+
+void
+ml_nlink_vendor_command_set_link(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vdev_id,
+				 enum link_control_modes link_control_mode,
+				 enum mlo_link_force_reason reason,
+				 enum mlo_link_force_mode mode,
+				 uint8_t link_num,
+				 uint16_t link_bitmap,
+				 uint16_t link_bitmap2)
+{
+	struct ml_nlink_change_event data;
+
+	qdf_mem_zero(&data, sizeof(data));
+	data.evt.vendor.link_ctrl_mode = link_control_mode;
+	data.evt.vendor.mode = mode;
+	data.evt.vendor.reason = reason;
+	data.evt.vendor.link_num = link_num;
+	data.evt.vendor.link_bitmap = link_bitmap;
+	data.evt.vendor.link_bitmap2 = link_bitmap2;
+
+	ml_nlink_conn_change_notify(
+			psoc, vdev_id,
+			ml_nlink_vendor_cmd_request_evt, &data);
+}