Sfoglia il codice sorgente

qcacmn: Add force link state API by link id bitmap

Add send_mlo_link_set_active_id_cmd_tlv API to send
force link bitmap to target.

Change-Id: Ie3a41bd2c82b6d10c8d82e4afa83621969c01798
CRs-Fixed: 3515441
Liangwei Dong 2 anni fa
parent
commit
7280363bff

+ 68 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -76,6 +76,9 @@ struct wlan_t2lm_context;
 #define STA_PROFILE_SUB_ELEM_ID 0
 #define PER_STA_PROF_MAC_ADDR_START 4
 
+/* MLO link id max value */
+#define MAX_MLO_LINK_ID 15
+
 #ifdef WLAN_MLO_MULTI_CHIP
 
 #ifndef WLAN_MAX_MLO_GROUPS
@@ -368,6 +371,33 @@ struct mlo_sta_quiet_status {
 	bool valid_status;
 };
 
+/**
+ * struct ml_link_force_state - link force state.
+ * @force_active_bitmap: force active link bitmap
+ * @force_inactive_bitmap: force inactive link bitmap
+ * @force_active_num: force active link num
+ * @force_active_num_bitmap: force active num link bitmap
+ * @force_inactive_num: force inactive link num
+ * @force_inactive_num_bitmap: force inactive num link bitmap
+ */
+struct ml_link_force_state {
+	uint16_t force_active_bitmap;
+	uint16_t force_inactive_bitmap;
+	uint8_t force_active_num;
+	uint16_t force_active_num_bitmap;
+	uint8_t force_inactive_num;
+	uint16_t force_inactive_num_bitmap;
+};
+
+/**
+ * struct wlan_link_force_context - link force ctx.
+ * @force_state: current force active/inactive states which
+ * have been sent to target
+ */
+struct wlan_link_force_context {
+	struct ml_link_force_state force_state;
+};
+
 /*
  * struct wlan_mlo_sta - MLO sta additional info
  * @wlan_connect_req_links: list of vdevs selected for connection with the MLAP
@@ -388,6 +418,7 @@ struct mlo_sta_quiet_status {
  * NB: not using kernel-doc format since the kernel-doc script doesn't
  *     handle the qdf_bitmap() macro
  * @copied_t2lm_ie_assoc_rsp: copy of t2lm ie received in assoc response
+ * @link_force_ctx: set link force mode context
  */
 struct wlan_mlo_sta {
 	qdf_bitmap(wlan_connect_req_links, WLAN_UMAC_MLO_MAX_VDEVS);
@@ -412,6 +443,9 @@ struct wlan_mlo_sta {
 	struct ml_link_state_cmd_info ml_link_state;
 	struct wlan_t2lm_context copied_t2lm_ie_assoc_rsp;
 #endif
+#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+	struct wlan_link_force_context link_force_ctx;
+#endif
 };
 
 /*
@@ -961,6 +995,11 @@ enum mlo_link_force_reason {
  * @active: current active vdev bitmap array
  * @inactive_sz: size of current inactive vdev bitmap array
  * @inactive: current inactive vdev bitmap array
+ * @use_ieee_link_id: link id is valid in active_linkid_bitmap or
+ *	inactive_linkid_bitmap
+ * @ap_mld_mac_addr: AP MLD mac address
+ * @active_linkid_bitmap: current active link id bitmap
+ * @inactive_linkid_bitmap: current inactive link id bitmap
  */
 struct mlo_link_set_active_resp {
 	uint32_t status;
@@ -968,6 +1007,10 @@ struct mlo_link_set_active_resp {
 	uint32_t active[MLO_VDEV_BITMAP_SZ];
 	uint32_t inactive_sz;
 	uint32_t inactive[MLO_VDEV_BITMAP_SZ];
+	bool use_ieee_link_id;
+	struct qdf_mac_addr  ap_mld_mac_addr;
+	uint32_t active_linkid_bitmap;
+	uint32_t inactive_linkid_bitmap;
 };
 
 /**
@@ -1000,6 +1043,25 @@ struct mlo_control_flags {
 	bool dynamic_force_link_num;
 };
 
+/* struct ml_link_force_cmd - force command for links
+ * @ap_mld_mac_addr: AP mld mac address
+ * @ieee_link_id_bitmap: link id bitmap
+ * valid for WMI_MLO_LINK_FORCE_ACTIVE, WMI_MLO_LINK_FORCE_INACTIVE,
+ * WMI_MLO_LINK_NO_FORCE, WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM,
+ * WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM.
+ * @ieee_link_id_bitmap2: link id bitmap, only valid for
+ * WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE carry the inactive linkid bitmap
+ * @link_num: link num
+ * only valid on WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM or
+ * WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM
+ */
+struct ml_link_force_cmd {
+	struct qdf_mac_addr ap_mld_mac_addr;
+	uint16_t ieee_link_id_bitmap;
+	uint16_t ieee_link_id_bitmap2;
+	uint8_t link_num;
+};
+
 /**
  * struct mlo_link_set_active_param: MLO link set active params
  * @force_mode: operation to take (enum mlo_link_force_mode)
@@ -1022,6 +1084,10 @@ struct mlo_control_flags {
  *  It will be present when force_mode is MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
  *  it includes the inactive vdev bitmaps
  * @control_flags: This structure is used for setting wmi_mlo_control_flags.
+ * @use_ieee_link_id: send link id bitmap to target.
+ *  If this value is true, the "force_cmd" field should be provided and
+ *  that will be sent to target
+ * @force_cmd: force command which includes link id bitmap
  */
 struct mlo_link_set_active_param {
 	uint32_t force_mode;
@@ -1033,6 +1099,8 @@ struct mlo_link_set_active_param {
 	uint32_t vdev_bitmap[MLO_VDEV_BITMAP_SZ];
 	uint32_t inactive_vdev_bitmap[MLO_VDEV_BITMAP_SZ];
 	struct mlo_control_flags control_flags;
+	bool use_ieee_link_id;
+	struct ml_link_force_cmd force_cmd;
 };
 
 /**

+ 214 - 1
wmi/src/wmi_unified_11be_tlv.c

@@ -449,6 +449,186 @@ force_reason_host_to_fw(enum mlo_link_force_reason host_reason,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * send_mlo_link_set_active_id_cmd_tlv() - send mlo link set active command
+ * by link id bitmap
+ * @wmi_handle: wmi handle
+ * @param: Pointer to mlo link set active param
+ *
+ * This API will populate link bitmap for corresponding force mode and
+ * send command to target.
+ * Previous API send_mlo_link_set_active_cmd_tlv can only handle vdev
+ * bitmap, if some associated links have no vdev attached, we have to use
+ * this API to do link force active/inactive.
+ * Note: no vdev associated links can be "non forced" state, so that target
+ * can repurpose vdev to such link.
+ * If link with no vdev attached is forced inactive for such concurrency
+ * reason, target will not switch to such link.
+ *
+ * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error
+ */
+static QDF_STATUS
+send_mlo_link_set_active_id_cmd_tlv(wmi_unified_t wmi_handle,
+				    struct mlo_link_set_active_param *param)
+{
+	QDF_STATUS status;
+	wmi_mlo_link_set_active_cmd_fixed_param *cmd;
+	wmi_mlo_set_active_link_number_param *link_num_param;
+	uint32_t *link_bitmap;
+	uint32_t num_link_num_param = 0, num_link_bitmap = 0, tlv_len;
+	uint32_t num_inactive_link_bitmap = 0;
+	wmi_buf_t buf;
+	uint8_t *buf_ptr;
+	uint32_t len;
+	WMITLV_TAG_ID tag_id;
+	WMI_MLO_LINK_FORCE_MODE force_mode;
+	WMI_MLO_LINK_FORCE_REASON force_reason;
+
+	status = force_mode_host_to_fw(param->force_mode, &force_mode);
+	if (QDF_IS_STATUS_ERROR(status))
+		return QDF_STATUS_E_INVAL;
+
+	status = force_reason_host_to_fw(param->reason, &force_reason);
+	if (QDF_IS_STATUS_ERROR(status))
+		return QDF_STATUS_E_INVAL;
+
+	switch (force_mode) {
+	case WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM:
+	case WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM:
+		num_link_num_param = 1;
+		fallthrough;
+	case WMI_MLO_LINK_FORCE_ACTIVE:
+	case WMI_MLO_LINK_FORCE_INACTIVE:
+	case WMI_MLO_LINK_NO_FORCE:
+		num_link_bitmap = 1;
+		break;
+	case WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE:
+		num_link_bitmap = 1;
+		num_inactive_link_bitmap = 1;
+		break;
+	default:
+		wmi_err("Invalid force reason: %d", force_mode);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	len = sizeof(*cmd) +
+	      WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE +
+	      WMI_TLV_HDR_SIZE + sizeof(*link_num_param) * num_link_num_param +
+	      WMI_TLV_HDR_SIZE + sizeof(*link_bitmap) * num_link_bitmap;
+	if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE)
+		len += WMI_TLV_HDR_SIZE +
+		sizeof(*link_bitmap) * num_inactive_link_bitmap;
+
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf)
+		return QDF_STATUS_E_NOMEM;
+
+	buf_ptr = (uint8_t *)wmi_buf_data(buf);
+	cmd = (wmi_mlo_link_set_active_cmd_fixed_param *)buf_ptr;
+	tlv_len = WMITLV_GET_STRUCT_TLVLEN
+			(wmi_mlo_link_set_active_cmd_fixed_param);
+
+	tag_id = WMITLV_TAG_STRUC_wmi_mlo_link_set_active_cmd_fixed_param;
+	WMITLV_SET_HDR(&cmd->tlv_header, tag_id, tlv_len);
+	cmd->force_mode = force_mode;
+	cmd->reason = force_reason;
+	cmd->use_ieee_link_id_bitmap = 1;
+	WMI_CHAR_ARRAY_TO_MAC_ADDR(param->force_cmd.ap_mld_mac_addr.bytes,
+				   &cmd->ap_mld_mac_addr);
+	if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE) {
+		cmd->ctrl_flags.overwrite_force_active_bitmap =
+			param->control_flags.overwrite_force_active_bitmap;
+	} else if (force_mode == WMI_MLO_LINK_FORCE_INACTIVE) {
+		cmd->ctrl_flags.overwrite_force_inactive_bitmap =
+			param->control_flags.overwrite_force_inactive_bitmap;
+	} else if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE) {
+		cmd->ctrl_flags.overwrite_force_active_bitmap =
+			param->control_flags.overwrite_force_active_bitmap;
+		cmd->ctrl_flags.overwrite_force_inactive_bitmap =
+			param->control_flags.overwrite_force_inactive_bitmap;
+	} else {
+		cmd->ctrl_flags.dynamic_force_link_num =
+			param->control_flags.dynamic_force_link_num;
+	}
+
+	wmi_debug("mode %d reason %d num_link_num_param %d num_link_bitmap %d num_inactive %d overwrite %d %d %d",
+		  cmd->force_mode, cmd->reason, num_link_num_param,
+		  num_link_bitmap, num_inactive_link_bitmap,
+		  cmd->ctrl_flags.overwrite_force_active_bitmap,
+		  cmd->ctrl_flags.overwrite_force_inactive_bitmap,
+		  cmd->ctrl_flags.dynamic_force_link_num);
+	wmi_debug("ap mld mac addr: "QDF_MAC_ADDR_FMT,
+		  QDF_MAC_ADDR_REF(param->force_cmd.ap_mld_mac_addr.bytes));
+
+	buf_ptr += sizeof(*cmd);
+
+	/* set num of link tlv */
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+		       sizeof(*link_num_param) * num_link_num_param);
+	buf_ptr += WMI_TLV_HDR_SIZE;
+
+	if (num_link_num_param) {
+		link_num_param =
+			(wmi_mlo_set_active_link_number_param *)buf_ptr;
+		tlv_len = WMITLV_GET_STRUCT_TLVLEN
+				(wmi_mlo_set_active_link_number_param);
+
+		WMITLV_SET_HDR(&link_num_param->tlv_header, 0, tlv_len);
+		link_num_param->num_of_link = param->force_cmd.link_num;
+		wmi_debug("entry[0]: num_of_link %d",
+			  link_num_param->num_of_link);
+
+		buf_ptr += sizeof(*link_num_param) * 1;
+	}
+	/* add empty vdev bitmap tlv */
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
+	buf_ptr += WMI_TLV_HDR_SIZE;
+	/* add empty vdev bitmap2 tlv */
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
+	buf_ptr += WMI_TLV_HDR_SIZE;
+
+	/* add link bitmap tlv */
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
+		       sizeof(*link_bitmap) * num_link_bitmap);
+	buf_ptr += WMI_TLV_HDR_SIZE;
+
+	if (num_link_bitmap) {
+		link_bitmap = (A_UINT32 *)(buf_ptr);
+
+		link_bitmap[0] = param->force_cmd.ieee_link_id_bitmap;
+		wmi_debug("entry[0]: link_bitmap 0x%x ", link_bitmap[0]);
+
+		buf_ptr += sizeof(*link_bitmap) * 1;
+	}
+	/* add link bitmap2 tlv */
+	if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE) {
+		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
+			       sizeof(*link_bitmap) *
+			       num_inactive_link_bitmap);
+		buf_ptr += WMI_TLV_HDR_SIZE;
+
+		if (num_inactive_link_bitmap) {
+			link_bitmap = (A_UINT32 *)(buf_ptr);
+			link_bitmap[0] = param->force_cmd.ieee_link_id_bitmap2;
+			wmi_debug("entry[0]: link_bitmap2 0x%x ",
+				  link_bitmap[0]);
+
+			buf_ptr += sizeof(*link_bitmap) * 1;
+		}
+	}
+
+	wmi_mtrace(WMI_MLO_LINK_SET_ACTIVE_CMDID, 0, cmd->force_mode);
+	status = wmi_unified_cmd_send(wmi_handle, buf, len,
+				      WMI_MLO_LINK_SET_ACTIVE_CMDID);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		wmi_err("Failed to send MLO link set active command to FW: %d",
+			status);
+		wmi_buf_free(buf);
+	}
+
+	return status;
+}
+
 /**
  * send_mlo_link_set_active_cmd_tlv() - send mlo link set active command
  * @wmi_handle: wmi handle
@@ -474,6 +654,16 @@ send_mlo_link_set_active_cmd_tlv(wmi_unified_t wmi_handle,
 	WMI_MLO_LINK_FORCE_MODE force_mode;
 	WMI_MLO_LINK_FORCE_REASON force_reason;
 
+	/* If use_ieee_link_id = true, use new API
+	 * send_mlo_link_set_active_id_cmd_tlv to fill link bitamp
+	 * to wmi buffer.
+	 * And target will indicate event with same flag set to true
+	 * to indicate link bitmap included in the event.
+	 */
+	if (param->use_ieee_link_id)
+		return send_mlo_link_set_active_id_cmd_tlv(wmi_handle,
+							   param);
+
 	if (!param->num_vdev_bitmap && !param->num_link_entry) {
 		wmi_err("No entry is provided vdev bit map %d link entry %d",
 			param->num_vdev_bitmap,
@@ -638,7 +828,30 @@ extract_mlo_link_set_active_resp_tlv(wmi_unified_t wmi_handle, void *evt_buf,
 
 	evt = param_buf->fixed_param;
 	resp->status = evt->status;
-	wmi_debug("status: %u", resp->status);
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&evt->ap_mld_mac_addr,
+				   resp->ap_mld_mac_addr.bytes);
+	wmi_debug("status: %u use linkid %d ap mld:"QDF_MAC_ADDR_FMT,
+		  resp->status,
+		  evt->use_ieee_link_id_bitmap,
+		  QDF_MAC_ADDR_REF(resp->ap_mld_mac_addr.bytes));
+	if (evt->use_ieee_link_id_bitmap) {
+		bitmap = param_buf->force_active_ieee_link_id_bitmap;
+		if (bitmap &&
+		    param_buf->num_force_active_ieee_link_id_bitmap > 0)
+			resp->active_linkid_bitmap = bitmap[0];
+
+		bitmap = param_buf->force_inactive_ieee_link_id_bitmap;
+		if (bitmap &&
+		    param_buf->num_force_inactive_ieee_link_id_bitmap > 0)
+			resp->inactive_linkid_bitmap = bitmap[0];
+		resp->use_ieee_link_id = true;
+		wmi_debug("active links: 0x%x inactive links: 0x%x num: %x %x",
+			  resp->active_linkid_bitmap,
+			  resp->inactive_linkid_bitmap,
+			  param_buf->num_force_active_ieee_link_id_bitmap,
+			  param_buf->num_force_inactive_ieee_link_id_bitmap);
+		return QDF_STATUS_SUCCESS;
+	}
 
 	bitmap = param_buf->force_active_vdev_bitmap;
 	entry_num = qdf_min(param_buf->num_force_active_vdev_bitmap,