mirror of https://gitee.com/openkylin/linux.git
We have:
* fixes for AQL (airtime queue limits) * reduce packet loss detection false positives * a small channel number fix for the 6 GHz band * a fix for 80+80/160 MHz negotiation * an nl80211 attribute (NL80211_ATTR_HE_6GHZ_CAPABILITY) fix * add a missing sanity check for the regulatory code -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAl9I10UACgkQB8qZga/f l8TVrQ/8CNCAhEwaGVj4SxjJAlma7vnMffxR5BXboPsWm3fVzknJnLvlLyTpXJbH lXadT3fv4M9dxKFIqfJiak7LK4c8rv64xeYXelZWVq43S1DjVV3mZOaTehOPbxtM Wo+d9mUkSH7PgbgipHsR01/fdFCEwu0uCqqG6syOj1+f3Pcvaofwv8vZyhtWwkTk ZchvdtU2Q/Nh0SEaIKg6esNogfPBtgSrCX7CV/uNbfeyISL5iSeU6DZeZZLDdcD9 b66PNs+DFAI2XIr/2hmHWtkVOUIhAY9EQfICaBvUZryyvFDR9ycSO5khginZP47/ 88gjJ2loYt9M+p00/FcYXkNzxwdo9tppHQ7XmZi4Ciwt7ADuvDlTdehS/ix93HkS 5hC5UOz8GNy1XZjayqzSVn3AwWuEncRM67NQo3J6qwS1vnF4NKi7rdwSDO49OX3V aDAXGiALo2V9ZgbtOOlSbUl1y107mPtemkmdAOcMvXCLXFYixUeUgULTvl4S72fk RVxb0xp7lJ0T5hFXGGcTO/MV9X5Rg/d/Y1AKhCy3Wt2bdNk0K5JOcblnrXp8dz83 qveiscDy4B6NEnaPOffS5z/7E5wXIN77L9TYKOnQ/v8Gu+r15imyzcgz/s8EvRmJ rWhB45SUhc5CBIjTFa4iR8M8u1Wc/a+I5Zht39VRTCLtDlOADZw= =zMP7 -----END PGP SIGNATURE----- Merge tag 'mac80211-for-davem-2020-08-28' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Johannes Berg says: ==================== We have: * fixes for AQL (airtime queue limits) * reduce packet loss detection false positives * a small channel number fix for the 6 GHz band * a fix for 80+80/160 MHz negotiation * an nl80211 attribute (NL80211_ATTR_HE_6GHZ_CAPABILITY) fix * add a missing sanity check for the regulatory code ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
51458c9705
|
@ -405,18 +405,14 @@ ieee80211_calc_legacy_rate_duration(u16 bitrate, bool short_pre,
|
|||
return duration;
|
||||
}
|
||||
|
||||
u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
|
||||
struct ieee80211_rx_status *status,
|
||||
int len)
|
||||
static u32 ieee80211_get_rate_duration(struct ieee80211_hw *hw,
|
||||
struct ieee80211_rx_status *status,
|
||||
u32 *overhead)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
const struct ieee80211_rate *rate;
|
||||
bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI;
|
||||
bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE;
|
||||
int bw, streams;
|
||||
int group, idx;
|
||||
u32 duration;
|
||||
bool cck;
|
||||
|
||||
switch (status->bw) {
|
||||
case RATE_INFO_BW_20:
|
||||
|
@ -437,20 +433,6 @@ u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
switch (status->encoding) {
|
||||
case RX_ENC_LEGACY:
|
||||
if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ))
|
||||
return 0;
|
||||
|
||||
sband = hw->wiphy->bands[status->band];
|
||||
if (!sband || status->rate_idx >= sband->n_bitrates)
|
||||
return 0;
|
||||
|
||||
rate = &sband->bitrates[status->rate_idx];
|
||||
cck = rate->flags & IEEE80211_RATE_MANDATORY_B;
|
||||
|
||||
return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp,
|
||||
cck, len);
|
||||
|
||||
case RX_ENC_VHT:
|
||||
streams = status->nss;
|
||||
idx = status->rate_idx;
|
||||
|
@ -477,51 +459,144 @@ u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
|
|||
|
||||
duration = airtime_mcs_groups[group].duration[idx];
|
||||
duration <<= airtime_mcs_groups[group].shift;
|
||||
*overhead = 36 + (streams << 2);
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
|
||||
u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
|
||||
struct ieee80211_rx_status *status,
|
||||
int len)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
u32 duration, overhead = 0;
|
||||
|
||||
if (status->encoding == RX_ENC_LEGACY) {
|
||||
const struct ieee80211_rate *rate;
|
||||
bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE;
|
||||
bool cck;
|
||||
|
||||
if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ))
|
||||
return 0;
|
||||
|
||||
sband = hw->wiphy->bands[status->band];
|
||||
if (!sband || status->rate_idx >= sband->n_bitrates)
|
||||
return 0;
|
||||
|
||||
rate = &sband->bitrates[status->rate_idx];
|
||||
cck = rate->flags & IEEE80211_RATE_MANDATORY_B;
|
||||
|
||||
return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp,
|
||||
cck, len);
|
||||
}
|
||||
|
||||
duration = ieee80211_get_rate_duration(hw, status, &overhead);
|
||||
if (!duration)
|
||||
return 0;
|
||||
|
||||
duration *= len;
|
||||
duration /= AVG_PKT_SIZE;
|
||||
duration /= 1024;
|
||||
|
||||
duration += 36 + (streams << 2);
|
||||
|
||||
return duration;
|
||||
return duration + overhead;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime);
|
||||
|
||||
static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_rate *rate,
|
||||
u8 band, int len)
|
||||
static bool ieee80211_fill_rate_info(struct ieee80211_hw *hw,
|
||||
struct ieee80211_rx_status *stat, u8 band,
|
||||
struct rate_info *ri)
|
||||
{
|
||||
struct ieee80211_rx_status stat = {
|
||||
.band = band,
|
||||
};
|
||||
struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
|
||||
int i;
|
||||
|
||||
if (rate->idx < 0 || !rate->count)
|
||||
if (!ri || !sband)
|
||||
return false;
|
||||
|
||||
stat->bw = ri->bw;
|
||||
stat->nss = ri->nss;
|
||||
stat->rate_idx = ri->mcs;
|
||||
|
||||
if (ri->flags & RATE_INFO_FLAGS_HE_MCS)
|
||||
stat->encoding = RX_ENC_HE;
|
||||
else if (ri->flags & RATE_INFO_FLAGS_VHT_MCS)
|
||||
stat->encoding = RX_ENC_VHT;
|
||||
else if (ri->flags & RATE_INFO_FLAGS_MCS)
|
||||
stat->encoding = RX_ENC_HT;
|
||||
else
|
||||
stat->encoding = RX_ENC_LEGACY;
|
||||
|
||||
if (ri->flags & RATE_INFO_FLAGS_SHORT_GI)
|
||||
stat->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
|
||||
stat->he_gi = ri->he_gi;
|
||||
|
||||
if (stat->encoding != RX_ENC_LEGACY)
|
||||
return true;
|
||||
|
||||
stat->rate_idx = 0;
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (ri->legacy != sband->bitrates[i].bitrate)
|
||||
continue;
|
||||
|
||||
stat->rate_idx = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ieee80211_fill_rx_status(struct ieee80211_rx_status *stat,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_rate *rate,
|
||||
struct rate_info *ri, u8 band, int len)
|
||||
{
|
||||
memset(stat, 0, sizeof(*stat));
|
||||
stat->band = band;
|
||||
|
||||
if (ieee80211_fill_rate_info(hw, stat, band, ri))
|
||||
return 0;
|
||||
|
||||
if (rate->idx < 0 || !rate->count)
|
||||
return -1;
|
||||
|
||||
if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
|
||||
stat.bw = RATE_INFO_BW_80;
|
||||
stat->bw = RATE_INFO_BW_80;
|
||||
else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
|
||||
stat.bw = RATE_INFO_BW_40;
|
||||
stat->bw = RATE_INFO_BW_40;
|
||||
else
|
||||
stat.bw = RATE_INFO_BW_20;
|
||||
stat->bw = RATE_INFO_BW_20;
|
||||
|
||||
stat.enc_flags = 0;
|
||||
stat->enc_flags = 0;
|
||||
if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
|
||||
stat.enc_flags |= RX_ENC_FLAG_SHORTPRE;
|
||||
stat->enc_flags |= RX_ENC_FLAG_SHORTPRE;
|
||||
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
|
||||
stat.enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
stat->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
|
||||
stat.rate_idx = rate->idx;
|
||||
stat->rate_idx = rate->idx;
|
||||
if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
|
||||
stat.encoding = RX_ENC_VHT;
|
||||
stat.rate_idx = ieee80211_rate_get_vht_mcs(rate);
|
||||
stat.nss = ieee80211_rate_get_vht_nss(rate);
|
||||
stat->encoding = RX_ENC_VHT;
|
||||
stat->rate_idx = ieee80211_rate_get_vht_mcs(rate);
|
||||
stat->nss = ieee80211_rate_get_vht_nss(rate);
|
||||
} else if (rate->flags & IEEE80211_TX_RC_MCS) {
|
||||
stat.encoding = RX_ENC_HT;
|
||||
stat->encoding = RX_ENC_HT;
|
||||
} else {
|
||||
stat.encoding = RX_ENC_LEGACY;
|
||||
stat->encoding = RX_ENC_LEGACY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_rate *rate,
|
||||
struct rate_info *ri,
|
||||
u8 band, int len)
|
||||
{
|
||||
struct ieee80211_rx_status stat;
|
||||
|
||||
if (ieee80211_fill_rx_status(&stat, hw, rate, ri, band, len))
|
||||
return 0;
|
||||
|
||||
return ieee80211_calc_rx_airtime(hw, &stat, len);
|
||||
}
|
||||
|
||||
|
@ -536,7 +611,7 @@ u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
|
|||
struct ieee80211_tx_rate *rate = &info->status.rates[i];
|
||||
u32 cur_duration;
|
||||
|
||||
cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate,
|
||||
cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate, NULL,
|
||||
info->band, len);
|
||||
if (!cur_duration)
|
||||
break;
|
||||
|
@ -572,26 +647,41 @@ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
|
|||
if (pubsta) {
|
||||
struct sta_info *sta = container_of(pubsta, struct sta_info,
|
||||
sta);
|
||||
struct ieee80211_rx_status stat;
|
||||
struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate;
|
||||
u32 airtime;
|
||||
struct rate_info *ri = &sta->tx_stats.last_rate_info;
|
||||
u32 duration, overhead;
|
||||
u8 agg_shift;
|
||||
|
||||
if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS |
|
||||
IEEE80211_TX_RC_MCS)))
|
||||
ampdu = false;
|
||||
if (ieee80211_fill_rx_status(&stat, hw, rate, ri, band, len))
|
||||
return 0;
|
||||
|
||||
if (stat.encoding == RX_ENC_LEGACY || !ampdu)
|
||||
return ieee80211_calc_rx_airtime(hw, &stat, len);
|
||||
|
||||
duration = ieee80211_get_rate_duration(hw, &stat, &overhead);
|
||||
/*
|
||||
* Assume that HT/VHT transmission on any AC except VO will
|
||||
* use aggregation. Since we don't have reliable reporting
|
||||
* of aggregation length, assume an average of 16.
|
||||
* of aggregation length, assume an average size based on the
|
||||
* tx rate.
|
||||
* This will not be very accurate, but much better than simply
|
||||
* assuming un-aggregated tx.
|
||||
* assuming un-aggregated tx in all cases.
|
||||
*/
|
||||
airtime = ieee80211_calc_tx_airtime_rate(hw, rate, band,
|
||||
ampdu ? len * 16 : len);
|
||||
if (ampdu)
|
||||
airtime /= 16;
|
||||
if (duration > 400) /* <= VHT20 MCS2 1S */
|
||||
agg_shift = 1;
|
||||
else if (duration > 250) /* <= VHT20 MCS3 1S or MCS1 2S */
|
||||
agg_shift = 2;
|
||||
else if (duration > 150) /* <= VHT20 MCS5 1S or MCS3 2S */
|
||||
agg_shift = 3;
|
||||
else
|
||||
agg_shift = 4;
|
||||
|
||||
return airtime;
|
||||
duration *= len;
|
||||
duration /= AVG_PKT_SIZE;
|
||||
duration /= 1024;
|
||||
|
||||
return duration + (overhead >> agg_shift);
|
||||
}
|
||||
|
||||
if (!conf)
|
||||
|
|
|
@ -524,7 +524,7 @@ struct ieee80211_sta_rx_stats {
|
|||
* @status_stats.retry_failed: # of frames that failed after retry
|
||||
* @status_stats.retry_count: # of retries attempted
|
||||
* @status_stats.lost_packets: # of lost packets
|
||||
* @status_stats.last_tdls_pkt_time: timestamp of last TDLS packet
|
||||
* @status_stats.last_pkt_time: timestamp of last ACKed packet
|
||||
* @status_stats.msdu_retries: # of MSDU retries
|
||||
* @status_stats.msdu_failed: # of failed MSDUs
|
||||
* @status_stats.last_ack: last ack timestamp (jiffies)
|
||||
|
@ -597,7 +597,7 @@ struct sta_info {
|
|||
unsigned long filtered;
|
||||
unsigned long retry_failed, retry_count;
|
||||
unsigned int lost_packets;
|
||||
unsigned long last_tdls_pkt_time;
|
||||
unsigned long last_pkt_time;
|
||||
u64 msdu_retries[IEEE80211_NUM_TIDS + 1];
|
||||
u64 msdu_failed[IEEE80211_NUM_TIDS + 1];
|
||||
unsigned long last_ack;
|
||||
|
@ -611,6 +611,7 @@ struct sta_info {
|
|||
u64 packets[IEEE80211_NUM_ACS];
|
||||
u64 bytes[IEEE80211_NUM_ACS];
|
||||
struct ieee80211_tx_rate last_rate;
|
||||
struct rate_info last_rate_info;
|
||||
u64 msdu[IEEE80211_NUM_TIDS + 1];
|
||||
} tx_stats;
|
||||
u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
|
||||
|
|
|
@ -755,12 +755,16 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
|
|||
* - current throughput (higher value for higher tpt)?
|
||||
*/
|
||||
#define STA_LOST_PKT_THRESHOLD 50
|
||||
#define STA_LOST_PKT_TIME HZ /* 1 sec since last ACK */
|
||||
#define STA_LOST_TDLS_PKT_THRESHOLD 10
|
||||
#define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */
|
||||
|
||||
static void ieee80211_lost_packet(struct sta_info *sta,
|
||||
struct ieee80211_tx_info *info)
|
||||
{
|
||||
unsigned long pkt_time = STA_LOST_PKT_TIME;
|
||||
unsigned int pkt_thr = STA_LOST_PKT_THRESHOLD;
|
||||
|
||||
/* If driver relies on its own algorithm for station kickout, skip
|
||||
* mac80211 packet loss mechanism.
|
||||
*/
|
||||
|
@ -773,21 +777,20 @@ static void ieee80211_lost_packet(struct sta_info *sta,
|
|||
return;
|
||||
|
||||
sta->status_stats.lost_packets++;
|
||||
if (!sta->sta.tdls &&
|
||||
sta->status_stats.lost_packets < STA_LOST_PKT_THRESHOLD)
|
||||
return;
|
||||
if (sta->sta.tdls) {
|
||||
pkt_time = STA_LOST_TDLS_PKT_TIME;
|
||||
pkt_thr = STA_LOST_PKT_THRESHOLD;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're in TDLS mode, make sure that all STA_LOST_TDLS_PKT_THRESHOLD
|
||||
* of the last packets were lost, and that no ACK was received in the
|
||||
* last STA_LOST_TDLS_PKT_TIME ms, before triggering the CQM packet-loss
|
||||
* mechanism.
|
||||
* For non-TDLS, use STA_LOST_PKT_THRESHOLD and STA_LOST_PKT_TIME
|
||||
*/
|
||||
if (sta->sta.tdls &&
|
||||
(sta->status_stats.lost_packets < STA_LOST_TDLS_PKT_THRESHOLD ||
|
||||
time_before(jiffies,
|
||||
sta->status_stats.last_tdls_pkt_time +
|
||||
STA_LOST_TDLS_PKT_TIME)))
|
||||
if (sta->status_stats.lost_packets < pkt_thr ||
|
||||
!time_after(jiffies, sta->status_stats.last_pkt_time + pkt_time))
|
||||
return;
|
||||
|
||||
cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
|
||||
|
@ -1033,9 +1036,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
|||
sta->status_stats.lost_packets = 0;
|
||||
|
||||
/* Track when last TDLS packet was ACKed */
|
||||
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
||||
sta->status_stats.last_tdls_pkt_time =
|
||||
jiffies;
|
||||
sta->status_stats.last_pkt_time = jiffies;
|
||||
} else if (noack_success) {
|
||||
/* nothing to do here, do not account as lost */
|
||||
} else {
|
||||
|
@ -1137,9 +1138,17 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
|||
struct ieee80211_tx_info *info = status->info;
|
||||
struct ieee80211_sta *pubsta = status->sta;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct sta_info *sta;
|
||||
int retry_count;
|
||||
bool acked, noack_success;
|
||||
|
||||
if (pubsta) {
|
||||
sta = container_of(pubsta, struct sta_info, sta);
|
||||
|
||||
if (status->rate)
|
||||
sta->tx_stats.last_rate_info = *status->rate;
|
||||
}
|
||||
|
||||
if (status->skb)
|
||||
return __ieee80211_tx_status(hw, status);
|
||||
|
||||
|
@ -1154,10 +1163,6 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
|||
noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
|
||||
|
||||
if (pubsta) {
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = container_of(pubsta, struct sta_info, sta);
|
||||
|
||||
if (!acked && !noack_success)
|
||||
sta->status_stats.retry_failed++;
|
||||
sta->status_stats.retry_count += retry_count;
|
||||
|
@ -1168,9 +1173,8 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
|||
if (sta->status_stats.lost_packets)
|
||||
sta->status_stats.lost_packets = 0;
|
||||
|
||||
/* Track when last TDLS packet was ACKed */
|
||||
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
||||
sta->status_stats.last_tdls_pkt_time = jiffies;
|
||||
/* Track when last packet was ACKed */
|
||||
sta->status_stats.last_pkt_time = jiffies;
|
||||
} else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||
return;
|
||||
} else if (noack_success) {
|
||||
|
@ -1259,8 +1263,7 @@ void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
|
|||
if (sta->status_stats.lost_packets)
|
||||
sta->status_stats.lost_packets = 0;
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
||||
sta->status_stats.last_tdls_pkt_time = jiffies;
|
||||
sta->status_stats.last_pkt_time = jiffies;
|
||||
} else {
|
||||
ieee80211_lost_packet(sta, info);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include "core.h"
|
||||
#include "rdev-ops.h"
|
||||
|
@ -912,6 +913,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
|
|||
struct ieee80211_sta_vht_cap *vht_cap;
|
||||
struct ieee80211_edmg *edmg_cap;
|
||||
u32 width, control_freq, cap;
|
||||
bool support_80_80 = false;
|
||||
|
||||
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
|
||||
return false;
|
||||
|
@ -979,9 +981,13 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
|
|||
return false;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
|
||||
if (chandef->chan->band != NL80211_BAND_6GHZ &&
|
||||
cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
|
||||
cap = vht_cap->cap;
|
||||
support_80_80 =
|
||||
(cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) ||
|
||||
(cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
|
||||
cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) ||
|
||||
u32_get_bits(cap, IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) > 1;
|
||||
if (chandef->chan->band != NL80211_BAND_6GHZ && !support_80_80)
|
||||
return false;
|
||||
/* fall through */
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
|
@ -1001,7 +1007,8 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
|
|||
return false;
|
||||
cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
|
||||
if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
|
||||
cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
|
||||
cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ &&
|
||||
!(vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -6011,7 +6011,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
|
||||
params.he_6ghz_capa =
|
||||
nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
|
||||
nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_AIRTIME_WEIGHT])
|
||||
params.airtime_weight =
|
||||
|
|
|
@ -2946,6 +2946,9 @@ int regulatory_hint_user(const char *alpha2,
|
|||
if (WARN_ON(!alpha2))
|
||||
return -EINVAL;
|
||||
|
||||
if (!is_world_regdom(alpha2) && !is_an_alpha2(alpha2))
|
||||
return -EINVAL;
|
||||
|
||||
request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
|
||||
if (!request)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -123,11 +123,13 @@ int ieee80211_freq_khz_to_channel(u32 freq)
|
|||
return (freq - 2407) / 5;
|
||||
else if (freq >= 4910 && freq <= 4980)
|
||||
return (freq - 4000) / 5;
|
||||
else if (freq < 5945)
|
||||
else if (freq < 5925)
|
||||
return (freq - 5000) / 5;
|
||||
else if (freq == 5935)
|
||||
return 2;
|
||||
else if (freq <= 45000) /* DMG band lower limit */
|
||||
/* see 802.11ax D4.1 27.3.22.2 */
|
||||
return (freq - 5940) / 5;
|
||||
/* see 802.11ax D6.1 27.3.22.2 */
|
||||
return (freq - 5950) / 5;
|
||||
else if (freq >= 58320 && freq <= 70200)
|
||||
return (freq - 56160) / 2160;
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue