Commit 21cc70c7 authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-next-for-net-next-2021-02-12' of...

Merge tag 'mac80211-next-for-net-next-2021-02-12' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
Last set of updates:
 * more minstrel work from Felix to reduce the
   probing overhead
 * QoS for nl80211 control port frames
 * STBC injection support
 * and a couple of small fixes
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 93efb0c6 735a4848
......@@ -2583,12 +2583,14 @@ struct cfg80211_auth_request {
* authentication capability. Drivers can offload authentication to
* userspace if this flag is set. Only applicable for cfg80211_connect()
* request (connect callback).
* @ASSOC_REQ_DISABLE_HE: Disable HE
*/
enum cfg80211_assoc_req_flags {
ASSOC_REQ_DISABLE_HT = BIT(0),
ASSOC_REQ_DISABLE_VHT = BIT(1),
ASSOC_REQ_USE_RRM = BIT(2),
CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3),
ASSOC_REQ_DISABLE_HE = BIT(4),
};
/**
......
......@@ -1963,8 +1963,15 @@ enum nl80211_commands {
* @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire
* probe-response frame. The DA field in the 802.11 header is zero-ed out,
* to be filled by the FW.
* @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable
* this feature. Currently, only supported in mac80211 drivers.
* @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable
* this feature during association. This is a flag attribute.
* Currently only supported in mac80211 drivers.
* @NL80211_ATTR_DISABLE_VHT: Force VHT capable interfaces to disable
* this feature during association. This is a flag attribute.
* Currently only supported in mac80211 drivers.
* @NL80211_ATTR_DISABLE_HE: Force HE capable interfaces to disable
* this feature during association. This is a flag attribute.
* Currently only supported in mac80211 drivers.
* @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the
* ATTR_HT_CAPABILITY to which attention should be paid.
* Currently, only mac80211 NICs support this feature.
......@@ -3045,6 +3052,8 @@ enum nl80211_attrs {
NL80211_ATTR_SAR_SPEC,
NL80211_ATTR_DISABLE_HE,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
......
......@@ -356,7 +356,7 @@ u32 airtime_link_metric_get(struct ieee80211_local *local,
*/
tx_time = (device_constant + 10 * test_frame_len / rate);
estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT);
result = ((u64)tx_time * estimated_retx) >> (2 * ARITH_SHIFT);
return (u32)result;
}
......
......@@ -5754,6 +5754,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (req->flags & ASSOC_REQ_DISABLE_VHT)
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
if (req->flags & ASSOC_REQ_DISABLE_HE)
ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
err = ieee80211_prep_connection(sdata, req->bss, true, override);
if (err)
goto err_clear;
......
This diff is collapsed.
......@@ -6,6 +6,8 @@
#ifndef __RC_MINSTREL_HT_H
#define __RC_MINSTREL_HT_H
#include <linux/bitfield.h>
/* number of highest throughput rates to consider*/
#define MAX_THR_RATES 4
#define SAMPLE_COLUMNS 10 /* number of columns in sample table */
......@@ -57,10 +59,22 @@
#define MCS_GROUP_RATES 10
#define MI_RATE_IDX_MASK GENMASK(3, 0)
#define MI_RATE_GROUP_MASK GENMASK(15, 4)
#define MI_RATE(_group, _idx) \
(FIELD_PREP(MI_RATE_GROUP_MASK, _group) | \
FIELD_PREP(MI_RATE_IDX_MASK, _idx))
#define MI_RATE_IDX(_rate) FIELD_GET(MI_RATE_IDX_MASK, _rate)
#define MI_RATE_GROUP(_rate) FIELD_GET(MI_RATE_GROUP_MASK, _rate)
#define MINSTREL_SAMPLE_RATES 5 /* rates per sample type */
#define MINSTREL_SAMPLE_INTERVAL (HZ / 50)
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;
......@@ -110,10 +124,16 @@ struct minstrel_rate_stats {
u8 retry_count;
u8 retry_count_rtscts;
u8 sample_skipped;
bool retry_updated;
};
enum minstrel_sample_type {
MINSTREL_SAMPLE_TYPE_INC,
MINSTREL_SAMPLE_TYPE_JUMP,
MINSTREL_SAMPLE_TYPE_SLOW,
__MINSTREL_SAMPLE_TYPE_MAX
};
struct minstrel_mcs_group_data {
u8 index;
u8 column;
......@@ -126,10 +146,10 @@ 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_sample_category {
u8 sample_group;
u16 sample_rates[MINSTREL_SAMPLE_RATES];
u16 cur_sample_rates[MINSTREL_SAMPLE_RATES];
};
struct minstrel_ht_sta {
......@@ -155,26 +175,19 @@ struct minstrel_ht_sta {
unsigned int overhead_legacy;
unsigned int overhead_legacy_rtscts;
unsigned int total_packets_last;
unsigned int total_packets_cur;
unsigned int total_packets;
unsigned int sample_packets;
/* tx flags to add for frames for this sta */
u32 tx_flags;
u8 sample_wait;
u8 sample_tries;
u8 sample_count;
u8 sample_slow;
u8 band;
enum minstrel_sample_mode sample_mode;
u8 sample_seq;
u16 sample_rate;
/* current MCS group to be sampled */
u8 sample_group;
u8 band;
unsigned long sample_time;
struct minstrel_sample_category sample[__MINSTREL_SAMPLE_TYPE_MAX];
/* Bitfield of supported MCS rates of all groups */
u16 supported[MINSTREL_GROUPS_NB];
......
......@@ -32,6 +32,18 @@ minstrel_stats_release(struct inode *inode, struct file *file)
return 0;
}
static bool
minstrel_ht_is_sample_rate(struct minstrel_ht_sta *mi, int idx)
{
int type, i;
for (type = 0; type < ARRAY_SIZE(mi->sample); type++)
for (i = 0; i < MINSTREL_SAMPLE_RATES; i++)
if (mi->sample[type].cur_sample_rates[i] == idx)
return true;
return false;
}
static char *
minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
{
......@@ -56,7 +68,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
for (j = 0; j < MCS_GROUP_RATES; j++) {
struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
int idx = i * MCS_GROUP_RATES + j;
int idx = MI_RATE(i, j);
unsigned int duration;
if (!(mi->supported[i] & BIT(j)))
......@@ -84,6 +96,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
*(p++) = (idx == mi->max_tp_rate[2]) ? 'C' : ' ';
*(p++) = (idx == mi->max_tp_rate[3]) ? 'D' : ' ';
*(p++) = (idx == mi->max_prob_rate) ? 'P' : ' ';
*(p++) = minstrel_ht_is_sample_rate(mi, idx) ? 'S' : ' ';
if (gflags & IEEE80211_TX_RC_MCS) {
p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j);
......@@ -145,9 +158,9 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
p += sprintf(p, "\n");
p += sprintf(p,
" best ____________rate__________ ____statistics___ _____last____ ______sum-of________\n");
" best ____________rate__________ ____statistics___ _____last____ ______sum-of________\n");
p += sprintf(p,
"mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]\n");
"mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]\n");
p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
for (i = 0; i < MINSTREL_CCK_GROUP; i++)
......@@ -201,7 +214,7 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
for (j = 0; j < MCS_GROUP_RATES; j++) {
struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
int idx = i * MCS_GROUP_RATES + j;
int idx = MI_RATE(i, j);
unsigned int duration;
if (!(mi->supported[i] & BIT(j)))
......@@ -228,6 +241,7 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[2]) ? "C" : ""));
p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[3]) ? "D" : ""));
p += sprintf(p, "%s" ,((idx == mi->max_prob_rate) ? "P" : ""));
p += sprintf(p, "%s", (minstrel_ht_is_sample_rate(mi, idx) ? "S" : ""));
if (gflags & IEEE80211_TX_RC_MCS) {
p += sprintf(p, ",MCS%-2u,", (mg->streams - 1) * 8 + j);
......
......@@ -628,16 +628,12 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr = (void *)skb->data;
__be16 ethertype = 0;
if (skb->len >= ETH_HLEN && skb->protocol == cpu_to_be16(ETH_P_802_3))
skb_copy_bits(skb, 2 * ETH_ALEN, &ethertype, ETH_TLEN);
rcu_read_lock();
sdata = ieee80211_sdata_from_skb(local, skb);
if (sdata) {
if (ethertype == sdata->control_port_protocol ||
ethertype == cpu_to_be16(ETH_P_PREAUTH))
if (skb->protocol == sdata->control_port_protocol ||
skb->protocol == cpu_to_be16(ETH_P_PREAUTH))
cfg80211_control_port_tx_status(&sdata->wdev,
cookie,
skb->data,
......
......@@ -1182,9 +1182,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
tx->sta = rcu_dereference(sdata->u.vlan.sta);
if (!tx->sta && sdata->wdev.use_4addr)
return TX_DROP;
} else if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX |
IEEE80211_TX_CTL_INJECTED) ||
tx->sdata->control_port_protocol == tx->skb->protocol) {
} else if (tx->sdata->control_port_protocol == tx->skb->protocol) {
tx->sta = sta_info_get_bss(sdata, hdr->addr1);
}
if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
......@@ -2124,6 +2122,15 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_FEC &&
mcs_flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC)
info->flags |= IEEE80211_TX_CTL_LDPC;
if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_STBC) {
u8 stbc = u8_get_bits(mcs_flags,
IEEE80211_RADIOTAP_MCS_STBC_MASK);
info->flags |=
u32_encode_bits(stbc,
IEEE80211_TX_CTL_STBC);
}
break;
case IEEE80211_RADIOTAP_VHT:
......@@ -5404,6 +5411,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
struct sk_buff *skb;
struct ethhdr *ehdr;
u32 ctrl_flags = 0;
......@@ -5426,8 +5434,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
if (cookie)
ctrl_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX |
IEEE80211_TX_CTL_INJECTED;
flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX;
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
sizeof(struct ethhdr) + len);
......@@ -5444,10 +5451,25 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
ehdr->h_proto = proto;
skb->dev = dev;
skb->protocol = htons(ETH_P_802_3);
skb->protocol = proto;
skb_reset_network_header(skb);
skb_reset_mac_header(skb);
/* update QoS header to prioritize control port frames if possible,
* priorization also happens for control port frames send over
* AF_PACKET
*/
rcu_read_lock();
if (ieee80211_lookup_ra_sta(sdata, skb, &sta) == 0 && !IS_ERR(sta)) {
u16 queue = __ieee80211_select_queue(sdata, sta, skb);
skb_set_queue_mapping(skb, queue);
skb_get_hash(skb);
}
rcu_read_unlock();
/* mutex lock is only needed for incrementing the cookie counter */
mutex_lock(&local->mtx);
......
......@@ -752,6 +752,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
NL80211_SAE_PWE_BOTH),
[NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
[NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
[NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
......@@ -10019,6 +10020,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
req.flags |= ASSOC_REQ_DISABLE_VHT;
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
req.flags |= ASSOC_REQ_DISABLE_HE;
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
memcpy(&req.vht_capa_mask,
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
......@@ -10802,6 +10806,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT]))
connect.flags |= ASSOC_REQ_DISABLE_VHT;
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
connect.flags |= ASSOC_REQ_DISABLE_HE;
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
memcpy(&connect.vht_capa_mask,
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
......
......@@ -1629,7 +1629,7 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
{
const struct ieee80211_regdomain *regd = reg_get_regdomain(wiphy);
static const u32 bws[] = {0, 1, 2, 4, 5, 8, 10, 16, 20};
const struct ieee80211_reg_rule *reg_rule;
const struct ieee80211_reg_rule *reg_rule = ERR_PTR(-ERANGE);
int i = ARRAY_SIZE(bws) - 1;
u32 bw;
......
......@@ -82,12 +82,6 @@ static void wiphy_dev_release(struct device *dev)
cfg80211_dev_free(rdev);
}
static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
{
/* TODO, we probably need stuff here */
return 0;
}
#ifdef CONFIG_PM_SLEEP
static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
{
......@@ -162,7 +156,6 @@ struct class ieee80211_class = {
.owner = THIS_MODULE,
.dev_release = wiphy_dev_release,
.dev_groups = ieee80211_groups,
.dev_uevent = wiphy_uevent,
.pm = WIPHY_PM_OPS,
.ns_type = &net_ns_type_operations,
.namespace = wiphy_namespace,
......
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