mirror of
https://github.com/torvalds/linux.git
synced 2024-12-24 11:51:27 +00:00
wifi: mac80211: simplify adding supported rates
Make this a new-style "put" function, and change the parameters to pass more information directly, this makes it usable also for the MLME code. Link: https://msgid.link/20240129202041.f604a03bd728.I8c798ea45b8479ac9982e77d0378af11a09ccdaf@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
e0b5ee9187
commit
147ceae205
@ -2511,12 +2511,6 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef,
|
||||
int ieee80211_parse_bitrates(enum nl80211_chan_width width,
|
||||
const struct ieee80211_supported_band *sband,
|
||||
const u8 *srates, int srates_len, u32 *rates);
|
||||
int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb, bool need_basic,
|
||||
enum nl80211_band band);
|
||||
int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb, bool need_basic,
|
||||
enum nl80211_band band);
|
||||
u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo);
|
||||
void ieee80211_add_s1g_capab_ie(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta_s1g_cap *caps,
|
||||
@ -2526,6 +2520,10 @@ void ieee80211_add_aid_request_ie(struct ieee80211_sub_if_data *sdata,
|
||||
u8 *ieee80211_ie_build_s1g_cap(u8 *pos, struct ieee80211_sta_s1g_cap *s1g_cap);
|
||||
|
||||
/* element building in SKBs */
|
||||
int ieee80211_put_srates_elem(struct sk_buff *skb,
|
||||
const struct ieee80211_supported_band *sband,
|
||||
u32 basic_rates, u32 rate_flags, u32 masked_rates,
|
||||
u8 element_id);
|
||||
void ieee80211_put_he_6ghz_cap(struct sk_buff *skb,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
enum ieee80211_smps_mode smps_mode);
|
||||
|
@ -968,19 +968,19 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
|
||||
int head_len, tail_len;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct mesh_csa_settings *csa;
|
||||
enum nl80211_band band;
|
||||
const struct ieee80211_supported_band *sband;
|
||||
u8 ie_len_he_cap, ie_len_eht_cap;
|
||||
u8 *pos;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon);
|
||||
u32 rate_flags;
|
||||
|
||||
sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh);
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
|
||||
band = chanctx_conf->def.chan->band;
|
||||
rcu_read_unlock();
|
||||
|
||||
sband = ieee80211_get_sband(sdata);
|
||||
rate_flags =
|
||||
ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chanreq.oper);
|
||||
|
||||
ie_len_he_cap = ieee80211_ie_len_he_cap(sdata);
|
||||
ie_len_eht_cap = ieee80211_ie_len_eht_cap(sdata);
|
||||
@ -1107,7 +1107,9 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
|
||||
if (ieee80211_put_srates_elem(skb, sband,
|
||||
sdata->vif.bss_conf.basic_rates,
|
||||
rate_flags, 0, WLAN_EID_SUPP_RATES) ||
|
||||
mesh_add_ds_params_ie(sdata, skb))
|
||||
goto out_free;
|
||||
|
||||
@ -1118,7 +1120,9 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
|
||||
skb_trim(skb, 0);
|
||||
bcn->tail = bcn->head + bcn->head_len;
|
||||
|
||||
if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
|
||||
if (ieee80211_put_srates_elem(skb, sband,
|
||||
sdata->vif.bss_conf.basic_rates,
|
||||
rate_flags, 0, WLAN_EID_EXT_SUPP_RATES) ||
|
||||
mesh_add_rsn_ie(sdata, skb) ||
|
||||
mesh_add_ht_cap_ie(sdata, skb) ||
|
||||
mesh_add_ht_oper_ie(sdata, skb) ||
|
||||
|
@ -264,14 +264,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
if (action != WLAN_SP_MESH_PEERING_CLOSE) {
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum nl80211_band band;
|
||||
u32 rate_flags, basic_rates;
|
||||
|
||||
sband = ieee80211_get_sband(sdata);
|
||||
if (!sband) {
|
||||
err = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
band = sband->band;
|
||||
|
||||
/* capability info */
|
||||
pos = skb_put_zero(skb, 2);
|
||||
@ -280,8 +279,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
|
||||
pos = skb_put(skb, 2);
|
||||
put_unaligned_le16(sta->sta.aid, pos);
|
||||
}
|
||||
if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
|
||||
ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
|
||||
|
||||
rate_flags =
|
||||
ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chanreq.oper);
|
||||
basic_rates = sdata->vif.bss_conf.basic_rates;
|
||||
|
||||
if (ieee80211_put_srates_elem(skb, sband, basic_rates,
|
||||
rate_flags, 0,
|
||||
WLAN_EID_SUPP_RATES) ||
|
||||
ieee80211_put_srates_elem(skb, sband, basic_rates,
|
||||
rate_flags, 0,
|
||||
WLAN_EID_EXT_SUPP_RATES) ||
|
||||
mesh_add_rsn_ie(sdata, skb) ||
|
||||
mesh_add_meshid_ie(sdata, skb) ||
|
||||
mesh_add_meshconf_ie(sdata, skb))
|
||||
|
@ -1110,10 +1110,7 @@ static void ieee80211_assoc_add_rates(struct sk_buff *skb,
|
||||
struct ieee80211_supported_band *sband,
|
||||
struct ieee80211_mgd_assoc_data *assoc_data)
|
||||
{
|
||||
unsigned int rates_len, supp_rates_len;
|
||||
u32 rates = 0;
|
||||
int i, count;
|
||||
u8 *pos;
|
||||
u32 rates;
|
||||
|
||||
if (assoc_data->supp_rates_len) {
|
||||
/*
|
||||
@ -1122,53 +1119,23 @@ static void ieee80211_assoc_add_rates(struct sk_buff *skb,
|
||||
* in the association request (e.g. D-Link DAP 1353 in
|
||||
* b-only mode)...
|
||||
*/
|
||||
rates_len = ieee80211_parse_bitrates(width, sband,
|
||||
assoc_data->supp_rates,
|
||||
assoc_data->supp_rates_len,
|
||||
&rates);
|
||||
ieee80211_parse_bitrates(width, sband,
|
||||
assoc_data->supp_rates,
|
||||
assoc_data->supp_rates_len,
|
||||
&rates);
|
||||
} else {
|
||||
/*
|
||||
* In case AP not provide any supported rates information
|
||||
* before association, we send information element(s) with
|
||||
* all rates that we support.
|
||||
*/
|
||||
rates_len = sband->n_bitrates;
|
||||
for (i = 0; i < sband->n_bitrates; i++)
|
||||
rates |= BIT(i);
|
||||
rates = ~0;
|
||||
}
|
||||
|
||||
supp_rates_len = rates_len;
|
||||
if (supp_rates_len > 8)
|
||||
supp_rates_len = 8;
|
||||
|
||||
pos = skb_put(skb, supp_rates_len + 2);
|
||||
*pos++ = WLAN_EID_SUPP_RATES;
|
||||
*pos++ = supp_rates_len;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (BIT(i) & rates) {
|
||||
int rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
|
||||
*pos++ = (u8)rate;
|
||||
if (++count == 8)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rates_len > count) {
|
||||
pos = skb_put(skb, rates_len - count + 2);
|
||||
*pos++ = WLAN_EID_EXT_SUPP_RATES;
|
||||
*pos++ = rates_len - count;
|
||||
|
||||
for (i++; i < sband->n_bitrates; i++) {
|
||||
if (BIT(i) & rates) {
|
||||
int rate;
|
||||
|
||||
rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
|
||||
*pos++ = (u8)rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
ieee80211_put_srates_elem(skb, sband, 0, 0, ~rates,
|
||||
WLAN_EID_SUPP_RATES);
|
||||
ieee80211_put_srates_elem(skb, sband, 0, 0, ~rates,
|
||||
WLAN_EID_EXT_SUPP_RATES);
|
||||
}
|
||||
|
||||
static size_t ieee80211_add_before_ht_elems(struct sk_buff *skb,
|
||||
|
@ -382,8 +382,8 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_link_data *link,
|
||||
if (WARN_ON_ONCE(!sband))
|
||||
return;
|
||||
|
||||
ieee80211_add_srates_ie(sdata, skb, false, sband->band);
|
||||
ieee80211_add_ext_srates_ie(sdata, skb, false, sband->band);
|
||||
ieee80211_put_srates_elem(skb, sband, 0, 0, 0, WLAN_EID_SUPP_RATES);
|
||||
ieee80211_put_srates_elem(skb, sband, 0, 0, 0, WLAN_EID_EXT_SUPP_RATES);
|
||||
ieee80211_tdls_add_supp_channels(sdata, skb);
|
||||
|
||||
/* add any custom IEs that go before Extended Capabilities */
|
||||
|
@ -4091,93 +4091,62 @@ int ieee80211_parse_bitrates(enum nl80211_chan_width width,
|
||||
return count;
|
||||
}
|
||||
|
||||
int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb, bool need_basic,
|
||||
enum nl80211_band band)
|
||||
int ieee80211_put_srates_elem(struct sk_buff *skb,
|
||||
const struct ieee80211_supported_band *sband,
|
||||
u32 basic_rates, u32 rate_flags, u32 masked_rates,
|
||||
u8 element_id)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_supported_band *sband;
|
||||
int rate;
|
||||
u8 i, rates, *pos;
|
||||
u32 basic_rates = sdata->vif.bss_conf.basic_rates;
|
||||
u32 rate_flags;
|
||||
u8 i, rates, skip;
|
||||
|
||||
rate_flags =
|
||||
ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chanreq.oper);
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
rates = 0;
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
|
||||
continue;
|
||||
if (masked_rates & BIT(i))
|
||||
continue;
|
||||
rates++;
|
||||
}
|
||||
if (rates > 8)
|
||||
rates = 8;
|
||||
|
||||
if (element_id == WLAN_EID_SUPP_RATES) {
|
||||
rates = min_t(u8, rates, 8);
|
||||
skip = 0;
|
||||
} else {
|
||||
skip = 8;
|
||||
if (rates <= skip)
|
||||
return 0;
|
||||
rates -= skip;
|
||||
}
|
||||
|
||||
if (skb_tailroom(skb) < rates + 2)
|
||||
return -ENOMEM;
|
||||
return -ENOBUFS;
|
||||
|
||||
skb_put_u8(skb, element_id);
|
||||
skb_put_u8(skb, rates);
|
||||
|
||||
for (i = 0; i < sband->n_bitrates && rates; i++) {
|
||||
int rate;
|
||||
u8 basic;
|
||||
|
||||
pos = skb_put(skb, rates + 2);
|
||||
*pos++ = WLAN_EID_SUPP_RATES;
|
||||
*pos++ = rates;
|
||||
for (i = 0; i < rates; i++) {
|
||||
u8 basic = 0;
|
||||
if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
|
||||
continue;
|
||||
|
||||
if (need_basic && basic_rates & BIT(i))
|
||||
basic = 0x80;
|
||||
rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
|
||||
*pos++ = basic | (u8) rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb, bool need_basic,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_supported_band *sband;
|
||||
int rate;
|
||||
u8 i, exrates, *pos;
|
||||
u32 basic_rates = sdata->vif.bss_conf.basic_rates;
|
||||
u32 rate_flags;
|
||||
|
||||
rate_flags =
|
||||
ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chanreq.oper);
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
exrates = 0;
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
|
||||
if (masked_rates & BIT(i))
|
||||
continue;
|
||||
exrates++;
|
||||
}
|
||||
|
||||
if (exrates > 8)
|
||||
exrates -= 8;
|
||||
else
|
||||
exrates = 0;
|
||||
|
||||
if (skb_tailroom(skb) < exrates + 2)
|
||||
return -ENOMEM;
|
||||
|
||||
if (exrates) {
|
||||
pos = skb_put(skb, exrates + 2);
|
||||
*pos++ = WLAN_EID_EXT_SUPP_RATES;
|
||||
*pos++ = exrates;
|
||||
for (i = 8; i < sband->n_bitrates; i++) {
|
||||
u8 basic = 0;
|
||||
if ((rate_flags & sband->bitrates[i].flags)
|
||||
!= rate_flags)
|
||||
continue;
|
||||
if (need_basic && basic_rates & BIT(i))
|
||||
basic = 0x80;
|
||||
rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
|
||||
*pos++ = basic | (u8) rate;
|
||||
if (skip > 0) {
|
||||
skip--;
|
||||
continue;
|
||||
}
|
||||
|
||||
basic = basic_rates & BIT(i) ? 0x80 : 0;
|
||||
|
||||
rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 5);
|
||||
skb_put_u8(skb, basic | (u8)rate);
|
||||
rates--;
|
||||
}
|
||||
|
||||
WARN(rates > 0, "rates confused: rates:%d, element:%d\n",
|
||||
rates, element_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user