[openwrt/openwrt] mac80211: add minstrel improvements/fixes

LEDE Commits lede-commits at lists.infradead.org
Wed Feb 21 10:30:30 PST 2018


nbd pushed a commit to openwrt/openwrt.git, branch master:
https://git.lede-project.org/c8d07575e5bca43966651bd5b9b3f8c22bbe43ca

commit c8d07575e5bca43966651bd5b9b3f8c22bbe43ca
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Mon Feb 12 21:38:30 2018 +0100

    mac80211: add minstrel improvements/fixes
    
    - Simplify debugfs code
    - Reduce size
    - Fix handling of CCK rates
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 ...nstrel-remove-unnecessary-debugfs-cleanup.patch | 150 ++++++
 ...nstrel-merge-with-minstrel_ht-always-enab.patch | 588 +++++++++++++++++++++
 ...-minstrel-reduce-minstrel_mcs_groups-size.patch | 300 +++++++++++
 ...nstrel-fix-using-short-preamble-CCK-rates.patch |  23 +
 4 files changed, 1061 insertions(+)

diff --git a/package/kernel/mac80211/patches/326-mac80211-minstrel-remove-unnecessary-debugfs-cleanup.patch b/package/kernel/mac80211/patches/326-mac80211-minstrel-remove-unnecessary-debugfs-cleanup.patch
new file mode 100644
index 0000000..14cf664
--- /dev/null
+++ b/package/kernel/mac80211/patches/326-mac80211-minstrel-remove-unnecessary-debugfs-cleanup.patch
@@ -0,0 +1,150 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Sat, 10 Feb 2018 12:41:51 +0100
+Subject: [PATCH] mac80211: minstrel: remove unnecessary debugfs cleanup
+ code
+
+debugfs entries are cleaned up by debugfs_remove_recursive already.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel.c
++++ b/net/mac80211/rc80211_minstrel.c
+@@ -689,8 +689,8 @@ minstrel_alloc(struct ieee80211_hw *hw,
+ 
+ #ifdef CPTCFG_MAC80211_DEBUGFS
+ 	mp->fixed_rate_idx = (u32) -1;
+-	mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx",
+-			S_IRUGO | S_IWUGO, debugfsdir, &mp->fixed_rate_idx);
++	debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
++			   &mp->fixed_rate_idx);
+ #endif
+ 
+ 	minstrel_init_cck_rates(mp);
+@@ -701,9 +701,6 @@ minstrel_alloc(struct ieee80211_hw *hw,
+ static void
+ minstrel_free(void *priv)
+ {
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+-	debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate);
+-#endif
+ 	kfree(priv);
+ }
+ 
+@@ -735,7 +732,6 @@ const struct rate_control_ops mac80211_m
+ 	.free_sta = minstrel_free_sta,
+ #ifdef CPTCFG_MAC80211_DEBUGFS
+ 	.add_sta_debugfs = minstrel_add_sta_debugfs,
+-	.remove_sta_debugfs = minstrel_remove_sta_debugfs,
+ #endif
+ 	.get_expected_throughput = minstrel_get_expected_throughput,
+ };
+--- a/net/mac80211/rc80211_minstrel.h
++++ b/net/mac80211/rc80211_minstrel.h
+@@ -109,11 +109,6 @@ struct minstrel_sta_info {
+ 
+ 	/* sampling table */
+ 	u8 *sample_table;
+-
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+-	struct dentry *dbg_stats;
+-	struct dentry *dbg_stats_csv;
+-#endif
+ };
+ 
+ struct minstrel_priv {
+@@ -137,7 +132,6 @@ struct minstrel_priv {
+ 	 *   - setting will be applied on next update
+ 	 */
+ 	u32 fixed_rate_idx;
+-	struct dentry *dbg_fixed_rate;
+ #endif
+ };
+ 
+@@ -156,7 +150,6 @@ minstrel_get_ewmsd10(struct minstrel_rat
+ 
+ extern const struct rate_control_ops mac80211_minstrel;
+ void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
+-void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
+ 
+ /* Recalculate success probabilities and counters for a given rate using EWMA */
+ void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
+--- a/net/mac80211/rc80211_minstrel_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_debugfs.c
+@@ -214,19 +214,7 @@ minstrel_add_sta_debugfs(void *priv, voi
+ {
+ 	struct minstrel_sta_info *mi = priv_sta;
+ 
+-	mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi,
+-			&minstrel_stat_fops);
+-
+-	mi->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO, dir,
+-			mi, &minstrel_stat_csv_fops);
+-}
+-
+-void
+-minstrel_remove_sta_debugfs(void *priv, void *priv_sta)
+-{
+-	struct minstrel_sta_info *mi = priv_sta;
+-
+-	debugfs_remove(mi->dbg_stats);
+-
+-	debugfs_remove(mi->dbg_stats_csv);
++	debugfs_create_file("rc_stats", S_IRUGO, dir, mi, &minstrel_stat_fops);
++	debugfs_create_file("rc_stats_csv", S_IRUGO, dir, mi,
++			    &minstrel_stat_csv_fops);
+ }
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -1393,7 +1393,6 @@ static const struct rate_control_ops mac
+ 	.free = minstrel_ht_free,
+ #ifdef CPTCFG_MAC80211_DEBUGFS
+ 	.add_sta_debugfs = minstrel_ht_add_sta_debugfs,
+-	.remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
+ #endif
+ 	.get_expected_throughput = minstrel_ht_get_expected_throughput,
+ };
+--- a/net/mac80211/rc80211_minstrel_ht.h
++++ b/net/mac80211/rc80211_minstrel_ht.h
+@@ -110,17 +110,12 @@ struct minstrel_ht_sta_priv {
+ 		struct minstrel_ht_sta ht;
+ 		struct minstrel_sta_info legacy;
+ 	};
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+-	struct dentry *dbg_stats;
+-	struct dentry *dbg_stats_csv;
+-#endif
+ 	void *ratelist;
+ 	void *sample_table;
+ 	bool is_ht;
+ };
+ 
+ void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
+-void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
+ int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
+ 			   int prob_ewma);
+ 
+--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
+@@ -303,17 +303,8 @@ minstrel_ht_add_sta_debugfs(void *priv,
+ {
+ 	struct minstrel_ht_sta_priv *msp = priv_sta;
+ 
+-	msp->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, msp,
+-			&minstrel_ht_stat_fops);
+-	msp->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO,
+-			     dir, msp, &minstrel_ht_stat_csv_fops);
+-}
+-
+-void
+-minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta)
+-{
+-	struct minstrel_ht_sta_priv *msp = priv_sta;
+-
+-	debugfs_remove(msp->dbg_stats);
+-	debugfs_remove(msp->dbg_stats_csv);
++	debugfs_create_file("rc_stats", S_IRUGO, dir, msp,
++			    &minstrel_ht_stat_fops);
++	debugfs_create_file("rc_stats_csv", S_IRUGO, dir, msp,
++			    &minstrel_ht_stat_csv_fops);
+ }
diff --git a/package/kernel/mac80211/patches/327-mac80211-minstrel-merge-with-minstrel_ht-always-enab.patch b/package/kernel/mac80211/patches/327-mac80211-minstrel-merge-with-minstrel_ht-always-enab.patch
new file mode 100644
index 0000000..fe71079
--- /dev/null
+++ b/package/kernel/mac80211/patches/327-mac80211-minstrel-merge-with-minstrel_ht-always-enab.patch
@@ -0,0 +1,588 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Sat, 10 Feb 2018 12:43:30 +0100
+Subject: [PATCH] mac80211: minstrel: merge with minstrel_ht, always enable
+ VHT support
+
+Legacy-only devices are not very common and the overhead of the extra
+code for HT and VHT rates is not big enough to justify all those extra
+lines of code to make it optional.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/Kconfig
++++ b/net/mac80211/Kconfig
+@@ -25,20 +25,6 @@ config MAC80211_RC_MINSTREL
+ 	---help---
+ 	  This option enables the 'minstrel' TX rate control algorithm
+ 
+-config MAC80211_RC_MINSTREL_HT
+-	bool "Minstrel 802.11n support" if EXPERT
+-	depends on MAC80211_RC_MINSTREL
+-	default y
+-	---help---
+-	  This option enables the 'minstrel_ht' TX rate control algorithm
+-
+-config MAC80211_RC_MINSTREL_VHT
+-	bool "Minstrel 802.11ac support" if EXPERT
+-	depends on MAC80211_RC_MINSTREL_HT
+-	default n
+-	---help---
+-	  This option enables VHT in the 'minstrel_ht' TX rate control algorithm
+-
+ choice
+ 	prompt "Default rate control algorithm"
+ 	depends on MAC80211_HAS_RC
+@@ -60,8 +46,7 @@ endchoice
+ 
+ config MAC80211_RC_DEFAULT
+ 	string
+-	default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT
+-	default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
++	default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL
+ 	default ""
+ 
+ endif
+--- a/net/mac80211/Makefile
++++ b/net/mac80211/Makefile
+@@ -50,13 +50,14 @@ mac80211-$(CONFIG_PM) += pm.o
+ 
+ CFLAGS_trace.o := -I$(src)
+ 
+-rc80211_minstrel-y := rc80211_minstrel.o
+-rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o
++rc80211_minstrel-y := \
++	rc80211_minstrel.o \
++	rc80211_minstrel_ht.o
+ 
+-rc80211_minstrel_ht-y := rc80211_minstrel_ht.o
+-rc80211_minstrel_ht-$(CPTCFG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o
++rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += \
++	rc80211_minstrel_debugfs.o \
++	rc80211_minstrel_ht_debugfs.o
+ 
+ mac80211-$(CPTCFG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
+-mac80211-$(CPTCFG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y)
+ 
+ ccflags-y += -DDEBUG
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -1252,18 +1252,12 @@ static int __init ieee80211_init(void)
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = rc80211_minstrel_ht_init();
+-	if (ret)
+-		goto err_minstrel;
+-
+ 	ret = ieee80211_iface_init();
+ 	if (ret)
+ 		goto err_netdev;
+ 
+ 	return 0;
+  err_netdev:
+-	rc80211_minstrel_ht_exit();
+- err_minstrel:
+ 	rc80211_minstrel_exit();
+ 
+ 	return ret;
+@@ -1271,7 +1265,6 @@ static int __init ieee80211_init(void)
+ 
+ static void __exit ieee80211_exit(void)
+ {
+-	rc80211_minstrel_ht_exit();
+ 	rc80211_minstrel_exit();
+ 
+ 	ieee80211s_stop();
+--- a/net/mac80211/rate.h
++++ b/net/mac80211/rate.h
+@@ -95,18 +95,5 @@ static inline void rc80211_minstrel_exit
+ }
+ #endif
+ 
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_HT
+-int rc80211_minstrel_ht_init(void);
+-void rc80211_minstrel_ht_exit(void);
+-#else
+-static inline int rc80211_minstrel_ht_init(void)
+-{
+-	return 0;
+-}
+-static inline void rc80211_minstrel_ht_exit(void)
+-{
+-}
+-#endif
+-
+ 
+ #endif /* IEEE80211_RATE_H */
+--- a/net/mac80211/rc80211_minstrel.c
++++ b/net/mac80211/rc80211_minstrel.c
+@@ -482,6 +482,38 @@ init_sample_table(struct minstrel_sta_in
+ }
+ 
+ static void
++minstrel_init_cck_rates(struct minstrel_priv *mp,
++			struct cfg80211_chan_def *chandef)
++{
++	static const int bitrates[4] = { 10, 20, 55, 110 };
++	struct ieee80211_supported_band *sband;
++	u32 rate_flags = ieee80211_chandef_rate_flags(chandef);
++	int i, j;
++
++	sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ];
++	if (!sband)
++		return;
++
++	for (i = 0, j = 0; i < sband->n_bitrates; i++) {
++		struct ieee80211_rate *rate = &sband->bitrates[i];
++
++		if (rate->flags & IEEE80211_RATE_ERP_G)
++			continue;
++
++		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
++			continue;
++
++		for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
++			if (rate->bitrate != bitrates[j])
++				continue;
++
++			mp->cck_rates[j] = i;
++			break;
++		}
++	}
++}
++
++static void
+ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
+ 		   struct cfg80211_chan_def *chandef,
+ 		   struct ieee80211_sta *sta, void *priv_sta)
+@@ -493,6 +525,8 @@ minstrel_rate_init(void *priv, struct ie
+ 	unsigned int t_slot = 9; /* FIXME: get real slot time */
+ 	u32 rate_flags;
+ 
++	minstrel_init_cck_rates(mp, chandef);
++
+ 	mi->sta = sta;
+ 	mi->lowest_rix = rate_lowest_index(sband, sta);
+ 	ctl_rate = &sband->bitrates[mi->lowest_rix];
+@@ -572,138 +606,6 @@ minstrel_rate_init(void *priv, struct ie
+ 	minstrel_update_rates(mp, mi);
+ }
+ 
+-static void *
+-minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
+-{
+-	struct ieee80211_supported_band *sband;
+-	struct minstrel_sta_info *mi;
+-	struct minstrel_priv *mp = priv;
+-	struct ieee80211_hw *hw = mp->hw;
+-	int max_rates = 0;
+-	int i;
+-
+-	mi = kzalloc(sizeof(struct minstrel_sta_info), gfp);
+-	if (!mi)
+-		return NULL;
+-
+-	for (i = 0; i < NUM_NL80211_BANDS; i++) {
+-		sband = hw->wiphy->bands[i];
+-		if (sband && sband->n_bitrates > max_rates)
+-			max_rates = sband->n_bitrates;
+-	}
+-
+-	mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp);
+-	if (!mi->r)
+-		goto error;
+-
+-	mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp);
+-	if (!mi->sample_table)
+-		goto error1;
+-
+-	mi->last_stats_update = jiffies;
+-	return mi;
+-
+-error1:
+-	kfree(mi->r);
+-error:
+-	kfree(mi);
+-	return NULL;
+-}
+-
+-static void
+-minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta)
+-{
+-	struct minstrel_sta_info *mi = priv_sta;
+-
+-	kfree(mi->sample_table);
+-	kfree(mi->r);
+-	kfree(mi);
+-}
+-
+-static void
+-minstrel_init_cck_rates(struct minstrel_priv *mp)
+-{
+-	static const int bitrates[4] = { 10, 20, 55, 110 };
+-	struct ieee80211_supported_band *sband;
+-	u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
+-	int i, j;
+-
+-	sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ];
+-	if (!sband)
+-		return;
+-
+-	for (i = 0, j = 0; i < sband->n_bitrates; i++) {
+-		struct ieee80211_rate *rate = &sband->bitrates[i];
+-
+-		if (rate->flags & IEEE80211_RATE_ERP_G)
+-			continue;
+-
+-		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+-			continue;
+-
+-		for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
+-			if (rate->bitrate != bitrates[j])
+-				continue;
+-
+-			mp->cck_rates[j] = i;
+-			break;
+-		}
+-	}
+-}
+-
+-static void *
+-minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+-{
+-	struct minstrel_priv *mp;
+-
+-	mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
+-	if (!mp)
+-		return NULL;
+-
+-	/* contention window settings
+-	 * Just an approximation. Using the per-queue values would complicate
+-	 * the calculations and is probably unnecessary */
+-	mp->cw_min = 15;
+-	mp->cw_max = 1023;
+-
+-	/* number of packets (in %) to use for sampling other rates
+-	 * sample less often for non-mrr packets, because the overhead
+-	 * is much higher than with mrr */
+-	mp->lookaround_rate = 5;
+-	mp->lookaround_rate_mrr = 10;
+-
+-	/* maximum time that the hw is allowed to stay in one MRR segment */
+-	mp->segment_size = 6000;
+-
+-	if (hw->max_rate_tries > 0)
+-		mp->max_retry = hw->max_rate_tries;
+-	else
+-		/* safe default, does not necessarily have to match hw properties */
+-		mp->max_retry = 7;
+-
+-	if (hw->max_rates >= 4)
+-		mp->has_mrr = true;
+-
+-	mp->hw = hw;
+-	mp->update_interval = 100;
+-
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+-	mp->fixed_rate_idx = (u32) -1;
+-	debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
+-			   &mp->fixed_rate_idx);
+-#endif
+-
+-	minstrel_init_cck_rates(mp);
+-
+-	return mp;
+-}
+-
+-static void
+-minstrel_free(void *priv)
+-{
+-	kfree(priv);
+-}
+-
+ static u32 minstrel_get_expected_throughput(void *priv_sta)
+ {
+ 	struct minstrel_sta_info *mi = priv_sta;
+@@ -722,29 +624,8 @@ static u32 minstrel_get_expected_through
+ }
+ 
+ const struct rate_control_ops mac80211_minstrel = {
+-	.name = "minstrel",
+ 	.tx_status_ext = minstrel_tx_status,
+ 	.get_rate = minstrel_get_rate,
+ 	.rate_init = minstrel_rate_init,
+-	.alloc = minstrel_alloc,
+-	.free = minstrel_free,
+-	.alloc_sta = minstrel_alloc_sta,
+-	.free_sta = minstrel_free_sta,
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+-	.add_sta_debugfs = minstrel_add_sta_debugfs,
+-#endif
+ 	.get_expected_throughput = minstrel_get_expected_throughput,
+ };
+-
+-int __init
+-rc80211_minstrel_init(void)
+-{
+-	return ieee80211_rate_control_register(&mac80211_minstrel);
+-}
+-
+-void
+-rc80211_minstrel_exit(void)
+-{
+-	ieee80211_rate_control_unregister(&mac80211_minstrel);
+-}
+-
+--- a/net/mac80211/rc80211_minstrel.h
++++ b/net/mac80211/rc80211_minstrel.h
+@@ -158,7 +158,5 @@ int minstrel_get_tp_avg(struct minstrel_
+ /* debugfs */
+ int minstrel_stats_open(struct inode *inode, struct file *file);
+ int minstrel_stats_csv_open(struct inode *inode, struct file *file);
+-ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos);
+-int minstrel_stats_release(struct inode *inode, struct file *file);
+ 
+ #endif
+--- a/net/mac80211/rc80211_minstrel_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_debugfs.c
+@@ -54,22 +54,6 @@
+ #include <net/mac80211.h>
+ #include "rc80211_minstrel.h"
+ 
+-ssize_t
+-minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
+-{
+-	struct minstrel_debugfs_info *ms;
+-
+-	ms = file->private_data;
+-	return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
+-}
+-
+-int
+-minstrel_stats_release(struct inode *inode, struct file *file)
+-{
+-	kfree(file->private_data);
+-	return 0;
+-}
+-
+ int
+ minstrel_stats_open(struct inode *inode, struct file *file)
+ {
+@@ -135,14 +119,6 @@ minstrel_stats_open(struct inode *inode,
+ 	return 0;
+ }
+ 
+-static const struct file_operations minstrel_stat_fops = {
+-	.owner = THIS_MODULE,
+-	.open = minstrel_stats_open,
+-	.read = minstrel_stats_read,
+-	.release = minstrel_stats_release,
+-	.llseek = default_llseek,
+-};
+-
+ int
+ minstrel_stats_csv_open(struct inode *inode, struct file *file)
+ {
+@@ -200,21 +176,3 @@ minstrel_stats_csv_open(struct inode *in
+ 
+ 	return 0;
+ }
+-
+-static const struct file_operations minstrel_stat_csv_fops = {
+-	.owner = THIS_MODULE,
+-	.open = minstrel_stats_csv_open,
+-	.read = minstrel_stats_read,
+-	.release = minstrel_stats_release,
+-	.llseek = default_llseek,
+-};
+-
+-void
+-minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
+-{
+-	struct minstrel_sta_info *mi = priv_sta;
+-
+-	debugfs_create_file("rc_stats", S_IRUGO, dir, mi, &minstrel_stat_fops);
+-	debugfs_create_file("rc_stats_csv", S_IRUGO, dir, mi,
+-			    &minstrel_stat_csv_fops);
+-}
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -137,12 +137,10 @@
+ 		}					\
+ 	}
+ 
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ static bool minstrel_vht_only = true;
+ module_param(minstrel_vht_only, bool, 0644);
+ MODULE_PARM_DESC(minstrel_vht_only,
+ 		 "Use only VHT rates when VHT is supported by sta.");
+-#endif
+ 
+ /*
+  * To enable sufficiently targeted rate sampling, MCS rates are divided into
+@@ -171,7 +169,6 @@ const struct mcs_group minstrel_mcs_grou
+ 
+ 	CCK_GROUP,
+ 
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ 	VHT_GROUP(1, 0, BW_20),
+ 	VHT_GROUP(2, 0, BW_20),
+ 	VHT_GROUP(3, 0, BW_20),
+@@ -195,7 +192,6 @@ const struct mcs_group minstrel_mcs_grou
+ 	VHT_GROUP(1, 1, BW_80),
+ 	VHT_GROUP(2, 1, BW_80),
+ 	VHT_GROUP(3, 1, BW_80),
+-#endif
+ };
+ 
+ static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
+@@ -1146,12 +1142,10 @@ minstrel_ht_update_caps(void *priv, stru
+ 
+ 	BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB);
+ 
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ 	if (vht_cap->vht_supported)
+ 		use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0);
+ 	else
+-#endif
+-	use_vht = 0;
++		use_vht = 0;
+ 
+ 	msp->is_ht = true;
+ 	memset(mi, 0, sizeof(*mi));
+@@ -1226,10 +1220,9 @@ minstrel_ht_update_caps(void *priv, stru
+ 
+ 		/* HT rate */
+ 		if (gflags & IEEE80211_TX_RC_MCS) {
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ 			if (use_vht && minstrel_vht_only)
+ 				continue;
+-#endif
++
+ 			mi->supported[i] = mcs->rx_mask[nss - 1];
+ 			if (mi->supported[i])
+ 				n_supported++;
+@@ -1352,13 +1345,52 @@ minstrel_ht_free_sta(void *priv, struct
+ static void *
+ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+ {
+-	return mac80211_minstrel.alloc(hw, debugfsdir);
++	struct minstrel_priv *mp;
++
++	mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
++	if (!mp)
++		return NULL;
++
++	/* contention window settings
++	 * Just an approximation. Using the per-queue values would complicate
++	 * the calculations and is probably unnecessary */
++	mp->cw_min = 15;
++	mp->cw_max = 1023;
++
++	/* number of packets (in %) to use for sampling other rates
++	 * sample less often for non-mrr packets, because the overhead
++	 * is much higher than with mrr */
++	mp->lookaround_rate = 5;
++	mp->lookaround_rate_mrr = 10;
++
++	/* maximum time that the hw is allowed to stay in one MRR segment */
++	mp->segment_size = 6000;
++
++	if (hw->max_rate_tries > 0)
++		mp->max_retry = hw->max_rate_tries;
++	else
++		/* safe default, does not necessarily have to match hw properties */
++		mp->max_retry = 7;
++
++	if (hw->max_rates >= 4)
++		mp->has_mrr = true;
++
++	mp->hw = hw;
++	mp->update_interval = 100;
++
++#ifdef CPTCFG_MAC80211_DEBUGFS
++	mp->fixed_rate_idx = (u32) -1;
++	debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
++			   &mp->fixed_rate_idx);
++#endif
++
++	return mp;
+ }
+ 
+ static void
+ minstrel_ht_free(void *priv)
+ {
+-	mac80211_minstrel.free(priv);
++	kfree(priv);
+ }
+ 
+ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
+@@ -1417,14 +1449,14 @@ static void __init init_sample_table(voi
+ }
+ 
+ int __init
+-rc80211_minstrel_ht_init(void)
++rc80211_minstrel_init(void)
+ {
+ 	init_sample_table();
+ 	return ieee80211_rate_control_register(&mac80211_minstrel_ht);
+ }
+ 
+ void
+-rc80211_minstrel_ht_exit(void)
++rc80211_minstrel_exit(void)
+ {
+ 	ieee80211_rate_control_unregister(&mac80211_minstrel_ht);
+ }
+--- a/net/mac80211/rc80211_minstrel_ht.h
++++ b/net/mac80211/rc80211_minstrel_ht.h
+@@ -15,11 +15,7 @@
+  */
+ #define MINSTREL_MAX_STREAMS		3
+ #define MINSTREL_HT_STREAM_GROUPS	4 /* BW(=2) * SGI(=2) */
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ #define MINSTREL_VHT_STREAM_GROUPS	6 /* BW(=3) * SGI(=2) */
+-#else
+-#define MINSTREL_VHT_STREAM_GROUPS	0
+-#endif
+ 
+ #define MINSTREL_HT_GROUPS_NB	(MINSTREL_MAX_STREAMS *		\
+ 				 MINSTREL_HT_STREAM_GROUPS)
+@@ -34,11 +30,7 @@
+ #define MINSTREL_CCK_GROUP	(MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB)
+ #define MINSTREL_VHT_GROUP_0	(MINSTREL_CCK_GROUP + 1)
+ 
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ #define MCS_GROUP_RATES		10
+-#else
+-#define MCS_GROUP_RATES		8
+-#endif
+ 
+ struct mcs_group {
+ 	u32 flags;
+--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
+@@ -15,6 +15,22 @@
+ #include "rc80211_minstrel.h"
+ #include "rc80211_minstrel_ht.h"
+ 
++static ssize_t
++minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
++{
++	struct minstrel_debugfs_info *ms;
++
++	ms = file->private_data;
++	return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
++}
++
++static int
++minstrel_stats_release(struct inode *inode, struct file *file)
++{
++	kfree(file->private_data);
++	return 0;
++}
++
+ static char *
+ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
+ {
diff --git a/package/kernel/mac80211/patches/328-mac80211-minstrel-reduce-minstrel_mcs_groups-size.patch b/package/kernel/mac80211/patches/328-mac80211-minstrel-reduce-minstrel_mcs_groups-size.patch
new file mode 100644
index 0000000..d62c362
--- /dev/null
+++ b/package/kernel/mac80211/patches/328-mac80211-minstrel-reduce-minstrel_mcs_groups-size.patch
@@ -0,0 +1,300 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Sat, 10 Feb 2018 12:45:47 +0100
+Subject: [PATCH] mac80211: minstrel: reduce minstrel_mcs_groups size
+
+By storing a shift value for all duration values of a group, we can
+reduce precision by a neglegible amount to make it fit into a u16 value.
+This improves cache footprint and reduces size:
+
+Before:
+   text    data     bss     dec     hex filename
+  10024     116       0   10140    279c rc80211_minstrel_ht.o
+
+After:
+   text    data     bss     dec     hex filename
+   9368     116       0    9484    250c rc80211_minstrel_ht.o
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -52,22 +52,23 @@
+ 	_streams - 1
+ 
+ /* MCS rate information for an MCS group */
+-#define MCS_GROUP(_streams, _sgi, _ht40)				\
++#define MCS_GROUP(_streams, _sgi, _ht40, _s)				\
+ 	[GROUP_IDX(_streams, _sgi, _ht40)] = {				\
+ 	.streams = _streams,						\
++	.shift = _s,							\
+ 	.flags =							\
+ 		IEEE80211_TX_RC_MCS |					\
+ 		(_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) |			\
+ 		(_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0),		\
+ 	.duration = {							\
+-		MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26),		\
+-		MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52),		\
+-		MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78),		\
+-		MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104),	\
+-		MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156),	\
+-		MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208),	\
+-		MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234),	\
+-		MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260)		\
++		MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s,	\
++		MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s,	\
++		MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s,	\
++		MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s,	\
++		MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s,	\
++		MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s,	\
++		MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s,	\
++		MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s	\
+ 	}								\
+ }
+ 
+@@ -80,9 +81,10 @@
+ #define BW2VBPS(_bw, r3, r2, r1)					\
+ 	(_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
+ 
+-#define VHT_GROUP(_streams, _sgi, _bw)					\
++#define VHT_GROUP(_streams, _sgi, _bw, _s)				\
+ 	[VHT_GROUP_IDX(_streams, _sgi, _bw)] = {			\
+ 	.streams = _streams,						\
++	.shift = _s,							\
+ 	.flags =							\
+ 		IEEE80211_TX_RC_VHT_MCS |				\
+ 		(_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) |			\
+@@ -90,25 +92,25 @@
+ 		 _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0),	\
+ 	.duration = {							\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw,  117,  54,  26)),		\
++			     BW2VBPS(_bw,  117,  54,  26)) >> _s,	\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw,  234, 108,  52)),		\
++			     BW2VBPS(_bw,  234, 108,  52)) >> _s,	\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw,  351, 162,  78)),		\
++			     BW2VBPS(_bw,  351, 162,  78)) >> _s,	\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw,  468, 216, 104)),		\
++			     BW2VBPS(_bw,  468, 216, 104)) >> _s,	\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw,  702, 324, 156)),		\
++			     BW2VBPS(_bw,  702, 324, 156)) >> _s,	\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw,  936, 432, 208)),		\
++			     BW2VBPS(_bw,  936, 432, 208)) >> _s,	\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw, 1053, 486, 234)),		\
++			     BW2VBPS(_bw, 1053, 486, 234)) >> _s,	\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw, 1170, 540, 260)),		\
++			     BW2VBPS(_bw, 1170, 540, 260)) >> _s,	\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw, 1404, 648, 312)),		\
++			     BW2VBPS(_bw, 1404, 648, 312)) >> _s,	\
+ 		MCS_DURATION(_streams, _sgi,				\
+-			     BW2VBPS(_bw, 1560, 720, 346))		\
++			     BW2VBPS(_bw, 1560, 720, 346)) >> _s	\
+ 	}								\
+ }
+ 
+@@ -121,19 +123,20 @@
+ 	(CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) +	\
+ 	 CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE))
+ 
+-#define CCK_DURATION_LIST(_short)			\
+-	CCK_ACK_DURATION(10, _short),			\
+-	CCK_ACK_DURATION(20, _short),			\
+-	CCK_ACK_DURATION(55, _short),			\
+-	CCK_ACK_DURATION(110, _short)
++#define CCK_DURATION_LIST(_short, _s)			\
++	CCK_ACK_DURATION(10, _short) >> _s,		\
++	CCK_ACK_DURATION(20, _short) >> _s,		\
++	CCK_ACK_DURATION(55, _short) >> _s,		\
++	CCK_ACK_DURATION(110, _short) >> _s
+ 
+-#define CCK_GROUP					\
++#define CCK_GROUP(_s)					\
+ 	[MINSTREL_CCK_GROUP] = {			\
+ 		.streams = 0,				\
+ 		.flags = 0,				\
++		.shift = _s,				\
+ 		.duration = {				\
+-			CCK_DURATION_LIST(false),	\
+-			CCK_DURATION_LIST(true)		\
++			CCK_DURATION_LIST(false, _s),	\
++			CCK_DURATION_LIST(true, _s)	\
+ 		}					\
+ 	}
+ 
+@@ -151,47 +154,47 @@ MODULE_PARM_DESC(minstrel_vht_only,
+  * BW -> SGI -> #streams
+  */
+ const struct mcs_group minstrel_mcs_groups[] = {
+-	MCS_GROUP(1, 0, BW_20),
+-	MCS_GROUP(2, 0, BW_20),
+-	MCS_GROUP(3, 0, BW_20),
++	MCS_GROUP(1, 0, BW_20, 5),
++	MCS_GROUP(2, 0, BW_20, 4),
++	MCS_GROUP(3, 0, BW_20, 4),
+ 
+-	MCS_GROUP(1, 1, BW_20),
+-	MCS_GROUP(2, 1, BW_20),
+-	MCS_GROUP(3, 1, BW_20),
++	MCS_GROUP(1, 1, BW_20, 5),
++	MCS_GROUP(2, 1, BW_20, 4),
++	MCS_GROUP(3, 1, BW_20, 4),
+ 
+-	MCS_GROUP(1, 0, BW_40),
+-	MCS_GROUP(2, 0, BW_40),
+-	MCS_GROUP(3, 0, BW_40),
++	MCS_GROUP(1, 0, BW_40, 4),
++	MCS_GROUP(2, 0, BW_40, 4),
++	MCS_GROUP(3, 0, BW_40, 4),
+ 
+-	MCS_GROUP(1, 1, BW_40),
+-	MCS_GROUP(2, 1, BW_40),
+-	MCS_GROUP(3, 1, BW_40),
++	MCS_GROUP(1, 1, BW_40, 4),
++	MCS_GROUP(2, 1, BW_40, 4),
++	MCS_GROUP(3, 1, BW_40, 4),
+ 
+-	CCK_GROUP,
++	CCK_GROUP(8),
+ 
+-	VHT_GROUP(1, 0, BW_20),
+-	VHT_GROUP(2, 0, BW_20),
+-	VHT_GROUP(3, 0, BW_20),
++	VHT_GROUP(1, 0, BW_20, 5),
++	VHT_GROUP(2, 0, BW_20, 4),
++	VHT_GROUP(3, 0, BW_20, 4),
+ 
+-	VHT_GROUP(1, 1, BW_20),
+-	VHT_GROUP(2, 1, BW_20),
+-	VHT_GROUP(3, 1, BW_20),
++	VHT_GROUP(1, 1, BW_20, 5),
++	VHT_GROUP(2, 1, BW_20, 4),
++	VHT_GROUP(3, 1, BW_20, 4),
+ 
+-	VHT_GROUP(1, 0, BW_40),
+-	VHT_GROUP(2, 0, BW_40),
+-	VHT_GROUP(3, 0, BW_40),
++	VHT_GROUP(1, 0, BW_40, 4),
++	VHT_GROUP(2, 0, BW_40, 4),
++	VHT_GROUP(3, 0, BW_40, 4),
+ 
+-	VHT_GROUP(1, 1, BW_40),
+-	VHT_GROUP(2, 1, BW_40),
+-	VHT_GROUP(3, 1, BW_40),
++	VHT_GROUP(1, 1, BW_40, 4),
++	VHT_GROUP(2, 1, BW_40, 4),
++	VHT_GROUP(3, 1, BW_40, 4),
+ 
+-	VHT_GROUP(1, 0, BW_80),
+-	VHT_GROUP(2, 0, BW_80),
+-	VHT_GROUP(3, 0, BW_80),
++	VHT_GROUP(1, 0, BW_80, 4),
++	VHT_GROUP(2, 0, BW_80, 4),
++	VHT_GROUP(3, 0, BW_80, 4),
+ 
+-	VHT_GROUP(1, 1, BW_80),
+-	VHT_GROUP(2, 1, BW_80),
+-	VHT_GROUP(3, 1, BW_80),
++	VHT_GROUP(1, 1, BW_80, 4),
++	VHT_GROUP(2, 1, BW_80, 4),
++	VHT_GROUP(3, 1, BW_80, 4),
+ };
+ 
+ static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
+@@ -307,7 +310,8 @@ minstrel_ht_get_tp_avg(struct minstrel_h
+ 	if (group != MINSTREL_CCK_GROUP)
+ 		nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
+ 
+-	nsecs += minstrel_mcs_groups[group].duration[rate];
++	nsecs += minstrel_mcs_groups[group].duration[rate] <<
++		 minstrel_mcs_groups[group].shift;
+ 
+ 	/*
+ 	 * For the throughput calculation, limit the probability value to 90% to
+@@ -780,7 +784,7 @@ minstrel_calc_retransmit(struct minstrel
+ 	mrs->retry_updated = true;
+ 
+ 	group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
+-	tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;
++	tx_time_data = (group->duration[index % MCS_GROUP_RATES] << group->shift) * ampdu_len / 1000;
+ 
+ 	/* Contention time for first 2 tries */
+ 	ctime = (t_slot * cw) >> 1;
+@@ -880,14 +884,14 @@ minstrel_ht_get_max_amsdu_len(struct min
+ 		return 1;
+ 
+ 	/* If the rate is slower than single-stream MCS1, make A-MSDU limit small */
+-	if (g->duration[rate] > MCS_DURATION(1, 0, 52))
++	if ((g->duration[rate] << g->shift) > MCS_DURATION(1, 0, 52))
+ 		return 500;
+ 
+ 	/*
+ 	 * If the rate is slower than single-stream MCS4, limit A-MSDU to usual
+ 	 * data packet size
+ 	 */
+-	if (g->duration[rate] > MCS_DURATION(1, 0, 104))
++	if ((g->duration[rate] << g->shift) > MCS_DURATION(1, 0, 104))
+ 		return 1600;
+ 
+ 	/*
+@@ -895,7 +899,7 @@ minstrel_ht_get_max_amsdu_len(struct min
+ 	 * rate success probability is less than 75%, limit A-MSDU to twice the usual
+ 	 * data packet size
+ 	 */
+-	if (g->duration[rate] > MCS_DURATION(1, 0, 260) ||
++	if ((g->duration[rate] << g->shift) > MCS_DURATION(1, 0, 260) ||
+ 	    (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <
+ 	     MINSTREL_FRAC(75, 100)))
+ 		return 3200;
+@@ -946,7 +950,7 @@ static inline int
+ minstrel_get_duration(int index)
+ {
+ 	const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
+-	return group->duration[index % MCS_GROUP_RATES];
++	return group->duration[index % MCS_GROUP_RATES] << group->shift;
+ }
+ 
+ static int
+--- a/net/mac80211/rc80211_minstrel_ht.h
++++ b/net/mac80211/rc80211_minstrel_ht.h
+@@ -33,9 +33,10 @@
+ #define MCS_GROUP_RATES		10
+ 
+ struct mcs_group {
+-	u32 flags;
+-	unsigned int streams;
+-	unsigned int duration[MCS_GROUP_RATES];
++	u16 flags;
++	u8 streams;
++	u8 shift;
++	u16 duration[MCS_GROUP_RATES];
+ };
+ 
+ extern const struct mcs_group minstrel_mcs_groups[];
+--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
+@@ -95,7 +95,7 @@ minstrel_ht_stats_dump(struct minstrel_h
+ 		p += sprintf(p, "  %3u  ", idx);
+ 
+ 		/* tx_time[rate(i)] in usec */
+-		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
++		tx_time = DIV_ROUND_CLOSEST(mg->duration[j] << mg->shift, 1000);
+ 		p += sprintf(p, "%6u  ", tx_time);
+ 
+ 		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
+@@ -238,7 +238,7 @@ minstrel_ht_stats_csv_dump(struct minstr
+ 		}
+ 
+ 		p += sprintf(p, "%u,", idx);
+-		tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
++		tx_time = DIV_ROUND_CLOSEST(mg->duration[j] << mg->shift, 1000);
+ 		p += sprintf(p, "%u,", tx_time);
+ 
+ 		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
diff --git a/package/kernel/mac80211/patches/329-mac80211-minstrel-fix-using-short-preamble-CCK-rates.patch b/package/kernel/mac80211/patches/329-mac80211-minstrel-fix-using-short-preamble-CCK-rates.patch
new file mode 100644
index 0000000..5b298e6
--- /dev/null
+++ b/package/kernel/mac80211/patches/329-mac80211-minstrel-fix-using-short-preamble-CCK-rates.patch
@@ -0,0 +1,23 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Sat, 10 Feb 2018 13:43:07 +0100
+Subject: [PATCH] mac80211: minstrel: fix using short preamble CCK rates on
+ HT clients
+
+mi->supported[MINSTREL_CCK_GROUP] needs to be updated
+
+Fixes: 782dda00ab8e ("mac80211: minstrel_ht: move short preamble check out of get_rate")
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -1265,7 +1265,8 @@ minstrel_ht_update_caps(void *priv, stru
+ 		goto use_legacy;
+ 
+ 	if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE))
+-		mi->cck_supported_short |= mi->cck_supported_short << 4;
++		mi->supported[MINSTREL_CCK_GROUP] |=
++			mi->cck_supported_short << 4;
+ 
+ 	/* create an initial rate table with the lowest supported rates */
+ 	minstrel_ht_update_stats(mp, mi);



More information about the lede-commits mailing list