This round's updates:

* finally some of the promised HE code, but it turns
    out to be small - but everything kept changing, so
    one part I did in the driver was >30 patches for
    what was ultimately <200 lines of code ... similar
    here for this code.
  * improved scan privacy support - can now specify scan
    flags for randomizing the sequence number as well as
    reducing the probe request element content
  * rfkill cleanups
  * a timekeeping cleanup from Arnd
  * various other cleanups
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAls2HpsACgkQB8qZga/f
 l8RPuQ//aZbTXc/GkYh0/GAmF4ORHePOHTXTZbMEzPeHQSlUE0nTSieyVtamsyy+
 P+0Ik/lck15Oq/8qabUqDfDY37Fm/OD88jxmoVhjDdgTUcTbIm71n1yS9vDLytuL
 n0Awq2d8xuR2bRkwGgt3Bg0RsCbvqUTa/irrighPiKGqwdVGf7kqGi76hsLrMkx9
 MQsVh1tRJCEvqEfs3yojhPna4AFjl9OoKFh0JjKJmKv5MWY5x4ojYG3kvvnAq2uF
 TIqko4l+R6AR+IzgBsPfzjj8YSJT67Z9IGe8YzId3OcMubpaJqKwrIq0+sYD/9AO
 /FGlK7V/NNge4E7sRPwu+dFzf9tOQAtKE06Icxy7aFknhdv5yGnuT2XaIUt2fv6b
 1jMWMPxY8azBL3H2siDJ17ouRoIJbkw+3o41m3ZCneLebMWjIX/s2Azqiz2lUiU2
 RjZ9Zr0qXdSghK5yD6/iInUBdmNBNq5ubQ8OIAy7fL7linvBAO23iP/G4E7zBikw
 9DtHvrpRx2yA4oYTZiaP0FIEmN/nhVuY7VLdjfLlLBtU9cs9kxOydOVSVB9MeJfE
 c+HiIApuykDxUj5mrd2mo7AkINjUVXKrVZLOH8hqlNvbjJRmcfyR/TOUJzdfeLX+
 0jmji7TMZaaooUEm+KllCnIyUxSmlS25/Ekfm2gdx/rMXXzi/Oo=
 =sNaA
 -----END PGP SIGNATURE-----

Merge tag 'mac80211-next-for-davem-2018-06-29' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Small merge conflict in net/mac80211/scan.c, I preserved
the kcalloc() conversion. -DaveM

Johannes Berg says:

====================
This round's updates:
 * finally some of the promised HE code, but it turns
   out to be small - but everything kept changing, so
   one part I did in the driver was >30 patches for
   what was ultimately <200 lines of code ... similar
   here for this code.
 * improved scan privacy support - can now specify scan
   flags for randomizing the sequence number as well as
   reducing the probe request element content
 * rfkill cleanups
 * a timekeeping cleanup from Arnd
 * various other cleanups
====================

Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
David S. Miller 2018-06-30 21:08:12 +09:00
commit 8365da2c05
38 changed files with 1939 additions and 249 deletions

View file

@ -3,7 +3,7 @@
*
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015 Intel Deutschland GmbH
* Copyright 2015-2017 Intel Deutschland GmbH
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@ -744,6 +744,8 @@ int wiphy_register(struct wiphy *wiphy)
/* sanity check supported bands/channels */
for (band = 0; band < NUM_NL80211_BANDS; band++) {
u16 types = 0;
sband = wiphy->bands[band];
if (!sband)
continue;
@ -788,6 +790,23 @@ int wiphy_register(struct wiphy *wiphy)
sband->channels[i].band = band;
}
for (i = 0; i < sband->n_iftype_data; i++) {
const struct ieee80211_sband_iftype_data *iftd;
iftd = &sband->iftype_data[i];
if (WARN_ON(!iftd->types_mask))
return -EINVAL;
if (WARN_ON(types & iftd->types_mask))
return -EINVAL;
/* at least one piece of information must be present */
if (WARN_ON(!iftd->he_cap.has_he))
return -EINVAL;
types |= iftd->types_mask;
}
have_band = true;
}

View file

