Commit fb86b920 authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-next-for-davem-2019-08-21' of...

Merge tag 'mac80211-next-for-davem-2019-08-21' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg:

====================
Here are a few groups of changes:
 * EDMG channel support (60 GHz, just a single patch)
 * initial 6/7 GHz band support (Arend)
 * association timestamp recording (Ben)
 * rate control improvements for better performance with
   the mt76 driver (Felix)
 * various fixes for previous HE support changes (John)
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3a76edf2 48cb3952
......@@ -351,7 +351,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) |
BIT_ULL(NL80211_STA_INFO_TX_FAILED);
sinfo->txrate.flags = RATE_INFO_FLAGS_60G;
sinfo->txrate.flags = RATE_INFO_FLAGS_DMG;
sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
sinfo->rxrate.mcs = stats->last_mcs_rx;
sinfo->rx_bytes = stats->rx_bytes;
......
......@@ -330,6 +330,60 @@ struct ieee80211_sband_iftype_data {
struct ieee80211_sta_he_cap he_cap;
};
/**
* enum ieee80211_edmg_bw_config - allowed channel bandwidth configurations
*
* @IEEE80211_EDMG_BW_CONFIG_4: 2.16GHz
* @IEEE80211_EDMG_BW_CONFIG_5: 2.16GHz and 4.32GHz
* @IEEE80211_EDMG_BW_CONFIG_6: 2.16GHz, 4.32GHz and 6.48GHz
* @IEEE80211_EDMG_BW_CONFIG_7: 2.16GHz, 4.32GHz, 6.48GHz and 8.64GHz
* @IEEE80211_EDMG_BW_CONFIG_8: 2.16GHz and 2.16GHz + 2.16GHz
* @IEEE80211_EDMG_BW_CONFIG_9: 2.16GHz, 4.32GHz and 2.16GHz + 2.16GHz
* @IEEE80211_EDMG_BW_CONFIG_10: 2.16GHz, 4.32GHz, 6.48GHz and 2.16GHz+2.16GHz
* @IEEE80211_EDMG_BW_CONFIG_11: 2.16GHz, 4.32GHz, 6.48GHz, 8.64GHz and
* 2.16GHz+2.16GHz
* @IEEE80211_EDMG_BW_CONFIG_12: 2.16GHz, 2.16GHz + 2.16GHz and
* 4.32GHz + 4.32GHz
* @IEEE80211_EDMG_BW_CONFIG_13: 2.16GHz, 4.32GHz, 2.16GHz + 2.16GHz and
* 4.32GHz + 4.32GHz
* @IEEE80211_EDMG_BW_CONFIG_14: 2.16GHz, 4.32GHz, 6.48GHz, 2.16GHz + 2.16GHz
* and 4.32GHz + 4.32GHz
* @IEEE80211_EDMG_BW_CONFIG_15: 2.16GHz, 4.32GHz, 6.48GHz, 8.64GHz,
* 2.16GHz + 2.16GHz and 4.32GHz + 4.32GHz
*/
enum ieee80211_edmg_bw_config {
IEEE80211_EDMG_BW_CONFIG_4 = 4,
IEEE80211_EDMG_BW_CONFIG_5 = 5,
IEEE80211_EDMG_BW_CONFIG_6 = 6,
IEEE80211_EDMG_BW_CONFIG_7 = 7,
IEEE80211_EDMG_BW_CONFIG_8 = 8,
IEEE80211_EDMG_BW_CONFIG_9 = 9,
IEEE80211_EDMG_BW_CONFIG_10 = 10,
IEEE80211_EDMG_BW_CONFIG_11 = 11,
IEEE80211_EDMG_BW_CONFIG_12 = 12,
IEEE80211_EDMG_BW_CONFIG_13 = 13,
IEEE80211_EDMG_BW_CONFIG_14 = 14,
IEEE80211_EDMG_BW_CONFIG_15 = 15,
};
/**
* struct ieee80211_edmg - EDMG configuration
*
* This structure describes most essential parameters needed
* to describe 802.11ay EDMG configuration
*
* @channels: bitmap that indicates the 2.16 GHz channel(s)
* that are allowed to be used for transmissions.
* Bit 0 indicates channel 1, bit 1 indicates channel 2, etc.
* Set to 0 indicate EDMG not supported.
* @bw_config: Channel BW Configuration subfield encodes
* the allowed channel bandwidth configurations
*/
struct ieee80211_edmg {
u8 channels;
enum ieee80211_edmg_bw_config bw_config;
};
/**
* struct ieee80211_supported_band - frequency band definition
*
......@@ -346,6 +400,7 @@ struct ieee80211_sband_iftype_data {
* @n_bitrates: Number of bitrates in @bitrates
* @ht_cap: HT capabilities in this band
* @vht_cap: VHT capabilities in this band
* @edmg_cap: EDMG capabilities in this band
* @n_iftype_data: number of iftype data entries
* @iftype_data: interface type data entries. Note that the bits in
* @types_mask inside this structure cannot overlap (i.e. only
......@@ -360,6 +415,7 @@ struct ieee80211_supported_band {
int n_bitrates;
struct ieee80211_sta_ht_cap ht_cap;
struct ieee80211_sta_vht_cap vht_cap;
struct ieee80211_edmg edmg_cap;
u16 n_iftype_data;
const struct ieee80211_sband_iftype_data *iftype_data;
};
......@@ -527,12 +583,17 @@ struct key_params {
* @center_freq1: center frequency of first segment
* @center_freq2: center frequency of second segment
* (only with 80+80 MHz)
* @edmg: define the EDMG channels configuration.
* If edmg is requested (i.e. the .channels member is non-zero),
* chan will define the primary channel and all other
* parameters are ignored.
*/
struct cfg80211_chan_def {
struct ieee80211_channel *chan;
enum nl80211_chan_width width;
u32 center_freq1;
u32 center_freq2;
struct ieee80211_edmg edmg;
};
/**
......@@ -590,6 +651,19 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
chandef1->center_freq2 == chandef2->center_freq2);
}
/**
* cfg80211_chandef_is_edmg - check if chandef represents an EDMG channel
*
* @chandef: the channel definition
*
* Return: %true if EDMG defined, %false otherwise.
*/
static inline bool
cfg80211_chandef_is_edmg(const struct cfg80211_chan_def *chandef)
{
return chandef->edmg.channels || chandef->edmg.bw_config;
}
/**
* cfg80211_chandef_compatible - check if two channel definitions are compatible
* @chandef1: first channel definition
......@@ -1177,15 +1251,17 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
* @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
* @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
* @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
* @RATE_INFO_FLAGS_60G: 60GHz MCS
* @RATE_INFO_FLAGS_DMG: 60GHz MCS
* @RATE_INFO_FLAGS_HE_MCS: HE MCS information
* @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode
*/
enum rate_info_flags {
RATE_INFO_FLAGS_MCS = BIT(0),
RATE_INFO_FLAGS_VHT_MCS = BIT(1),
RATE_INFO_FLAGS_SHORT_GI = BIT(2),
RATE_INFO_FLAGS_60G = BIT(3),
RATE_INFO_FLAGS_DMG = BIT(3),
RATE_INFO_FLAGS_HE_MCS = BIT(4),
RATE_INFO_FLAGS_EDMG = BIT(5),
};
/**
......@@ -1225,6 +1301,7 @@ enum rate_info_bw {
* @he_dcm: HE DCM value
* @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc,
* only valid if bw is %RATE_INFO_BW_HE_RU)
* @n_bonded_ch: In case of EDMG the number of bonded channels (1-4)
*/
struct rate_info {
u8 flags;
......@@ -1235,6 +1312,7 @@ struct rate_info {
u8 he_gi;
u8 he_dcm;
u8 he_ru_alloc;
u8 n_bonded_ch;
};
/**
......@@ -1330,6 +1408,7 @@ struct cfg80211_tid_stats {
* indicate the relevant values in this struct for them
* @connected_time: time(in secs) since a station is last connected
* @inactive_time: time since last station activity (tx/rx) in milliseconds
* @assoc_at: bootime (ns) of the last association
* @rx_bytes: bytes (size of MPDUs) received from this station
* @tx_bytes: bytes (size of MPDUs) transmitted to this station
* @llid: mesh local link id
......@@ -1390,6 +1469,7 @@ struct station_info {
u64 filled;
u32 connected_time;
u32 inactive_time;
u64 assoc_at;
u64 rx_bytes;
u64 tx_bytes;
u16 llid;
......@@ -2436,6 +2516,9 @@ struct cfg80211_bss_selection {
* @fils_erp_rrk_len: Length of @fils_erp_rrk in octets.
* @want_1x: indicates user-space supports and wants to use 802.1X driver
* offload of 4-way handshake.
* @edmg: define the EDMG channels.
* This may specify multiple channels and bonding options for the driver
* to choose from, based on BSS configuration.
*/
struct cfg80211_connect_params {
struct ieee80211_channel *channel;
......@@ -2469,6 +2552,7 @@ struct cfg80211_connect_params {
const u8 *fils_erp_rrk;
size_t fils_erp_rrk_len;
bool want_1x;
struct ieee80211_edmg edmg;
};
/**
......
......@@ -52,6 +52,11 @@
#define NL80211_MULTICAST_GROUP_NAN "nan"
#define NL80211_MULTICAST_GROUP_TESTMODE "testmode"
#define NL80211_EDMG_BW_CONFIG_MIN 4
#define NL80211_EDMG_BW_CONFIG_MAX 15
#define NL80211_EDMG_CHANNELS_MIN 1
#define NL80211_EDMG_CHANNELS_MAX 0x3c /* 0b00111100 */
/**
* DOC: Station handling
*
......@@ -2361,6 +2366,13 @@ enum nl80211_commands {
* @NL80211_ATTR_HE_OBSS_PD: nested attribute for OBSS Packet Detection
* functionality.
*
* @NL80211_ATTR_WIPHY_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz
* channel(s) that are allowed to be used for EDMG transmissions.
* Defined by IEEE P802.11ay/D4.0 section 9.4.2.251. (u8 attribute)
* @NL80211_ATTR_WIPHY_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes
* the allowed channel bandwidth configurations. (u8 attribute)
* Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
......@@ -2820,6 +2832,9 @@ enum nl80211_attrs {
NL80211_ATTR_HE_OBSS_PD,
NL80211_ATTR_WIPHY_EDMG_CHANNELS,
NL80211_ATTR_WIPHY_EDMG_BW_CONFIG,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
......@@ -3201,6 +3216,8 @@ enum nl80211_sta_bss_param {
* sent to the station (u64, usec)
* @NL80211_STA_INFO_AIRTIME_WEIGHT: current airtime weight for station (u16)
* @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station
* @NL80211_STA_INFO_ASSOC_AT_BOOTTIME: Timestamp (CLOCK_BOOTTIME, nanoseconds)
* of STA's association
* @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute
*/
......@@ -3247,6 +3264,7 @@ enum nl80211_sta_info {
NL80211_STA_INFO_TX_DURATION,
NL80211_STA_INFO_AIRTIME_WEIGHT,
NL80211_STA_INFO_AIRTIME_LINK_METRIC,
NL80211_STA_INFO_ASSOC_AT_BOOTTIME,
/* keep last */
__NL80211_STA_INFO_AFTER_LAST,
......@@ -3428,6 +3446,12 @@ enum nl80211_band_iftype_attr {
* @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE
* @NL80211_BAND_ATTR_IFTYPE_DATA: nested array attribute, with each entry using
* attributes from &enum nl80211_band_iftype_attr
* @NL80211_BAND_ATTR_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz
* channel(s) that are allowed to be used for EDMG transmissions.
* Defined by IEEE P802.11ay/D4.0 section 9.4.2.251.
* @NL80211_BAND_ATTR_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes
* the allowed channel bandwidth configurations.
* Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
* @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
* @__NL80211_BAND_ATTR_AFTER_LAST: internal use
*/
......@@ -3445,6 +3469,9 @@ enum nl80211_band_attr {
NL80211_BAND_ATTR_VHT_CAPA,
NL80211_BAND_ATTR_IFTYPE_DATA,
NL80211_BAND_ATTR_EDMG_CHANNELS,
NL80211_BAND_ATTR_EDMG_BW_CONFIG,
/* keep last */
__NL80211_BAND_ATTR_AFTER_LAST,
NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
......@@ -4543,6 +4570,7 @@ enum nl80211_txrate_gi {
* @NL80211_BAND_2GHZ: 2.4 GHz ISM band
* @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
* @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz)
* @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz)
* @NUM_NL80211_BANDS: number of bands, avoid using this in userspace
* since newer kernel versions may support more bands
*/
......@@ -4550,6 +4578,7 @@ enum nl80211_band {
NL80211_BAND_2GHZ,
NL80211_BAND_5GHZ,
NL80211_BAND_60GHZ,
NL80211_BAND_6GHZ,
NUM_NL80211_BANDS,
};
......
......@@ -72,12 +72,13 @@ ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif,
{
struct ieee80211_he_obss_pd *he_obss_pd =
&vif->bss_conf.he_obss_pd;
const u8 *data = he_spr_ie_elem->optional;
const u8 *data;
memset(he_obss_pd, 0, sizeof(*he_obss_pd));
if (!he_spr_ie_elem)
return;
data = he_spr_ie_elem->optional;
if (he_spr_ie_elem->he_sr_control &
IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
......
......@@ -158,10 +158,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
memset(chandef, 0, sizeof(struct cfg80211_chan_def));
chandef->chan = channel;
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
chandef->center_freq1 = channel->center_freq;
chandef->center_freq2 = 0;
if (!ht_oper || !sta_ht_cap.ht_supported) {
ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
......
......@@ -95,6 +95,7 @@ struct minstrel_sta_info {
struct minstrel_priv {
struct ieee80211_hw *hw;
bool has_mrr;
u32 sample_switch;
unsigned int cw_min;
unsigned int cw_max;
unsigned int max_retry;
......
This diff is collapsed.
......@@ -33,6 +33,7 @@ struct mcs_group {
u16 flags;
u8 streams;
u8 shift;
u8 bw;
u16 duration[MCS_GROUP_RATES];
};
......@@ -50,6 +51,12 @@ struct minstrel_mcs_group_data {
struct minstrel_rate_stats rates[MCS_GROUP_RATES];
};
enum minstrel_sample_mode {
MINSTREL_SAMPLE_IDLE,
MINSTREL_SAMPLE_ACTIVE,
MINSTREL_SAMPLE_PENDING,
};
struct minstrel_ht_sta {
struct ieee80211_sta *sta;
......@@ -71,6 +78,8 @@ struct minstrel_ht_sta {
unsigned int overhead;
unsigned int overhead_rtscts;
unsigned int total_packets_last;
unsigned int total_packets_cur;
unsigned int total_packets;
unsigned int sample_packets;
......@@ -82,6 +91,9 @@ struct minstrel_ht_sta {
u8 sample_count;
u8 sample_slow;
enum minstrel_sample_mode sample_mode;
u16 sample_rate;
/* current MCS group to be sampled */
u8 sample_group;
......
......@@ -1961,6 +1961,7 @@ int sta_info_move_state(struct sta_info *sta,
case IEEE80211_STA_ASSOC:
if (sta->sta_state == IEEE80211_STA_AUTH) {
set_bit(WLAN_STA_ASSOC, &sta->_flags);
sta->assoc_at = ktime_get_boottime_ns();
ieee80211_recalc_min_chandef(sta->sdata);
if (!sta->sta.support_p2p_ps)
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
......@@ -2190,6 +2191,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
BIT_ULL(NL80211_STA_INFO_STA_FLAGS) |
BIT_ULL(NL80211_STA_INFO_BSS_PARAM) |
BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME) |
BIT_ULL(NL80211_STA_INFO_ASSOC_AT_BOOTTIME) |
BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC);
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
......@@ -2198,6 +2200,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
}
sinfo->connected_time = ktime_get_seconds() - sta->last_connected;
sinfo->assoc_at = sta->assoc_at;
sinfo->inactive_time =
jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta));
......
......@@ -466,6 +466,7 @@ struct ieee80211_sta_rx_stats {
* the station when it leaves powersave or polls for frames
* @driver_buffered_tids: bitmap of TIDs the driver has data buffered on
* @txq_buffered_tids: bitmap of TIDs that mac80211 has txq data buffered on
* @assoc_at: clock boottime (in ns) of last association
* @last_connected: time (in seconds) when a station got connected
* @last_seq_ctrl: last received seq/frag number from this STA (per TID
* plus one for non-QoS frames)
......@@ -562,6 +563,7 @@ struct sta_info {
unsigned long driver_buffered_tids;
unsigned long txq_buffered_tids;
u64 assoc_at;
long last_connected;
/* Updated from RX path only, no locking requirements */
......
......@@ -260,9 +260,16 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info,
int len = sizeof(struct ieee80211_radiotap_header);
/* IEEE80211_RADIOTAP_RATE rate */
if (info->status.rates[0].idx >= 0 &&
!(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
IEEE80211_TX_RC_VHT_MCS)))
if (status && status->rate && !(status->rate->flags &
(RATE_INFO_FLAGS_MCS |
RATE_INFO_FLAGS_DMG |
RATE_INFO_FLAGS_EDMG |
RATE_INFO_FLAGS_VHT_MCS |
RATE_INFO_FLAGS_HE_MCS)))
len += 2;
else if (info->status.rates[0].idx >= 0 &&
!(info->status.rates[0].flags &
(IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS)))
len += 2;
/* IEEE80211_RADIOTAP_TX_FLAGS */
......@@ -321,13 +328,14 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
/* IEEE80211_RADIOTAP_RATE */
if (status && status->rate && !(status->rate->flags &
(RATE_INFO_FLAGS_MCS |
RATE_INFO_FLAGS_60G |
RATE_INFO_FLAGS_VHT_MCS |
RATE_INFO_FLAGS_HE_MCS)))
legacy_rate = status->rate->legacy;
else if (info->status.rates[0].idx >= 0 &&
if (status && status->rate) {
if (!(status->rate->flags & (RATE_INFO_FLAGS_MCS |
RATE_INFO_FLAGS_DMG |
RATE_INFO_FLAGS_EDMG |
RATE_INFO_FLAGS_VHT_MCS |
RATE_INFO_FLAGS_HE_MCS)))
legacy_rate = status->rate->legacy;
} else if (info->status.rates[0].idx >= 0 &&
!(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
IEEE80211_TX_RC_VHT_MCS)))
legacy_rate =
......@@ -397,7 +405,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
*pos = 11;
break;
case RATE_INFO_BW_80:
*pos = 2;
*pos = 4;
break;
case RATE_INFO_BW_40:
*pos = 1;
......@@ -406,6 +414,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
*pos = 0;
break;
}
pos++;
/* u8 mcs_nss[4] */
*pos = (status->rate->mcs << 4) | status->rate->nss;
......
......@@ -162,6 +162,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
break;
}
case NL80211_BAND_5GHZ:
case NL80211_BAND_6GHZ:
if (r->flags & IEEE80211_RATE_MANDATORY_A)
mrate = r->bitrate;
break;
......
......@@ -14,6 +14,11 @@
#include "core.h"
#include "rdev-ops.h"
static bool cfg80211_valid_60g_freq(u32 freq)
{
return freq >= 58320 && freq <= 70200;
}
void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
struct ieee80211_channel *chan,
enum nl80211_channel_type chan_type)
......@@ -23,6 +28,8 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
chandef->chan = chan;
chandef->center_freq2 = 0;
chandef->edmg.bw_config = 0;
chandef->edmg.channels = 0;
switch (chan_type) {
case NL80211_CHAN_NO_HT:
......@@ -47,6 +54,91 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
}
EXPORT_SYMBOL(cfg80211_chandef_create);
static bool cfg80211_edmg_chandef_valid(const struct cfg80211_chan_def *chandef)
{
int max_contiguous = 0;
int num_of_enabled = 0;
int contiguous = 0;
int i;
if (!chandef->edmg.channels || !chandef->edmg.bw_config)
return false;
if (!cfg80211_valid_60g_freq(chandef->chan->center_freq))
return false;
for (i = 0; i < 6; i++) {
if (chandef->edmg.channels & BIT(i)) {
contiguous++;
num_of_enabled++;
} else {
contiguous = 0;
}
max_contiguous = max(contiguous, max_contiguous);
}
/* basic verification of edmg configuration according to
* IEEE P802.11ay/D4.0 section 9.4.2.251
*/
/* check bw_config against contiguous edmg channels */
switch (chandef->edmg.bw_config) {
case IEEE80211_EDMG_BW_CONFIG_4:
case IEEE80211_EDMG_BW_CONFIG_8:
case IEEE80211_EDMG_BW_CONFIG_12:
if (max_contiguous < 1)
return false;
break;
case IEEE80211_EDMG_BW_CONFIG_5:
case IEEE80211_EDMG_BW_CONFIG_9:
case IEEE80211_EDMG_BW_CONFIG_13:
if (max_contiguous < 2)
return false;
break;
case IEEE80211_EDMG_BW_CONFIG_6:
case IEEE80211_EDMG_BW_CONFIG_10:
case IEEE80211_EDMG_BW_CONFIG_14:
if (max_contiguous < 3)
return false;
break;
case IEEE80211_EDMG_BW_CONFIG_7:
case IEEE80211_EDMG_BW_CONFIG_11:
case IEEE80211_EDMG_BW_CONFIG_15:
if (max_contiguous < 4)
return false;
break;
default:
return false;
}
/* check bw_config against aggregated (non contiguous) edmg channels */
switch (chandef->edmg.bw_config) {
case IEEE80211_EDMG_BW_CONFIG_4:
case IEEE80211_EDMG_BW_CONFIG_5:
case IEEE80211_EDMG_BW_CONFIG_6:
case IEEE80211_EDMG_BW_CONFIG_7:
break;
case IEEE80211_EDMG_BW_CONFIG_8:
case IEEE80211_EDMG_BW_CONFIG_9:
case IEEE80211_EDMG_BW_CONFIG_10:
case IEEE80211_EDMG_BW_CONFIG_11:
if (num_of_enabled < 2)
return false;
break;
case IEEE80211_EDMG_BW_CONFIG_12:
case IEEE80211_EDMG_BW_CONFIG_13:
case IEEE80211_EDMG_BW_CONFIG_14:
case IEEE80211_EDMG_BW_CONFIG_15:
if (num_of_enabled < 4 || max_contiguous < 2)
return false;
break;
default:
return false;
}
return true;
}
bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
{
u32 control_freq;
......@@ -112,6 +204,10 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
return false;
}
if (cfg80211_chandef_is_edmg(chandef) &&
!cfg80211_edmg_chandef_valid(chandef))
return false;
return true;
}
EXPORT_SYMBOL(cfg80211_chandef_valid);
......@@ -721,12 +817,66 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
return true;
}
/* check if the operating channels are valid and supported */
static bool cfg80211_edmg_usable(struct wiphy *wiphy, u8 edmg_channels,
enum ieee80211_edmg_bw_config edmg_bw_config,
int primary_channel,
struct ieee80211_edmg *edmg_cap)
{
struct ieee80211_channel *chan;
int i, freq;
int channels_counter = 0;
if (!edmg_channels && !edmg_bw_config)
return true;
if ((!edmg_channels && edmg_bw_config) ||
(edmg_channels && !edmg_bw_config))
return false;
if (!(edmg_channels & BIT(primary_channel - 1)))
return false;
/* 60GHz channels 1..6 */
for (i = 0; i < 6; i++) {
if (!(edmg_channels & BIT(i)))
continue;
if (!(edmg_cap->channels & BIT(i)))
return false;
channels_counter++;
freq = ieee80211_channel_to_frequency(i + 1,
NL80211_BAND_60GHZ);
chan = ieee80211_get_channel(wiphy, freq);
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
return false;
}
/* IEEE802.11 allows max 4 channels */
if (channels_counter > 4)
return false;
/* check bw_config is a subset of what driver supports
* (see IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13)
*/
if ((edmg_bw_config % 4) > (edmg_cap->bw_config % 4))
return false;
if (edmg_bw_config > edmg_cap->bw_config)
return false;
return true;
}
bool cfg80211_chandef_usable(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef,
u32 prohibited_flags)
{
struct ieee80211_sta_ht_cap *ht_cap;
struct ieee80211_sta_vht_cap *vht_cap;
struct ieee80211_edmg *edmg_cap;
u32 width, control_freq, cap;
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
......@@ -734,6 +884,15 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
edmg_cap = &wiphy->bands[chandef->chan->band]->edmg_cap;
if (edmg_cap->channels &&
!cfg80211_edmg_usable(wiphy,
chandef->edmg.channels,
chandef->edmg.bw_config,
chandef->chan->hw_value,
edmg_cap))
return false;
control_freq = chandef->chan->center_freq;
......@@ -894,7 +1053,8 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy,
if (chan == other_chan)
return true;
if (chan->band != NL80211_BAND_5GHZ)
if (chan->band != NL80211_BAND_5GHZ &&
chan->band != NL80211_BAND_6GHZ)
continue;
r1 = cfg80211_get_unii(chan->center_freq);
......
......@@ -104,13 +104,19 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
* use the mandatory rate set for 11b or
* 11a for maximum compatibility.
*/
struct ieee80211_supported_band *sband =
rdev->wiphy.bands[params->chandef.chan->band];
struct ieee80211_supported_band *sband;
enum nl80211_band band;
u32 flag;
int j;
u32 flag = params->chandef.chan->band == NL80211_BAND_5GHZ ?
IEEE80211_RATE_MANDATORY_A :
IEEE80211_RATE_MANDATORY_B;
band = params->chandef.chan->band;
if (band == NL80211_BAND_5GHZ ||
band == NL80211_BAND_6GHZ)
flag = IEEE80211_RATE_MANDATORY_A;
else
flag = IEEE80211_RATE_MANDATORY_B;
sband = rdev->wiphy.bands[band];
for (j = 0; j < sband->n_bitrates; j++) {
if (sband->bitrates[j].flags & flag)
params->basic_rates |= BIT(j);
......
......@@ -298,6 +298,13 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_EDMG_CHANNELS] = NLA_POLICY_RANGE(NLA_U8,
NL80211_EDMG_CHANNELS_MIN,
NL80211_EDMG_CHANNELS_MAX),
[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG] = NLA_POLICY_RANGE(NLA_U8,
NL80211_EDMG_BW_CONFIG_MIN,
NL80211_EDMG_BW_CONFIG_MAX),
[NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
[NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
[NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
......@@ -677,6 +684,7 @@ static const struct nla_policy
nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
[NL80211_BAND_2GHZ] = { .type = NLA_S32 },
[NL80211_BAND_5GHZ] = { .type = NLA_S32 },
[NL80211_BAND_6GHZ] = { .type = NLA_S32 },
[NL80211_BAND_60GHZ] = { .type = NLA_S32 },
};
......@@ -1573,6 +1581,15 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg,
nla_nest_end(msg, nl_iftype_data);
}
/* add EDMG info */
if (sband->edmg_cap.channels &&
(nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_CHANNELS,
sband->edmg_cap.channels) ||
nla_put_u8(msg, NL80211_BAND_ATTR_EDMG_BW_CONFIG,
sband->edmg_cap.bw_config)))
return -ENOBUFS;
/* add bitrates */
nl_rates = nla_nest_start_noflag(msg, NL80211_BAND_ATTR_RATES);
if (!nl_rates)
......@@ -2676,6 +2693,18 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
}
if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
chandef->edmg.channels =
nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
chandef->edmg.bw_config =
nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
} else {
chandef->edmg.bw_config = 0;
chandef->edmg.channels = 0;
}
if (!cfg80211_chandef_valid(chandef)) {
NL_SET_ERR_MSG(extack, "invalid channel definition");
return -EINVAL;
......@@ -5031,6 +5060,7 @@ 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);
PUT_SINFO_U64(ASSOC_AT_BOOTTIME, assoc_at);
if (sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
......@@ -9892,6 +9922,15 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) {
connect.edmg.channels =
nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]);
if (info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG])
connect.edmg.bw_config =
nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_BW_CONFIG]);
}
if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
connkeys = nl80211_parse_connkeys(rdev, info, NULL);
if (IS_ERR(connkeys))
......
......@@ -3806,8 +3806,9 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy)
}
/*
* See http://www.fcc.gov/document/5-ghz-unlicensed-spectrum-unii, for
* UNII band definitions
* See FCC notices for UNII band definitions
* 5GHz: https://www.fcc.gov/document/5-ghz-unlicensed-spectrum-unii
* 6GHz: https://www.fcc.gov/document/fcc-proposes-more-spectrum-unlicensed-use-0
*/
int cfg80211_get_unii(int freq)
{
......@@ -3831,6 +3832,22 @@ int cfg80211_get_unii(int freq)
if (freq > 5725 && freq <= 5825)
return 4;
/* UNII-5 */
if (freq > 5925 && freq <= 6425)
return 5;
/* UNII-6 */
if (freq > 6425 && freq <= 6525)
return 6;
/* UNII-7 */
if (freq > 6525 && freq <= 6875)
return 7;
/* UNII-8 */
if (freq > 6875 && freq <= 7125)
return 8;
return -EINVAL;
}
......
......@@ -2446,10 +2446,11 @@ TRACE_EVENT(rdev_set_mcast_rate,
sizeof(int) * NUM_NL80211_BANDS);
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", "
"mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 60GHz=0x%x]",
"mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 6GHz=0x%x, 60GHz=0x%x]",
WIPHY_PR_ARG, NETDEV_PR_ARG,
__entry->mcast_rate[NL80211_BAND_2GHZ],
__entry->mcast_rate[NL80211_BAND_5GHZ],
__entry->mcast_rate[NL80211_BAND_6GHZ],
__entry->mcast_rate[NL80211_BAND_60GHZ])
);
......
......@@ -91,6 +91,11 @@ int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
else
return 5000 + chan * 5;
break;
case NL80211_BAND_6GHZ:
/* see 802.11ax D4.1 27.3.22.2 */
if (chan <= 253)
return 5940 + chan * 5;
break;
case NL80211_BAND_60GHZ:
if (chan < 7)
return 56160 + chan * 2160;
......@@ -111,8 +116,11 @@ int ieee80211_frequency_to_channel(int freq)
return (freq - 2407) / 5;
else if (freq >= 4910 && freq <= 4980)
return (freq - 4000) / 5;
else if (freq <= 45000) /* DMG band lower limit */
else if (freq < 5940)
return (freq - 5000) / 5;
else if (freq <= 45000) /* DMG band lower limit */
/* see 802.11ax D4.1 27.3.22.2 */
return (freq - 5940) / 5;
else if (freq >= 58320 && freq <= 70200)
return (freq - 56160) / 2160;
else
......@@ -148,6 +156,7 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband)
switch (sband->band) {
case NL80211_BAND_5GHZ:
case NL80211_BAND_6GHZ:
want = 3;
for (i = 0; i < sband->n_bitrates; i++) {
if (sband->bitrates[i].bitrate == 60 ||
......@@ -1034,7 +1043,7 @@ static u32 cfg80211_calculate_bitrate_ht(struct rate_info *rate)
return (bitrate + 50000) / 100000;
}
static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
static u32 cfg80211_calculate_bitrate_dmg(struct rate_info *rate)
{
static const u32 __mcs2bitrate[] = {
/* control PHY */
......@@ -1081,6 +1090,40 @@ static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
return __mcs2bitrate[rate->mcs];
}
static u32 cfg80211_calculate_bitrate_edmg(struct rate_info *rate)
{
static const u32 __mcs2bitrate[] = {
/* control PHY */
[0] = 275,
/* SC PHY */
[1] = 3850,
[2] = 7700,
[3] = 9625,
[4] = 11550,
[5] = 12512, /* 1251.25 mbps */
[6] = 13475,
[7] = 15400,
[8] = 19250,
[9] = 23100,
[10] = 25025,
[11] = 26950,
[12] = 30800,
[13] = 38500,
[14] = 46200,
[15] = 50050,
[16] = 53900,
[17] = 57750,
[18] = 69300,
[19] = 75075,
[20] = 80850,
};
if (WARN_ON_ONCE(rate->mcs >= ARRAY_SIZE(__mcs2bitrate)))
return 0;
return __mcs2bitrate[rate->mcs] * rate->n_bonded_ch;
}
static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
{
static const u32 base[4][10] = {
......@@ -1253,8 +1296,10 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
{
if (rate->flags & RATE_INFO_FLAGS_MCS)
return cfg80211_calculate_bitrate_ht(rate);
if (rate->flags & RATE_INFO_FLAGS_60G)
return cfg80211_calculate_bitrate_60g(rate);
if (rate->flags & RATE_INFO_FLAGS_DMG)
return cfg80211_calculate_bitrate_dmg(rate);
if (rate->flags & RATE_INFO_FLAGS_EDMG)
return cfg80211_calculate_bitrate_edmg(rate);
if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
return cfg80211_calculate_bitrate_vht(rate);
if (rate->flags & RATE_INFO_FLAGS_HE_MCS)
......@@ -1466,6 +1511,9 @@ bool ieee80211_operating_class_to_band(u8 operating_class,
case 128 ... 130:
*band = NL80211_BAND_5GHZ;
return true;
case 131 ... 135:
*band = NL80211_BAND_6GHZ;
return true;
case 81:
case 82:
case 83:
......
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