Commit 74608aca authored by Simon Wunderlich's avatar Simon Wunderlich Committed by Johannes Berg

cfg80211/mac80211: get mandatory rates based on scan width

Mandatory rates for 5 and 10 MHz are different from the rates used for
20 MHz in 2.4 GHz mode, as they use OFDM only.
Signed-off-by: default avatarSimon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: default avatarMathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
parent 2103dec1
...@@ -3128,11 +3128,13 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband, ...@@ -3128,11 +3128,13 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
/** /**
* ieee80211_mandatory_rates - get mandatory rates for a given band * ieee80211_mandatory_rates - get mandatory rates for a given band
* @sband: the band to look for rates in * @sband: the band to look for rates in
* @scan_width: width of the control channel
* *
* This function returns a bitmap of the mandatory rates for the given * This function returns a bitmap of the mandatory rates for the given
* band, bits are set according to the rate position in the bitrates array. * band, bits are set according to the rate position in the bitrates array.
*/ */
u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband); u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
enum nl80211_bss_scan_width scan_width);
/* /*
* Radiotap parsing functions -- for controlled injection support * Radiotap parsing functions -- for controlled injection support
......
...@@ -371,6 +371,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, ...@@ -371,6 +371,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid,
struct sta_info *sta; struct sta_info *sta;
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
enum nl80211_bss_scan_width scan_width;
int band; int band;
/* /*
...@@ -399,6 +400,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, ...@@ -399,6 +400,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid,
if (WARN_ON_ONCE(!chanctx_conf)) if (WARN_ON_ONCE(!chanctx_conf))
return NULL; return NULL;
band = chanctx_conf->def.chan->band; band = chanctx_conf->def.chan->band;
scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
rcu_read_unlock(); rcu_read_unlock();
sta = sta_info_alloc(sdata, addr, GFP_KERNEL); sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
...@@ -412,7 +414,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, ...@@ -412,7 +414,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid,
/* make sure mandatory rates are always added */ /* make sure mandatory rates are always added */
sband = local->hw.wiphy->bands[band]; sband = local->hw.wiphy->bands[band];
sta->sta.supp_rates[band] = supp_rates | sta->sta.supp_rates[band] = supp_rates |
ieee80211_mandatory_rates(sband); ieee80211_mandatory_rates(sband, scan_width);
return ieee80211_ibss_finish_sta(sta); return ieee80211_ibss_finish_sta(sta);
} }
...@@ -476,6 +478,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ...@@ -476,6 +478,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
u64 beacon_timestamp, rx_timestamp; u64 beacon_timestamp, rx_timestamp;
u32 supp_rates = 0; u32 supp_rates = 0;
enum ieee80211_band band = rx_status->band; enum ieee80211_band band = rx_status->band;
enum nl80211_bss_scan_width scan_width;
struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
bool rates_updated = false; bool rates_updated = false;
...@@ -504,9 +507,15 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ...@@ -504,9 +507,15 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
prev_rates = sta->sta.supp_rates[band]; prev_rates = sta->sta.supp_rates[band];
/* make sure mandatory rates are always added */ /* make sure mandatory rates are always added */
sta->sta.supp_rates[band] = supp_rates | scan_width = NL80211_BSS_CHAN_WIDTH_20;
ieee80211_mandatory_rates(sband); if (rx_status->flag & RX_FLAG_5MHZ)
scan_width = NL80211_BSS_CHAN_WIDTH_5;
if (rx_status->flag & RX_FLAG_10MHZ)
scan_width = NL80211_BSS_CHAN_WIDTH_10;
sta->sta.supp_rates[band] = supp_rates |
ieee80211_mandatory_rates(sband,
scan_width);
if (sta->sta.supp_rates[band] != prev_rates) { if (sta->sta.supp_rates[band] != prev_rates) {
ibss_dbg(sdata, ibss_dbg(sdata,
"updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n", "updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n",
...@@ -640,6 +649,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, ...@@ -640,6 +649,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta; struct sta_info *sta;
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
enum nl80211_bss_scan_width scan_width;
int band; int band;
/* /*
...@@ -665,6 +675,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, ...@@ -665,6 +675,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
return; return;
} }
band = chanctx_conf->def.chan->band; band = chanctx_conf->def.chan->band;
scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
rcu_read_unlock(); rcu_read_unlock();
sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
...@@ -676,7 +687,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, ...@@ -676,7 +687,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
/* make sure mandatory rates are always added */ /* make sure mandatory rates are always added */
sband = local->hw.wiphy->bands[band]; sband = local->hw.wiphy->bands[band];
sta->sta.supp_rates[band] = supp_rates | sta->sta.supp_rates[band] = supp_rates |
ieee80211_mandatory_rates(sband); ieee80211_mandatory_rates(sband, scan_width);
spin_lock(&ifibss->incomplete_lock); spin_lock(&ifibss->incomplete_lock);
list_add(&sta->list, &ifibss->incomplete_stations); list_add(&sta->list, &ifibss->incomplete_stations);
......
...@@ -167,9 +167,12 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, ...@@ -167,9 +167,12 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
* basic rates * basic rates
*/ */
if (!setup->basic_rates) { if (!setup->basic_rates) {
enum nl80211_bss_scan_width scan_width;
struct ieee80211_supported_band *sband = struct ieee80211_supported_band *sband =
rdev->wiphy.bands[setup->chandef.chan->band]; rdev->wiphy.bands[setup->chandef.chan->band];
setup->basic_rates = ieee80211_mandatory_rates(sband); scan_width = cfg80211_chandef_to_scan_width(&setup->chandef);
setup->basic_rates = ieee80211_mandatory_rates(sband,
scan_width);
} }
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
......
...@@ -33,7 +33,8 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband, ...@@ -33,7 +33,8 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
} }
EXPORT_SYMBOL(ieee80211_get_response_rate); EXPORT_SYMBOL(ieee80211_get_response_rate);
u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband) u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
enum nl80211_bss_scan_width scan_width)
{ {
struct ieee80211_rate *bitrates; struct ieee80211_rate *bitrates;
u32 mandatory_rates = 0; u32 mandatory_rates = 0;
...@@ -43,10 +44,15 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband) ...@@ -43,10 +44,15 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband)
if (WARN_ON(!sband)) if (WARN_ON(!sband))
return 1; return 1;
if (sband->band == IEEE80211_BAND_2GHZ) if (sband->band == IEEE80211_BAND_2GHZ) {
mandatory_flag = IEEE80211_RATE_MANDATORY_B; if (scan_width == NL80211_BSS_CHAN_WIDTH_5 ||
else scan_width == NL80211_BSS_CHAN_WIDTH_10)
mandatory_flag = IEEE80211_RATE_MANDATORY_G;
else
mandatory_flag = IEEE80211_RATE_MANDATORY_B;
} else {
mandatory_flag = IEEE80211_RATE_MANDATORY_A; mandatory_flag = IEEE80211_RATE_MANDATORY_A;
}
bitrates = sband->bitrates; bitrates = sband->bitrates;
for (i = 0; i < sband->n_bitrates; i++) for (i = 0; i < sband->n_bitrates; i++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment