qcacmn: Add API to extract MSD caps from cmn info field

Add API to extract MLD AP MSD capabilities from MLO IE
common info field if present. This will be shared with FW
via peer assoc cmd.

Change-Id: I0ebcd5408a40f3314932d4a2a7e586c208af2ee5
CRs-Fixed: 3271118
This commit is contained in:
Gururaj Pandurangi
2022-07-25 18:21:32 -07:00
committed by Madan Koyyalamudi
parent 534715624f
commit 9fa8fc8b46
5 changed files with 147 additions and 1 deletions

View File

@@ -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)

View File

@@ -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;
};
/*

View File

@@ -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)