Skip to content

Commit

Permalink
wifi: mac80211: fetch and store the EML capability information
Browse files Browse the repository at this point in the history
We need to teach the low level driver about the EML capability which
includes information for EMLSR / EMLMR operation.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230504134511.828474-11-gregory.greenman@intel.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Emmanuel Grumbach authored and Johannes Berg committed Jun 6, 2023
1 parent 08dbff2 commit ce2bb3b
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
35 changes: 35 additions & 0 deletions include/linux/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -4635,6 +4635,41 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)
return sizeof(*mle) + common + mle->variable[0];
}

/**
* ieee80211_mle_get_eml_cap - returns the EML capability
* @data: pointer to the multi link EHT IE
*
* The element is assumed to be big enough. This must be checked by
* ieee80211_mle_size_ok().
* If the EML capability can't be found (the type is not basic, or
* the EML capability presence bit is clear), 0 will be returned.
*/
static inline u16 ieee80211_mle_get_eml_cap(const u8 *data)
{
const struct ieee80211_multi_link_elem *mle = (const void *)data;
u16 control = le16_to_cpu(mle->control);
const u8 *common = mle->variable;

if (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE) !=
IEEE80211_ML_CONTROL_TYPE_BASIC)
return 0;

/* common points now at the beginning of ieee80211_mle_basic_common_info */
common += sizeof(struct ieee80211_mle_basic_common_info);

if (!(control & IEEE80211_MLC_BASIC_PRES_EML_CAPA))
return 0;

if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
common += 1;
if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)
common += 1;
if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY)
common += 2;

return get_unaligned_le16(common);
}

/**
* ieee80211_mle_size_ok - validate multi-link element size
* @data: pointer to the element data
Expand Down
2 changes: 2 additions & 0 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,7 @@ enum ieee80211_offload_flags {
* @ps: power-save mode (STA only). This flag is NOT affected by
* offchannel/dynamic_ps operations.
* @aid: association ID number, valid only when @assoc is true
* @eml_cap: EML capabilities as described in P802.11be_D2.2 Figure 9-1002k.
* @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The
* may filter ARP queries targeted for other addresses than listed here.
* The driver must allow ARP queries targeted for all address listed here
Expand All @@ -1812,6 +1813,7 @@ struct ieee80211_vif_cfg {
bool ibss_creator;
bool ps;
u16 aid;
u16 eml_cap;

__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
int arp_addr_cnt;
Expand Down
11 changes: 11 additions & 0 deletions net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -4838,6 +4838,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
IEEE80211_CONN_DISABLE_EHT)) &&
he_oper) {
const struct cfg80211_bss_ies *cbss_ies;
const struct element *eht_ml_elem;
const u8 *eht_oper_ie;

cbss_ies = rcu_dereference(cbss->ies);
Expand All @@ -4848,6 +4849,16 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
eht_oper = (void *)(eht_oper_ie + 3);
else
eht_oper = NULL;

eht_ml_elem = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_MULTI_LINK,
cbss_ies->data, cbss_ies->len);

/* data + 1 / datalen - 1 since it's an extended element */
if (eht_ml_elem &&
ieee80211_mle_size_ok(eht_ml_elem->data + 1,
eht_ml_elem->datalen - 1))
sdata->vif.cfg.eml_cap =
ieee80211_mle_get_eml_cap(eht_ml_elem->data + 1);
}

/* Allow VHT if at least one channel on the sband supports 80 MHz */
Expand Down

0 comments on commit ce2bb3b

Please sign in to comment.