diff --git a/umac/mlo_mgr/inc/utils_mlo.h b/umac/mlo_mgr/inc/utils_mlo.h index 8c41af2a69..77b6e68210 100644 --- a/umac/mlo_mgr/inc/utils_mlo.h +++ b/umac/mlo_mgr/inc/utils_mlo.h @@ -224,6 +224,29 @@ util_get_bvmlie_eml_cap(uint8_t *mlieseq, qdf_size_t mlieseqlen, bool *eml_cap_found, uint16_t *eml_cap); +/** + * util_get_bvmlie_msd_cap() - Get the MSD capabilities for Basic variant + * MLO IE + * @mlieseq: Starting address of the Multi-Link element or Multi-Link element + * fragment sequence + * @mlieseqlen: Total length of the Multi-Link element or Multi-Link element + * fragment sequence + * @msd_cap_found: Pointer to the location where a boolean status should be + * updated indicating whether the MSD cabalility was found or not. This should + * be ignored by the caller if the function returns error. + * @msd_cap: Pointer to the location where the MSD capabilities should be + * updated. This should be ignored by the caller if the function indicates + * that the MSD capability was not found. + * + * Get the MSD capabilities from a given Basic variant Multi-Link element or + * element fragment sequence. + * + * Return: QDF_STATUS_SUCCESS in the case of success, QDF_STATUS value giving + * the reason for error in the case of failure + */ +QDF_STATUS +util_get_bvmlie_msd_cap(uint8_t *mlieseq, qdf_size_t mlieseqlen, + bool *msd_cap_found, uint16_t *msd_cap); /** * util_get_bvmlie_primary_linkid() - Get the link identifier * @mlieseq: Starting address of the Multi-Link element or Multi-Link element @@ -463,6 +486,14 @@ util_get_bvmlie_eml_cap(uint8_t *mlieseq, qdf_size_t mlieseqlen, return QDF_STATUS_E_NOSUPPORT; } +static inline QDF_STATUS +util_get_bvmlie_msd_cap(uint8_t *mlieseq, qdf_size_t mlieseqlen, + bool *msd_cap_found, + uint16_t *msd_cap) +{ + return QDF_STATUS_E_NOSUPPORT; +} + static inline QDF_STATUS util_get_bvmlie_primary_linkid(uint8_t *mlieseq, qdf_size_t mlieseqlen, bool *linkidfound, uint8_t *linkid) diff --git a/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h b/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h index 54a9d9890f..2b607ebfc7 100644 --- a/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h +++ b/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h @@ -568,6 +568,18 @@ struct wlan_mlo_eml_cap { reserved:1; }; +/** + * struct wlan_mlo_msd_cap - MSD capabilities of MLD + * @medium_sync_duration: Medium Sync Duration + * @medium_sync_ofdm_ed_thresh: MSD threshold value + * @medium_sync_max_txop_num: Max number of TXOP + */ +struct wlan_mlo_msd_cap { + uint16_t medium_sync_duration:8, + medium_sync_ofdm_ed_thresh:4, + medium_sync_max_txop_num:4; +}; + /** * struct wlan_mlo_mld_cap - MLD capabilities of MLD * @max_simult_link: Maximum number of simultaneous links @@ -607,6 +619,9 @@ struct wlan_mlo_mld_cap { * @nawds_config: eack link peer's NAWDS configuration * @pending_auth: Holds pending auth request * @t2lm_policy: TID-to-link mapping information + * @msd_cap_present: Medium Sync Capability present bit + * @mlpeer_emlcap: EML capability information for ML peer + * @mlpeer_msdcap: Medium Sync Delay capability information for ML peer */ struct wlan_mlo_peer_context { qdf_list_node_t peer_node; @@ -637,7 +652,9 @@ struct wlan_mlo_peer_context { #ifdef WLAN_FEATURE_11BE struct wlan_mlo_peer_t2lm_policy t2lm_policy; #endif + bool msd_cap_present; struct wlan_mlo_eml_cap mlpeer_emlcap; + struct wlan_mlo_msd_cap mlpeer_msdcap; }; /* diff --git a/umac/mlo_mgr/src/utils_mlo.c b/umac/mlo_mgr/src/utils_mlo.c index ae613bcf35..66c6464e29 100644 --- a/umac/mlo_mgr/src/utils_mlo.c +++ b/umac/mlo_mgr/src/utils_mlo.c @@ -2946,6 +2946,90 @@ util_get_bvmlie_eml_cap(uint8_t *mlieseq, qdf_size_t mlieseqlen, return QDF_STATUS_SUCCESS; } +QDF_STATUS +util_get_bvmlie_msd_cap(uint8_t *mlieseq, qdf_size_t mlieseqlen, + bool *msd_cap_found, + uint16_t *msd_cap) +{ + struct wlan_ie_multilink *mlie_fixed; + enum wlan_ml_variant variant; + uint16_t mlcontrol; + uint8_t msd_cap_offset; + uint8_t commoninfo_len; + uint16_t presencebitmap; + + if (!mlieseq || !mlieseqlen || !msd_cap_found || !msd_cap) + return QDF_STATUS_E_NULL_VALUE; + + *msd_cap = 0; + *msd_cap_found = false; + + if (mlieseqlen < sizeof(struct wlan_ie_multilink)) + return QDF_STATUS_E_INVAL; + + mlie_fixed = (struct wlan_ie_multilink *)mlieseq; + + if ((mlie_fixed->elem_id != WLAN_ELEMID_EXTN_ELEM) || + (mlie_fixed->elem_id_ext != WLAN_EXTN_ELEMID_MULTI_LINK)) + return QDF_STATUS_E_INVAL; + + mlcontrol = qdf_le16_to_cpu(mlie_fixed->mlcontrol); + + variant = QDF_GET_BITS(mlcontrol, WLAN_ML_CTRL_TYPE_IDX, + WLAN_ML_CTRL_TYPE_BITS); + + if (variant != WLAN_ML_VARIANT_BASIC) + return QDF_STATUS_E_INVAL; + + presencebitmap = QDF_GET_BITS(mlcontrol, WLAN_ML_CTRL_PBM_IDX, + WLAN_ML_CTRL_PBM_BITS); + + /* msd_cap_offset stores the offset of MSD capabilities within + * Common Info + */ + msd_cap_offset = WLAN_ML_BV_CINFO_LENGTH_SIZE + QDF_MAC_ADDR_SIZE; + if (presencebitmap & WLAN_ML_BV_CTRL_PBM_LINKIDINFO_P) + msd_cap_offset += WLAN_ML_BV_CINFO_LINKIDINFO_SIZE; + if (presencebitmap & WLAN_ML_BV_CTRL_PBM_BSSPARAMCHANGECNT_P) + msd_cap_offset += WLAN_ML_BSSPARAMCHNGCNT_SIZE; + if (presencebitmap & WLAN_ML_BV_CTRL_PBM_MEDIUMSYNCDELAYINFO_P) { + /* Common Info starts at + * mlieseq + sizeof(struct wlan_ie_multilink). + * Check if there is sufficient space in the buffer for + * the Common Info Length. + */ + if (mlieseqlen < (sizeof(struct wlan_ie_multilink) + + WLAN_ML_BV_CINFO_LENGTH_SIZE)) + return QDF_STATUS_E_PROTO; + + /* Check if the value indicated in the Common Info Length + * subfield is sufficient to access the MSD capabilities. + */ + commoninfo_len = *(mlieseq + sizeof(struct wlan_ie_multilink)); + if (commoninfo_len < (msd_cap_offset + + WLAN_ML_BV_CINFO_MEDMSYNCDELAYINFO_SIZE)) + return QDF_STATUS_E_PROTO; + + /* Common Info starts at mlieseq + sizeof(struct + * wlan_ie_multilink). Check if there is sufficient space in + * Common Info for the MSD capability. + */ + if (mlieseqlen < (sizeof(struct wlan_ie_multilink) + + msd_cap_offset + + WLAN_ML_BV_CINFO_MEDMSYNCDELAYINFO_SIZE)) + return QDF_STATUS_E_PROTO; + + *msd_cap_found = true; + *msd_cap = qdf_le16_to_cpu(*(uint16_t *)(mlieseq + + sizeof(struct wlan_ie_multilink) + + msd_cap_offset)); + } else { + mlo_debug("MSD caps not found in assoc rsp"); + } + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS util_get_bvmlie_mldmacaddr(uint8_t *mlieseq, qdf_size_t mlieseqlen, struct qdf_mac_addr *mldmacaddr) diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 347a5789f5..5fd44aa87e 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -1127,6 +1127,7 @@ struct wmi_host_tid_to_link_map_params { * @mlo_force_link_inactive: force the peer inactive * @emlsr_support: indicate if eMLSR supported * @emlmr_support: indicate if eMLMR supported + * @msd_cap_support: indicate if MSD supported * @mld_mac: MLD mac address * @logical_link_index: Unique index for links of the mlo. Starts with Zero * @ml_peer_id: ML peer id if generated by host. Otherwise invalid peer id @@ -1135,6 +1136,9 @@ struct wmi_host_tid_to_link_map_params { * @emlsr_trans_delay_us: eMLSR Transition Delay from peer in us * @emlmr_delay_us: eMLMR Delay from peer in us * @trans_timeout_us: EML Transition Timeout in us + * @medium_sync_duration: medium sync duration in us + * @medium_sync_ofdm_ed_thresh: medium sync ofdm threshold in us + * @medium_sync_max_txop_num: Max number of TXOPs */ struct peer_assoc_mlo_params { uint32_t mlo_enabled:1, @@ -1145,7 +1149,8 @@ struct peer_assoc_mlo_params { mlo_force_link_inactive:1, emlsr_support:1, emlmr_support:1, - unused:25; + msd_cap_support:1, + unused:23; uint8_t mld_mac[QDF_MAC_ADDR_SIZE]; uint32_t logical_link_index; uint32_t ml_peer_id; @@ -1154,6 +1159,9 @@ struct peer_assoc_mlo_params { uint16_t emlsr_trans_delay_us; uint16_t emlmr_delay_us; uint32_t trans_timeout_us; + uint16_t medium_sync_duration; + uint16_t medium_sync_ofdm_ed_thresh; + uint16_t medium_sync_max_txop_num; }; /** diff --git a/wmi/src/wmi_unified_11be_tlv.c b/wmi/src/wmi_unified_11be_tlv.c index 923bcc1652..8c7ac4e38e 100644 --- a/wmi/src/wmi_unified_11be_tlv.c +++ b/wmi/src/wmi_unified_11be_tlv.c @@ -259,6 +259,12 @@ uint8_t *peer_assoc_add_mlo_params(uint8_t *buf_ptr, mlo_params->emlsr_trans_delay_us = req->mlo_params.emlsr_trans_delay_us; mlo_params->emlsr_padding_delay_us = req->mlo_params.emlsr_pad_delay_us; + mlo_params->msd_dur_us = req->mlo_params.medium_sync_duration; + mlo_params->msd_ofdm_ed_thr = + req->mlo_params.medium_sync_ofdm_ed_thresh; + mlo_params->msd_max_num_txops = + req->mlo_params.medium_sync_max_txop_num; + return buf_ptr + sizeof(wmi_peer_assoc_mlo_params); }