@ -76,7 +76,7 @@ struct cfg80211_registered_device {
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
struct sk_buff *scan_msg;
struct list_head sched_scan_req_list;
unsigned long suspend_at;
time64_t suspend_at;
struct work_struct scan_done_wk;
struct genl_info *cur_cmd_info;

View file

@ -428,6 +428,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
[NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
[NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
[NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY,
.len = NL80211_HE_MAX_CAPABILITY_LEN },
};
/* policy for the key attributes */
@ -1324,6 +1326,34 @@ static int nl80211_send_coalesce(struct sk_buff *msg,
return 0;
}
static int
nl80211_send_iftype_data(struct sk_buff *msg,
const struct ieee80211_sband_iftype_data *iftdata)
{
const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap;
if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
iftdata->types_mask))
return -ENOBUFS;
if (he_cap->has_he) {
if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
sizeof(he_cap->he_cap_elem.mac_cap_info),
he_cap->he_cap_elem.mac_cap_info) ||
nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
sizeof(he_cap->he_cap_elem.phy_cap_info),
he_cap->he_cap_elem.phy_cap_info) ||
nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
sizeof(he_cap->he_mcs_nss_supp),
&he_cap->he_mcs_nss_supp) ||
nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
return -ENOBUFS;
}
return 0;
}
static int nl80211_send_band_rateinfo(struct sk_buff *msg,
struct ieee80211_supported_band *sband)
{
@ -1353,6 +1383,32 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg,
sband->vht_cap.cap)))
return -ENOBUFS;
if (sband->n_iftype_data) {
struct nlattr *nl_iftype_data =
nla_nest_start(msg, NL80211_BAND_ATTR_IFTYPE_DATA);
int err;
if (!nl_iftype_data)
return -ENOBUFS;
for (i = 0; i < sband->n_iftype_data; i++) {
struct nlattr *iftdata;
iftdata = nla_nest_start(msg, i + 1);
if (!iftdata)
return -ENOBUFS;
err = nl80211_send_iftype_data(msg,
&sband->iftype_data[i]);
if (err)
return err;
nla_nest_end(msg, iftdata);
}
nla_nest_end(msg, nl_iftype_data);
}
/* add bitrates */
nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
if (!nl_rates)
@ -2757,7 +2813,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
nla_put_u32(msg, NL80211_ATTR_GENERATION,
rdev->devlist_generation ^
(cfg80211_rdev_list_generation << 2)))
(cfg80211_rdev_list_generation << 2)) ||
nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
goto nla_put_failure;
if (rdev->ops->get_channel) {
@ -4471,6 +4528,9 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
case RATE_INFO_BW_160:
rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
break;
case RATE_INFO_BW_HE_RU:
rate_flg = 0;
WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
}
if (rate_flg && nla_put_flag(msg, rate_flg))
@ -4490,6 +4550,19 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
return false;
} else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
return false;
if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
return false;
if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
return false;
if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
return false;
if (info->bw == RATE_INFO_BW_HE_RU &&
nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
info->he_ru_alloc))
return false;
}
nla_nest_end(msg, rate);
@ -4546,13 +4619,13 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
#define PUT_SINFO(attr, memb, type) do { \
BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) && \
if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
sinfo->memb)) \
goto nla_put_failure; \
} while (0)
#define PUT_SINFO_U64(attr, memb) do { \
if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) && \
if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) && \
nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
sinfo->memb, NL80211_STA_INFO_PAD)) \
goto nla_put_failure; \
@ -4561,14 +4634,14 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
PUT_SINFO(CONNECTED_TIME, connected_time, u32);
PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
if (sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES) |
BIT(NL80211_STA_INFO_RX_BYTES64)) &&
if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
(u32)sinfo->rx_bytes))
goto nla_put_failure;
if (sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES) |
BIT(NL80211_STA_INFO_TX_BYTES64)) &&
if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
(u32)sinfo->tx_bytes))
goto nla_put_failure;
@ -4588,24 +4661,24 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
default:
break;
}
if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL)) {
if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
if (!nl80211_put_signal(msg, sinfo->chains,
sinfo->chain_signal,
NL80211_STA_INFO_CHAIN_SIGNAL))
goto nla_put_failure;
}
if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
if (!nl80211_put_signal(msg, sinfo->chains,
sinfo->chain_signal_avg,
NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
goto nla_put_failure;
}
if (sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
NL80211_STA_INFO_TX_BITRATE))
goto nla_put_failure;
}
if (sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE)) {
if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
NL80211_STA_INFO_RX_BITRATE))
goto nla_put_failure;
@ -4621,7 +4694,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
PUT_SINFO(PEER_PM, peer_pm, u32);
PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
if (sinfo->filled & BIT(NL80211_STA_INFO_BSS_PARAM)) {
if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM);
if (!bss_param)
goto nla_put_failure;
@ -4640,7 +4713,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
nla_nest_end(msg, bss_param);
}
if ((sinfo->filled & BIT(NL80211_STA_INFO_STA_FLAGS)) &&
if ((sinfo->filled & BIT_ULL(NL80211_STA_INFO_STA_FLAGS)) &&
nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
sizeof(struct nl80211_sta_flag_update),
&sinfo->sta_flags))
@ -4886,7 +4959,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
return -EINVAL;
if (params->supported_rates)
return -EINVAL;
if (params->ext_capab || params->ht_capa || params->vht_capa)
if (params->ext_capab || params->ht_capa || params->vht_capa ||
params->he_capa)
return -EINVAL;
}
@ -5092,6 +5166,15 @@ static int nl80211_set_station_tdls(struct genl_info *info,
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
params->vht_capa =
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
params->he_capa =
nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
params->he_capa_len =
nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
if (params->he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN)
return -EINVAL;
}
err = nl80211_parse_sta_channel_info(info, params);
if (err)
@ -5319,6 +5402,17 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
params.vht_capa =
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
params.he_capa =
nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
params.he_capa_len =
nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
/* max len is validated in nla policy */
if (params.he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN)
return -EINVAL;
}
if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
params.opmode_notif_used = true;
params.opmode_notif =
@ -5351,6 +5445,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
params.ht_capa = NULL;
params.vht_capa = NULL;
/* HE requires WME */
if (params.he_capa_len)
return -EINVAL;
}
/* When you run into this, adjust the code below for the new flag */
@ -6861,6 +6959,16 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
return regulatory_pre_cac_allowed(wdev->wiphy);
}
static bool nl80211_check_scan_feat(struct wiphy *wiphy, u32 flags, u32 flag,
enum nl80211_ext_feature_index feat)
{
if (!(flags & flag))
return true;
if (wiphy_ext_feature_isset(wiphy, feat))
return true;
return false;
}
static int
nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
void *request, struct nlattr **attrs,
@ -6895,15 +7003,33 @@ nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
if (((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
!(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
((*flags & NL80211_SCAN_FLAG_LOW_SPAN) &&
!wiphy_ext_feature_isset(wiphy,
NL80211_EXT_FEATURE_LOW_SPAN_SCAN)) ||
((*flags & NL80211_SCAN_FLAG_LOW_POWER) &&
!wiphy_ext_feature_isset(wiphy,
NL80211_EXT_FEATURE_LOW_POWER_SCAN)) ||
((*flags & NL80211_SCAN_FLAG_HIGH_ACCURACY) &&
!wiphy_ext_feature_isset(wiphy,
NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN)))
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_LOW_SPAN,
NL80211_EXT_FEATURE_LOW_SPAN_SCAN) ||
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_LOW_POWER,
NL80211_EXT_FEATURE_LOW_POWER_SCAN) ||
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_HIGH_ACCURACY,
NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN) ||
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME,
NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) ||
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP,
NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP) ||
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) ||
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE,
NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE) ||
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_RANDOM_SN,
NL80211_EXT_FEATURE_SCAN_RANDOM_SN) ||
!nl80211_check_scan_feat(wiphy, *flags,
NL80211_SCAN_FLAG_MIN_PREQ_CONTENT,
NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
return -EOPNOTSUPP;
if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
@ -6918,26 +7044,6 @@ nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev,
return err;
}
if ((*flags & NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME) &&
!wiphy_ext_feature_isset(wiphy,
NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME))
return -EOPNOTSUPP;
if ((*flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP) &&
!wiphy_ext_feature_isset(wiphy,
NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP))
return -EOPNOTSUPP;
if ((*flags & NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) &&
!wiphy_ext_feature_isset(wiphy,
NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION))
return -EOPNOTSUPP;
if ((*flags & NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE) &&
!wiphy_ext_feature_isset(wiphy,
NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE))
return -EOPNOTSUPP;
return 0;
}
@ -10160,7 +10266,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
if (err)
return err;
if (sinfo.filled & BIT(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
wdev->cqm_config->last_rssi_event_value =
(s8) sinfo.rx_beacon_signal_avg;
}

View file

@ -102,7 +102,7 @@ static int wiphy_suspend(struct device *dev)
struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
int ret = 0;
rdev->suspend_at = get_seconds();
rdev->suspend_at = ktime_get_boottime_seconds();
rtnl_lock();
if (rdev->wiphy.registered) {
@ -130,7 +130,7 @@ static int wiphy_resume(struct device *dev)
int ret = 0;
/* Age scan results with time spent in suspend */
cfg80211_bss_age(rdev, get_seconds() - rdev->suspend_at);
cfg80211_bss_age(rdev, ktime_get_boottime_seconds() - rdev->suspend_at);
rtnl_lock();
if (rdev->wiphy.registered && rdev->ops->resume)

View file

@ -4,6 +4,7 @@
*
* Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2017 Intel Deutschland GmbH
*/
#include <linux/export.h>
#include <linux/bitops.h>
@ -1142,6 +1143,85 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
return 0;
}
static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)
{
#define SCALE 2048
u16 mcs_divisors[12] = {
34133, /* 16.666666... */
17067, /* 8.333333... */
11378, /* 5.555555... */
8533, /* 4.166666... */
5689, /* 2.777777... */
4267, /* 2.083333... */
3923, /* 1.851851... */
3413, /* 1.666666... */
2844, /* 1.388888... */
2560, /* 1.250000... */
2276, /* 1.111111... */
2048, /* 1.000000... */
};
u32 rates_160M[3] = { 960777777, 907400000, 816666666 };
u32 rates_969[3] = { 480388888, 453700000, 408333333 };
u32 rates_484[3] = { 229411111, 216666666, 195000000 };
u32 rates_242[3] = { 114711111, 108333333, 97500000 };
u32 rates_106[3] = { 40000000, 37777777, 34000000 };
u32 rates_52[3] = { 18820000, 17777777, 16000000 };
u32 rates_26[3] = { 9411111, 8888888, 8000000 };
u64 tmp;
u32 result;
if (WARN_ON_ONCE(rate->mcs > 11))
return 0;
if (WARN_ON_ONCE(rate->he_gi > NL80211_RATE_INFO_HE_GI_3_2))
return 0;
if (WARN_ON_ONCE(rate->he_ru_alloc >
NL80211_RATE_INFO_HE_RU_ALLOC_2x996))
return 0;
if (WARN_ON_ONCE(rate->nss < 1 || rate->nss > 8))
return 0;
if (rate->bw == RATE_INFO_BW_160)
result = rates_160M[rate->he_gi];
else if (rate->bw == RATE_INFO_BW_80 ||
(rate->bw == RATE_INFO_BW_HE_RU &&
rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_996))
result = rates_969[rate->he_gi];
else if (rate->bw == RATE_INFO_BW_40 ||
(rate->bw == RATE_INFO_BW_HE_RU &&
rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_484))
result = rates_484[rate->he_gi];
else if (rate->bw == RATE_INFO_BW_20 ||
(rate->bw == RATE_INFO_BW_HE_RU &&
rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_242))
result = rates_242[rate->he_gi];
else if (rate->bw == RATE_INFO_BW_HE_RU &&
rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_106)
result = rates_106[rate->he_gi];
else if (rate->bw == RATE_INFO_BW_HE_RU &&
rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_52)
result = rates_52[rate->he_gi];
else if (rate->bw == RATE_INFO_BW_HE_RU &&
rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_26)
result = rates_26[rate->he_gi];
else if (WARN(1, "invalid HE MCS: bw:%d, ru:%d\n",
rate->bw, rate->he_ru_alloc))
return 0;
/* now scale to the appropriate MCS */
tmp = result;
tmp *= SCALE;
do_div(tmp, mcs_divisors[rate->mcs]);
result = tmp;
/* and take NSS, DCM into account */
result = (result * rate->nss) / 8;
if (rate->he_dcm)
result /= 2;
return result;
}
u32 cfg80211_calculate_bitrate(struct rate_info *rate)
{
if (rate->flags & RATE_INFO_FLAGS_MCS)
@ -1150,6 +1230,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
return cfg80211_calculate_bitrate_60g(rate);
if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
return cfg80211_calculate_bitrate_vht(rate);
if (rate->flags & RATE_INFO_FLAGS_HE_MCS)
return cfg80211_calculate_bitrate_he(rate);
return rate->legacy;
}
@ -1791,8 +1873,9 @@ bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp)
{
sinfo->pertid = kcalloc(sizeof(*(sinfo->pertid)),
IEEE80211_NUM_TIDS + 1, gfp);
sinfo->pertid = kcalloc(IEEE80211_NUM_TIDS + 1,
sizeof(*(sinfo->pertid)),
gfp);
if (!sinfo->pertid)
return -ENOMEM;

View file

@ -1278,7 +1278,7 @@ static int cfg80211_wext_giwrate(struct net_device *dev,
if (err)
return err;
if (!(sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)))
if (!(sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)))
return -EOPNOTSUPP;
rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate);
@ -1320,7 +1320,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
switch (rdev->wiphy.signal_type) {
case CFG80211_SIGNAL_TYPE_MBM:
if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) {
if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
int sig = sinfo.signal;
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
@ -1334,7 +1334,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
break;
}
case CFG80211_SIGNAL_TYPE_UNSPEC:
if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) {
if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
wstats.qual.level = sinfo.signal;
@ -1347,9 +1347,9 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
}
wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
if (sinfo.filled & BIT(NL80211_STA_INFO_RX_DROP_MISC))
if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC))
wstats.discard.misc = sinfo.rx_dropped_misc;
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_FAILED))
if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))
wstats.discard.retries = sinfo.tx_failed;
return &wstats;