mac80211: update to wireless-testing 2017-01-31
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
91fce81df6
commit
649e766a64
204 changed files with 1426 additions and 12877 deletions
|
@ -10,13 +10,13 @@ include $(INCLUDE_DIR)/kernel.mk
|
|||
|
||||
PKG_NAME:=mac80211
|
||||
|
||||
PKG_VERSION:=2016-10-08
|
||||
PKG_VERSION:=2017-01-31
|
||||
PKG_RELEASE:=1
|
||||
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
|
||||
PKG_BACKPORT_VERSION:=
|
||||
PKG_HASH:=4f6350e3b75815060bfdf47ef266ad613c7bfea5b7b1dc4552dee69e1bebe4fb
|
||||
PKG_HASH:=75e6d39e34cf156212a2509172a4a62b673b69eb4a1d9aaa565f7fa719fa2317
|
||||
|
||||
PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2
|
||||
PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.xz
|
||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/kconf/conf.c
|
||||
+++ b/kconf/conf.c
|
||||
@@ -593,40 +593,12 @@ int main(int ac, char **av)
|
||||
@@ -594,40 +594,12 @@ int main(int ac, char **av)
|
||||
case oldconfig:
|
||||
case listnewconfig:
|
||||
case olddefconfig:
|
||||
|
@ -44,7 +44,7 @@
|
|||
break;
|
||||
--- a/kconf/confdata.c
|
||||
+++ b/kconf/confdata.c
|
||||
@@ -1169,6 +1169,8 @@ bool conf_set_all_new_symbols(enum conf_
|
||||
@@ -1170,6 +1170,8 @@ bool conf_set_all_new_symbols(enum conf_
|
||||
}
|
||||
bool has_changed = false;
|
||||
|
||||
|
@ -53,7 +53,7 @@
|
|||
for_all_symbols(i, sym) {
|
||||
if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
|
||||
continue;
|
||||
@@ -1212,8 +1214,6 @@ bool conf_set_all_new_symbols(enum conf_
|
||||
@@ -1213,8 +1215,6 @@ bool conf_set_all_new_symbols(enum conf_
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
--- a/compat/Makefile
|
||||
+++ b/compat/Makefile
|
||||
@@ -35,8 +35,6 @@ compat-$(CPTCFG_KERNEL_4_6) += backport-
|
||||
|
||||
compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o
|
||||
compat-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += crypto-skcipher.o
|
||||
-skcipher-objs += crypto-skcipher.o
|
||||
-obj-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += skcipher.o
|
||||
compat-$(CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP) += drivers-base-devcoredump.o
|
||||
compat-$(CPTCFG_BPAUTO_RHASHTABLE) += lib-rhashtable.o
|
||||
cordic-objs += lib-cordic.o
|
|
@ -0,0 +1,28 @@
|
|||
--- a/backport-include/linux/kconfig.h
|
||||
+++ b/backport-include/linux/kconfig.h
|
||||
@@ -5,6 +5,8 @@
|
||||
#include_next <linux/kconfig.h>
|
||||
#endif
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
|
||||
+
|
||||
#ifndef __ARG_PLACEHOLDER_1
|
||||
#define __ARG_PLACEHOLDER_1 0,
|
||||
#define config_enabled(cfg) _config_enabled(cfg)
|
||||
@@ -16,6 +18,7 @@
|
||||
* 3.1 - 3.3 had a broken version of this, so undef
|
||||
* (they didn't have __ARG_PLACEHOLDER_1)
|
||||
*/
|
||||
+
|
||||
#undef IS_ENABLED
|
||||
#define IS_ENABLED(option) \
|
||||
(config_enabled(option) || config_enabled(option##_MODULE))
|
||||
@@ -24,6 +27,8 @@
|
||||
#undef IS_BUILTIN
|
||||
#define IS_BUILTIN(option) config_enabled(option)
|
||||
|
||||
+#endif
|
||||
+
|
||||
#ifndef IS_REACHABLE
|
||||
/*
|
||||
* IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled
|
|
@ -1,22 +0,0 @@
|
|||
--- a/backport-include/linux/skbuff.h
|
||||
+++ b/backport-include/linux/skbuff.h
|
||||
@@ -305,6 +305,19 @@ static inline void skb_free_frag(void *d
|
||||
{
|
||||
put_page(virt_to_head_page(data));
|
||||
}
|
||||
+
|
||||
+#include <net/flow_keys.h>
|
||||
+#include <linux/jhash.h>
|
||||
+
|
||||
+static inline u32 skb_get_hash_perturb(struct sk_buff *skb, u32 key)
|
||||
+{
|
||||
+ struct flow_keys keys;
|
||||
+
|
||||
+ skb_flow_dissect(skb, &keys);
|
||||
+ return jhash_3words((__force u32)keys.dst,
|
||||
+ (__force u32)keys.src ^ keys.ip_proto,
|
||||
+ (__force u32)keys.ports, key);
|
||||
+}
|
||||
#endif
|
||||
|
||||
#endif /* __BACKPORT_SKBUFF_H */
|
152
package/kernel/mac80211/patches/005-revert-devcoredump.patch
Normal file
152
package/kernel/mac80211/patches/005-revert-devcoredump.patch
Normal file
|
@ -0,0 +1,152 @@
|
|||
--- a/compat/Makefile
|
||||
+++ b/compat/Makefile
|
||||
@@ -35,8 +35,6 @@ compat-$(CPTCFG_KERNEL_4_6) += backport-
|
||||
|
||||
compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o
|
||||
compat-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += crypto-skcipher.o
|
||||
-skcipher-objs += crypto-skcipher.o
|
||||
-obj-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += skcipher.o
|
||||
compat-$(CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP) += drivers-base-devcoredump.o
|
||||
compat-$(CPTCFG_BPAUTO_RHASHTABLE) += lib-rhashtable.o
|
||||
cordic-objs += lib-cordic.o
|
||||
--- a/compat/drivers-base-devcoredump.c
|
||||
+++ b/compat/drivers-base-devcoredump.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/workqueue.h>
|
||||
+#include "backports.h"
|
||||
|
||||
static struct class devcd_class;
|
||||
|
||||
@@ -40,6 +41,10 @@ static bool devcd_disabled;
|
||||
/* if data isn't read by userspace after 5 minutes then delete it */
|
||||
#define DEVCD_TIMEOUT (HZ * 60 * 5)
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
|
||||
+static struct bin_attribute devcd_attr_data;
|
||||
+#endif
|
||||
+
|
||||
struct devcd_entry {
|
||||
struct device devcd_dev;
|
||||
void *data;
|
||||
@@ -69,8 +74,7 @@ static void devcd_dev_release(struct dev
|
||||
* a struct device to know when it goes away?
|
||||
*/
|
||||
if (devcd->failing_dev->kobj.sd)
|
||||
- sysfs_delete_link(&devcd->failing_dev->kobj, &dev->kobj,
|
||||
- "devcoredump");
|
||||
+ sysfs_remove_link(&devcd->failing_dev->kobj, "devcoredump");
|
||||
|
||||
put_device(devcd->failing_dev);
|
||||
kfree(devcd);
|
||||
@@ -82,6 +86,9 @@ static void devcd_del(struct work_struct
|
||||
|
||||
devcd = container_of(wk, struct devcd_entry, del_wk.work);
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
|
||||
+ device_remove_bin_file(&devcd->devcd_dev, &devcd_attr_data);
|
||||
+#endif
|
||||
device_del(&devcd->devcd_dev);
|
||||
put_device(&devcd->devcd_dev);
|
||||
}
|
||||
@@ -115,6 +122,7 @@ static struct bin_attribute devcd_attr_d
|
||||
.write = devcd_data_write,
|
||||
};
|
||||
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
|
||||
static struct bin_attribute *devcd_dev_bin_attrs[] = {
|
||||
&devcd_attr_data, NULL,
|
||||
};
|
||||
@@ -126,6 +134,7 @@ static const struct attribute_group devc
|
||||
static const struct attribute_group *devcd_dev_groups[] = {
|
||||
&devcd_dev_group, NULL,
|
||||
};
|
||||
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) */
|
||||
|
||||
static int devcd_free(struct device *dev, void *data)
|
||||
{
|
||||
@@ -160,18 +169,11 @@ static ssize_t disabled_store(struct cla
|
||||
|
||||
return count;
|
||||
}
|
||||
-static CLASS_ATTR_RW(disabled);
|
||||
|
||||
-static struct attribute *devcd_class_attrs[] = {
|
||||
- &class_attr_disabled.attr,
|
||||
- NULL,
|
||||
+static struct class_attribute devcd_class_attrs[] = {
|
||||
+ __ATTR_RW(disabled),
|
||||
+ __ATTR_NULL
|
||||
};
|
||||
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
|
||||
-ATTRIBUTE_GROUPS(devcd_class);
|
||||
-#else
|
||||
-#define BP_ATTR_GRP_STRUCT device_attribute
|
||||
-ATTRIBUTE_GROUPS_BACKPORT(devcd_class);
|
||||
-#endif
|
||||
|
||||
static struct class devcd_class = {
|
||||
.name = "devcoredump",
|
||||
@@ -179,10 +181,8 @@ static struct class devcd_class = {
|
||||
.dev_release = devcd_dev_release,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
|
||||
.dev_groups = devcd_dev_groups,
|
||||
-#else
|
||||
- .dev_attrs = devcd_class_dev_attrs,
|
||||
#endif
|
||||
- .class_groups = devcd_class_groups,
|
||||
+ .class_attrs = devcd_class_attrs,
|
||||
};
|
||||
|
||||
static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count,
|
||||
@@ -325,6 +325,11 @@ void dev_coredumpm(struct device *dev, s
|
||||
if (device_add(&devcd->devcd_dev))
|
||||
goto put_device;
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
|
||||
+ if (device_create_bin_file(&devcd->devcd_dev, &devcd_attr_data))
|
||||
+ goto put_device;
|
||||
+#endif
|
||||
+
|
||||
if (sysfs_create_link(&devcd->devcd_dev.kobj, &dev->kobj,
|
||||
"failing_device"))
|
||||
/* nothing - symlink will be missing */;
|
||||
@@ -367,16 +372,13 @@ void dev_coredumpsg(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_coredumpsg);
|
||||
|
||||
-static int __init devcoredump_init(void)
|
||||
+int __init devcoredump_init(void)
|
||||
{
|
||||
- init_devcd_class_attrs();
|
||||
return class_register(&devcd_class);
|
||||
}
|
||||
-__initcall(devcoredump_init);
|
||||
|
||||
-static void __exit devcoredump_exit(void)
|
||||
+void __exit devcoredump_exit(void)
|
||||
{
|
||||
class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
|
||||
class_unregister(&devcd_class);
|
||||
}
|
||||
-__exitcall(devcoredump_exit);
|
||||
--- a/include/linux/backport-devcoredump.h
|
||||
+++ b/include/linux/backport-devcoredump.h
|
||||
@@ -66,7 +66,7 @@ static inline void _devcd_free_sgtable(s
|
||||
}
|
||||
|
||||
|
||||
-#ifdef CONFIG_DEV_COREDUMP
|
||||
+#ifdef CPTCFG_BPAUTO_WANT_DEV_COREDUMP
|
||||
void dev_coredumpv(struct device *dev, void *data, size_t datalen,
|
||||
gfp_t gfp);
|
||||
|
||||
@@ -100,6 +100,6 @@ static inline void dev_coredumpsg(struct
|
||||
{
|
||||
_devcd_free_sgtable(table);
|
||||
}
|
||||
-#endif /* CONFIG_DEV_COREDUMP */
|
||||
+#endif /* CPTCFG_BPAUTO_WANT_DEV_COREDUMP */
|
||||
|
||||
#endif /* __DEVCOREDUMP_H */
|
|
@ -0,0 +1,20 @@
|
|||
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
|
||||
@@ -177,7 +177,7 @@ static bool rt2800usb_tx_sta_fifo_read_c
|
||||
if (rt2800usb_txstatus_pending(rt2x00dev)) {
|
||||
/* Read register after 1 ms */
|
||||
hrtimer_start(&rt2x00dev->txstatus_timer,
|
||||
- TXSTATUS_READ_INTERVAL,
|
||||
+ ktime_set(0, TXSTATUS_READ_INTERVAL),
|
||||
HRTIMER_MODE_REL);
|
||||
return false;
|
||||
}
|
||||
@@ -204,7 +204,7 @@ static void rt2800usb_async_read_tx_stat
|
||||
|
||||
/* Read TX_STA_FIFO register after 2 ms */
|
||||
hrtimer_start(&rt2x00dev->txstatus_timer,
|
||||
- 2 * TXSTATUS_READ_INTERVAL,
|
||||
+ ktime_set(0, 2*TXSTATUS_READ_INTERVAL),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -32,8 +32,22 @@ static int nl80211_crypto_settings(struc
|
||||
struct cfg80211_crypto_settings *settings,
|
||||
int cipher_limit);
|
||||
|
||||
+static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
|
||||
+ struct genl_info *info);
|
||||
+static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
|
||||
+ struct genl_info *info);
|
||||
+
|
||||
/* the netlink family */
|
||||
-static struct genl_family nl80211_fam;
|
||||
+static struct genl_family nl80211_fam = {
|
||||
+ .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
|
||||
+ .name = NL80211_GENL_NAME, /* have users key off the name instead */
|
||||
+ .hdrsize = 0, /* no private header */
|
||||
+ .version = 1, /* no particular meaning now */
|
||||
+ .maxattr = NL80211_ATTR_MAX,
|
||||
+ .netnsok = true,
|
||||
+ .pre_doit = nl80211_pre_doit,
|
||||
+ .post_doit = nl80211_post_doit,
|
||||
+};
|
||||
|
||||
/* multicast groups */
|
||||
enum nl80211_multicast_groups {
|
||||
@@ -549,14 +563,13 @@ static int nl80211_prepare_wdev_dump(str
|
||||
|
||||
if (!cb->args[0]) {
|
||||
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
||||
- genl_family_attrbuf(&nl80211_fam),
|
||||
- nl80211_fam.maxattr, nl80211_policy);
|
||||
+ nl80211_fam.attrbuf, nl80211_fam.maxattr,
|
||||
+ nl80211_policy);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
- *wdev = __cfg80211_wdev_from_attrs(
|
||||
- sock_net(skb->sk),
|
||||
- genl_family_attrbuf(&nl80211_fam));
|
||||
+ *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
|
||||
+ nl80211_fam.attrbuf);
|
||||
if (IS_ERR(*wdev)) {
|
||||
err = PTR_ERR(*wdev);
|
||||
goto out_unlock;
|
||||
@@ -1903,7 +1916,7 @@ static int nl80211_dump_wiphy_parse(stru
|
||||
struct netlink_callback *cb,
|
||||
struct nl80211_dump_wiphy_state *state)
|
||||
{
|
||||
- struct nlattr **tb = genl_family_attrbuf(&nl80211_fam);
|
||||
+ struct nlattr **tb = nl80211_fam.attrbuf;
|
||||
int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
||||
tb, nl80211_fam.maxattr, nl80211_policy);
|
||||
/* ignore parse errors for backward compatibility */
|
||||
@@ -7733,7 +7746,6 @@ static int nl80211_send_survey(struct sk
|
||||
|
||||
static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
- struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
|
||||
struct survey_info survey;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wireless_dev *wdev;
|
||||
@@ -7746,7 +7758,7 @@ static int nl80211_dump_survey(struct sk
|
||||
return res;
|
||||
|
||||
/* prepare_wdev_dump parsed the attributes */
|
||||
- radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
|
||||
+ radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
|
||||
|
||||
if (!wdev->netdev) {
|
||||
res = -EINVAL;
|
||||
@@ -8594,14 +8606,14 @@ static int nl80211_testmode_dump(struct
|
||||
*/
|
||||
phy_idx = cb->args[0] - 1;
|
||||
} else {
|
||||
- struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
|
||||
-
|
||||
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
||||
- attrbuf, nl80211_fam.maxattr, nl80211_policy);
|
||||
+ nl80211_fam.attrbuf, nl80211_fam.maxattr,
|
||||
+ nl80211_policy);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
- rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
|
||||
+ rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
|
||||
+ nl80211_fam.attrbuf);
|
||||
if (IS_ERR(rdev)) {
|
||||
err = PTR_ERR(rdev);
|
||||
goto out_err;
|
||||
@@ -8609,8 +8621,9 @@ static int nl80211_testmode_dump(struct
|
||||
phy_idx = rdev->wiphy_idx;
|
||||
rdev = NULL;
|
||||
|
||||
- if (attrbuf[NL80211_ATTR_TESTDATA])
|
||||
- cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
|
||||
+ if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
|
||||
+ cb->args[1] =
|
||||
+ (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
|
||||
}
|
||||
|
||||
if (cb->args[1]) {
|
||||
@@ -10814,7 +10827,8 @@ static int handle_nan_filter(struct nlat
|
||||
|
||||
i = 0;
|
||||
nla_for_each_nested(attr, attr_filter, rem) {
|
||||
- filter[i].filter = nla_memdup(attr, GFP_KERNEL);
|
||||
+ filter[i].filter = kmemdup(nla_data(attr), nla_len(attr),
|
||||
+ GFP_KERNEL);
|
||||
filter[i].len = nla_len(attr);
|
||||
i++;
|
||||
}
|
||||
@@ -11450,7 +11464,6 @@ static int nl80211_prepare_vendor_dump(s
|
||||
struct cfg80211_registered_device **rdev,
|
||||
struct wireless_dev **wdev)
|
||||
{
|
||||
- struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
|
||||
u32 vid, subcmd;
|
||||
unsigned int i;
|
||||
int vcmd_idx = -1;
|
||||
@@ -11486,28 +11499,31 @@ static int nl80211_prepare_vendor_dump(s
|
||||
}
|
||||
|
||||
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
||||
- attrbuf, nl80211_fam.maxattr, nl80211_policy);
|
||||
+ nl80211_fam.attrbuf, nl80211_fam.maxattr,
|
||||
+ nl80211_policy);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
- if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
|
||||
- !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
|
||||
+ if (!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID] ||
|
||||
+ !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
- *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf);
|
||||
+ *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
|
||||
+ nl80211_fam.attrbuf);
|
||||
if (IS_ERR(*wdev))
|
||||
*wdev = NULL;
|
||||
|
||||
- *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
|
||||
+ *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
|
||||
+ nl80211_fam.attrbuf);
|
||||
if (IS_ERR(*rdev)) {
|
||||
err = PTR_ERR(*rdev);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
- vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
|
||||
- subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
|
||||
+ vid = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID]);
|
||||
+ subcmd = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
|
||||
|
||||
for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
|
||||
const struct wiphy_vendor_command *vcmd;
|
||||
@@ -11531,9 +11547,9 @@ static int nl80211_prepare_vendor_dump(s
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
- if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
|
||||
- data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
|
||||
- data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
|
||||
+ if (nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]) {
|
||||
+ data = nla_data(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]);
|
||||
+ data_len = nla_len(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]);
|
||||
}
|
||||
|
||||
/* 0 is the first index - add 1 to parse only once */
|
||||
@@ -12795,21 +12811,6 @@ static __genl_const struct genl_ops nl80
|
||||
},
|
||||
};
|
||||
|
||||
-static struct genl_family nl80211_fam __ro_after_init = {
|
||||
- .name = NL80211_GENL_NAME, /* have users key off the name instead */
|
||||
- .hdrsize = 0, /* no private header */
|
||||
- .version = 1, /* no particular meaning now */
|
||||
- .maxattr = NL80211_ATTR_MAX,
|
||||
- .netnsok = true,
|
||||
- .pre_doit = nl80211_pre_doit,
|
||||
- .post_doit = nl80211_post_doit,
|
||||
- .module = THIS_MODULE,
|
||||
- .ops = nl80211_ops,
|
||||
- .n_ops = ARRAY_SIZE(nl80211_ops),
|
||||
- .mcgrps = nl80211_mcgrps,
|
||||
- .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
|
||||
-};
|
||||
-
|
||||
/* notification functions */
|
||||
|
||||
void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
|
||||
@@ -14759,11 +14760,12 @@ void nl80211_send_ap_stopped(struct wire
|
||||
|
||||
/* initialisation/exit functions */
|
||||
|
||||
-int __init nl80211_init(void)
|
||||
+int nl80211_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
- err = genl_register_family(&nl80211_fam);
|
||||
+ err = genl_register_family_with_ops_groups(&nl80211_fam, nl80211_ops,
|
||||
+ nl80211_mcgrps);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
--- a/drivers/net/wireless/mac80211_hwsim.c
|
||||
+++ b/drivers/net/wireless/mac80211_hwsim.c
|
||||
@@ -587,8 +587,15 @@ struct hwsim_radiotap_ack_hdr {
|
||||
__le16 rt_chbitmask;
|
||||
} __packed;
|
||||
|
||||
-/* MAC80211_HWSIM netlink family */
|
||||
-static struct genl_family hwsim_genl_family;
|
||||
+/* MAC80211_HWSIM netlinf family */
|
||||
+static struct genl_family hwsim_genl_family = {
|
||||
+ .id = GENL_ID_GENERATE,
|
||||
+ .hdrsize = 0,
|
||||
+ .name = "MAC80211_HWSIM",
|
||||
+ .version = 1,
|
||||
+ .maxattr = HWSIM_ATTR_MAX,
|
||||
+ .netnsok = true,
|
||||
+};
|
||||
|
||||
enum hwsim_multicast_groups {
|
||||
HWSIM_MCGRP_CONFIG,
|
||||
@@ -3250,18 +3257,6 @@ static __genl_const struct genl_ops hwsi
|
||||
},
|
||||
};
|
||||
|
||||
-static struct genl_family hwsim_genl_family __ro_after_init = {
|
||||
- .name = "MAC80211_HWSIM",
|
||||
- .version = 1,
|
||||
- .maxattr = HWSIM_ATTR_MAX,
|
||||
- .netnsok = true,
|
||||
- .module = THIS_MODULE,
|
||||
- .ops = hwsim_ops,
|
||||
- .n_ops = ARRAY_SIZE(hwsim_ops),
|
||||
- .mcgrps = hwsim_mcgrps,
|
||||
- .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
|
||||
-};
|
||||
-
|
||||
static void destroy_radio(struct work_struct *work)
|
||||
{
|
||||
struct mac80211_hwsim_data *data =
|
||||
@@ -3309,13 +3304,15 @@ static struct notifier_block hwsim_netli
|
||||
.notifier_call = mac80211_hwsim_netlink_notify,
|
||||
};
|
||||
|
||||
-static int __init hwsim_init_netlink(void)
|
||||
+static int hwsim_init_netlink(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
|
||||
|
||||
- rc = genl_register_family(&hwsim_genl_family);
|
||||
+ rc = genl_register_family_with_ops_groups(&hwsim_genl_family,
|
||||
+ hwsim_ops,
|
||||
+ hwsim_mcgrps);
|
||||
if (rc)
|
||||
goto failure;
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -1133,7 +1133,7 @@ static u16 ieee80211_netdev_select_queue
|
||||
return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
|
||||
}
|
||||
|
||||
-static void
|
||||
+static struct rtnl_link_stats64 *
|
||||
ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
int i;
|
||||
@@ -1158,6 +1158,8 @@ ieee80211_get_stats64(struct net_device
|
||||
stats->rx_bytes += rx_bytes;
|
||||
stats->tx_bytes += tx_bytes;
|
||||
}
|
||||
+
|
||||
+ return stats;
|
||||
}
|
||||
|
||||
static const struct net_device_ops ieee80211_dataif_ops = {
|
338
package/kernel/mac80211/patches/009-revert-mtu-changes.patch
Normal file
338
package/kernel/mac80211/patches/009-revert-mtu-changes.patch
Normal file
|
@ -0,0 +1,338 @@
|
|||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -151,6 +151,15 @@ void ieee80211_recalc_idle(struct ieee80
|
||||
ieee80211_hw_config(local, change);
|
||||
}
|
||||
|
||||
+static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
|
||||
+{
|
||||
+ if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ dev->mtu = new_mtu;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
|
||||
bool check_dup)
|
||||
{
|
||||
@@ -1168,6 +1177,7 @@ static const struct net_device_ops ieee8
|
||||
.ndo_uninit = ieee80211_uninit,
|
||||
.ndo_start_xmit = ieee80211_subif_start_xmit,
|
||||
.ndo_set_rx_mode = ieee80211_set_multicast_list,
|
||||
+ .ndo_change_mtu = ieee80211_change_mtu,
|
||||
.ndo_set_mac_address = ieee80211_change_mac,
|
||||
.ndo_select_queue = ieee80211_netdev_select_queue,
|
||||
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||
@@ -1211,6 +1221,7 @@ static const struct net_device_ops ieee8
|
||||
.ndo_uninit = ieee80211_uninit,
|
||||
.ndo_start_xmit = ieee80211_monitor_start_xmit,
|
||||
.ndo_set_rx_mode = ieee80211_set_multicast_list,
|
||||
+ .ndo_change_mtu = ieee80211_change_mtu,
|
||||
.ndo_set_mac_address = ieee80211_change_mac,
|
||||
.ndo_select_queue = ieee80211_monitor_select_queue,
|
||||
.ndo_get_stats64 = ieee80211_get_stats64,
|
||||
@@ -1919,10 +1930,6 @@ int ieee80211_if_add(struct ieee80211_lo
|
||||
|
||||
netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
|
||||
|
||||
- /* MTU range: 256 - 2304 */
|
||||
- ndev->min_mtu = 256;
|
||||
- ndev->max_mtu = IEEE80211_MAX_DATA_LEN;
|
||||
-
|
||||
ret = register_netdevice(ndev);
|
||||
if (ret) {
|
||||
ieee80211_if_free(ndev);
|
||||
--- a/drivers/net/wireless/ath/wil6210/netdev.c
|
||||
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
|
||||
@@ -42,6 +42,21 @@ static int wil_stop(struct net_device *n
|
||||
return wil_down(wil);
|
||||
}
|
||||
|
||||
+static int wil_change_mtu(struct net_device *ndev, int new_mtu)
|
||||
+{
|
||||
+ struct wil6210_priv *wil = ndev_to_wil(ndev);
|
||||
+
|
||||
+ if (new_mtu < 68 || new_mtu > mtu_max) {
|
||||
+ wil_err(wil, "invalid MTU %d\n", new_mtu);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ wil_dbg_misc(wil, "change MTU %d -> %d\n", ndev->mtu, new_mtu);
|
||||
+ ndev->mtu = new_mtu;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
struct wil6210_priv *wil = ndev_to_wil(ndev);
|
||||
@@ -55,6 +70,7 @@ static const struct net_device_ops wil_n
|
||||
.ndo_start_xmit = wil_start_xmit,
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
+ .ndo_change_mtu = wil_change_mtu,
|
||||
.ndo_do_ioctl = wil_do_ioctl,
|
||||
};
|
||||
|
||||
@@ -111,7 +127,6 @@ static int wil6210_netdev_poll_tx(struct
|
||||
static void wil_dev_setup(struct net_device *dev)
|
||||
{
|
||||
ether_setup(dev);
|
||||
- dev->max_mtu = mtu_max;
|
||||
dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT;
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/atmel/atmel.c
|
||||
+++ b/drivers/net/wireless/atmel/atmel.c
|
||||
@@ -1295,6 +1295,14 @@ static struct iw_statistics *atmel_get_w
|
||||
return &priv->wstats;
|
||||
}
|
||||
|
||||
+static int atmel_change_mtu(struct net_device *dev, int new_mtu)
|
||||
+{
|
||||
+ if ((new_mtu < 68) || (new_mtu > 2312))
|
||||
+ return -EINVAL;
|
||||
+ dev->mtu = new_mtu;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int atmel_set_mac_address(struct net_device *dev, void *p)
|
||||
{
|
||||
struct sockaddr *addr = p;
|
||||
@@ -1498,6 +1506,7 @@ static const struct file_operations atme
|
||||
static const struct net_device_ops atmel_netdev_ops = {
|
||||
.ndo_open = atmel_open,
|
||||
.ndo_stop = atmel_close,
|
||||
+ .ndo_change_mtu = atmel_change_mtu,
|
||||
.ndo_set_mac_address = atmel_set_mac_address,
|
||||
.ndo_start_xmit = start_tx,
|
||||
.ndo_do_ioctl = atmel_ioctl,
|
||||
@@ -1591,10 +1600,6 @@ struct net_device *init_atmel_card(unsig
|
||||
dev->irq = irq;
|
||||
dev->base_addr = port;
|
||||
|
||||
- /* MTU range: 68 - 2312 */
|
||||
- dev->min_mtu = 68;
|
||||
- dev->max_mtu = MAX_WIRELESS_BODY - ETH_FCS_LEN;
|
||||
-
|
||||
SET_NETDEV_DEV(dev, sys_dev);
|
||||
|
||||
if ((rc = request_irq(dev->irq, service_interrupt, IRQF_SHARED, dev->name, dev))) {
|
||||
--- a/drivers/net/wireless/cisco/airo.c
|
||||
+++ b/drivers/net/wireless/cisco/airo.c
|
||||
@@ -2329,6 +2329,14 @@ static int airo_set_mac_address(struct n
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int airo_change_mtu(struct net_device *dev, int new_mtu)
|
||||
+{
|
||||
+ if ((new_mtu < 68) || (new_mtu > 2400))
|
||||
+ return -EINVAL;
|
||||
+ dev->mtu = new_mtu;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static LIST_HEAD(airo_devices);
|
||||
|
||||
static void add_airo_dev(struct airo_info *ai)
|
||||
@@ -2648,6 +2656,7 @@ static const struct net_device_ops airo1
|
||||
.ndo_get_stats = airo_get_stats,
|
||||
.ndo_set_mac_address = airo_set_mac_address,
|
||||
.ndo_do_ioctl = airo_ioctl,
|
||||
+ .ndo_change_mtu = airo_change_mtu,
|
||||
};
|
||||
|
||||
static void wifi_setup(struct net_device *dev)
|
||||
@@ -2659,8 +2668,6 @@ static void wifi_setup(struct net_device
|
||||
dev->type = ARPHRD_IEEE80211;
|
||||
dev->hard_header_len = ETH_HLEN;
|
||||
dev->mtu = AIRO_DEF_MTU;
|
||||
- dev->min_mtu = 68;
|
||||
- dev->max_mtu = MIC_MSGLEN_MAX;
|
||||
dev->addr_len = ETH_ALEN;
|
||||
dev->tx_queue_len = 100;
|
||||
|
||||
@@ -2747,6 +2754,7 @@ static const struct net_device_ops airo_
|
||||
.ndo_set_rx_mode = airo_set_multicast_list,
|
||||
.ndo_set_mac_address = airo_set_mac_address,
|
||||
.ndo_do_ioctl = airo_ioctl,
|
||||
+ .ndo_change_mtu = airo_change_mtu,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
|
||||
@@ -2758,6 +2766,7 @@ static const struct net_device_ops mpi_n
|
||||
.ndo_set_rx_mode = airo_set_multicast_list,
|
||||
.ndo_set_mac_address = airo_set_mac_address,
|
||||
.ndo_do_ioctl = airo_ioctl,
|
||||
+ .ndo_change_mtu = airo_change_mtu,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
|
||||
@@ -2813,7 +2822,6 @@ static struct net_device *_init_airo_car
|
||||
dev->irq = irq;
|
||||
dev->base_addr = port;
|
||||
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
||||
- dev->max_mtu = MIC_MSGLEN_MAX;
|
||||
|
||||
SET_NETDEV_DEV(dev, dmdev);
|
||||
|
||||
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
|
||||
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
|
||||
@@ -6039,6 +6039,7 @@ static const struct net_device_ops ipw21
|
||||
.ndo_open = ipw2100_open,
|
||||
.ndo_stop = ipw2100_close,
|
||||
.ndo_start_xmit = libipw_xmit,
|
||||
+ .ndo_change_mtu = libipw_change_mtu,
|
||||
.ndo_tx_timeout = ipw2100_tx_timeout,
|
||||
.ndo_set_mac_address = ipw2100_set_address,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
@@ -6074,8 +6075,6 @@ static struct net_device *ipw2100_alloc_
|
||||
dev->wireless_data = &priv->wireless_data;
|
||||
dev->watchdog_timeo = 3 * HZ;
|
||||
dev->irq = 0;
|
||||
- dev->min_mtu = 68;
|
||||
- dev->max_mtu = LIBIPW_DATA_LEN;
|
||||
|
||||
/* NOTE: We don't use the wireless_handlers hook
|
||||
* in dev as the system will start throwing WX requests
|
||||
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
|
||||
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
|
||||
@@ -11561,6 +11561,7 @@ static const struct net_device_ops ipw_p
|
||||
.ndo_open = ipw_prom_open,
|
||||
.ndo_stop = ipw_prom_stop,
|
||||
.ndo_start_xmit = ipw_prom_hard_start_xmit,
|
||||
+ .ndo_change_mtu = libipw_change_mtu,
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
@@ -11586,9 +11587,6 @@ static int ipw_prom_alloc(struct ipw_pri
|
||||
priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
|
||||
priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops;
|
||||
|
||||
- priv->prom_net_dev->min_mtu = 68;
|
||||
- priv->prom_net_dev->max_mtu = LIBIPW_DATA_LEN;
|
||||
-
|
||||
priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR;
|
||||
SET_NETDEV_DEV(priv->prom_net_dev, &priv->pci_dev->dev);
|
||||
|
||||
@@ -11621,6 +11619,7 @@ static const struct net_device_ops ipw_n
|
||||
.ndo_set_rx_mode = ipw_net_set_multicast_list,
|
||||
.ndo_set_mac_address = ipw_net_set_mac_address,
|
||||
.ndo_start_xmit = libipw_xmit,
|
||||
+ .ndo_change_mtu = libipw_change_mtu,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
|
||||
@@ -11730,9 +11729,6 @@ static int ipw_pci_probe(struct pci_dev
|
||||
net_dev->wireless_handlers = &ipw_wx_handler_def;
|
||||
net_dev->ethtool_ops = &ipw_ethtool_ops;
|
||||
|
||||
- net_dev->min_mtu = 68;
|
||||
- net_dev->max_mtu = LIBIPW_DATA_LEN;
|
||||
-
|
||||
err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group);
|
||||
if (err) {
|
||||
IPW_ERROR("failed to create sysfs device attributes\n");
|
||||
--- a/drivers/net/wireless/intel/ipw2x00/libipw.h
|
||||
+++ b/drivers/net/wireless/intel/ipw2x00/libipw.h
|
||||
@@ -948,6 +948,7 @@ static inline int libipw_is_cck_rate(u8
|
||||
/* libipw.c */
|
||||
void free_libipw(struct net_device *dev, int monitor);
|
||||
struct net_device *alloc_libipw(int sizeof_priv, int monitor);
|
||||
+int libipw_change_mtu(struct net_device *dev, int new_mtu);
|
||||
|
||||
void libipw_networks_age(struct libipw_device *ieee, unsigned long age_secs);
|
||||
|
||||
--- a/drivers/net/wireless/intel/ipw2x00/libipw_module.c
|
||||
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_module.c
|
||||
@@ -118,6 +118,15 @@ static void libipw_networks_initialize(s
|
||||
&ieee->network_free_list);
|
||||
}
|
||||
|
||||
+int libipw_change_mtu(struct net_device *dev, int new_mtu)
|
||||
+{
|
||||
+ if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
|
||||
+ return -EINVAL;
|
||||
+ dev->mtu = new_mtu;
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(libipw_change_mtu);
|
||||
+
|
||||
struct net_device *alloc_libipw(int sizeof_priv, int monitor)
|
||||
{
|
||||
struct libipw_device *ieee;
|
||||
--- a/drivers/net/wireless/intersil/hostap/hostap_main.c
|
||||
+++ b/drivers/net/wireless/intersil/hostap/hostap_main.c
|
||||
@@ -765,6 +765,16 @@ static void hostap_set_multicast_list(st
|
||||
}
|
||||
|
||||
|
||||
+static int prism2_change_mtu(struct net_device *dev, int new_mtu)
|
||||
+{
|
||||
+ if (new_mtu < PRISM2_MIN_MTU || new_mtu > PRISM2_MAX_MTU)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ dev->mtu = new_mtu;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static void prism2_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
@@ -803,6 +813,7 @@ static const struct net_device_ops hosta
|
||||
.ndo_do_ioctl = hostap_ioctl,
|
||||
.ndo_set_mac_address = prism2_set_mac_address,
|
||||
.ndo_set_rx_mode = hostap_set_multicast_list,
|
||||
+ .ndo_change_mtu = prism2_change_mtu,
|
||||
.ndo_tx_timeout = prism2_tx_timeout,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
@@ -815,6 +826,7 @@ static const struct net_device_ops hosta
|
||||
.ndo_do_ioctl = hostap_ioctl,
|
||||
.ndo_set_mac_address = prism2_set_mac_address,
|
||||
.ndo_set_rx_mode = hostap_set_multicast_list,
|
||||
+ .ndo_change_mtu = prism2_change_mtu,
|
||||
.ndo_tx_timeout = prism2_tx_timeout,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
@@ -827,6 +839,7 @@ static const struct net_device_ops hosta
|
||||
.ndo_do_ioctl = hostap_ioctl,
|
||||
.ndo_set_mac_address = prism2_set_mac_address,
|
||||
.ndo_set_rx_mode = hostap_set_multicast_list,
|
||||
+ .ndo_change_mtu = prism2_change_mtu,
|
||||
.ndo_tx_timeout = prism2_tx_timeout,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
@@ -838,8 +851,6 @@ void hostap_setup_dev(struct net_device
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
ether_setup(dev);
|
||||
- dev->min_mtu = PRISM2_MIN_MTU;
|
||||
- dev->max_mtu = PRISM2_MAX_MTU;
|
||||
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
||||
|
||||
/* kernel callbacks */
|
||||
--- a/drivers/net/wireless/intersil/orinoco/main.c
|
||||
+++ b/drivers/net/wireless/intersil/orinoco/main.c
|
||||
@@ -322,6 +322,9 @@ int orinoco_change_mtu(struct net_device
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
|
||||
+ if ((new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
/* MTU + encapsulation + header length */
|
||||
if ((new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) >
|
||||
(priv->nicbuf_size - ETH_HLEN))
|
||||
@@ -2285,9 +2288,6 @@ int orinoco_if_add(struct orinoco_privat
|
||||
dev->base_addr = base_addr;
|
||||
dev->irq = irq;
|
||||
|
||||
- dev->min_mtu = ORINOCO_MIN_MTU;
|
||||
- dev->max_mtu = ORINOCO_MAX_MTU;
|
||||
-
|
||||
SET_NETDEV_DEV(dev, priv->dev);
|
||||
ret = register_netdev(dev);
|
||||
if (ret)
|
|
@ -1,6 +1,6 @@
|
|||
--- a/.local-symbols
|
||||
+++ b/.local-symbols
|
||||
@@ -477,45 +477,6 @@ USB_IPHETH=
|
||||
@@ -482,45 +482,6 @@ USB_IPHETH=
|
||||
USB_SIERRA_NET=
|
||||
USB_VL600=
|
||||
USB_NET_CH9200=
|
||||
|
@ -88,7 +88,7 @@
|
|||
gpiodev = bus->chipco.dev ? : pcidev;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
|
||||
@@ -43,6 +43,6 @@ brcmsmac-y := \
|
||||
@@ -42,6 +42,6 @@ brcmsmac-y := \
|
||||
brcms_trace_events.o \
|
||||
debug.o
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
- aes_gcm.o \
|
||||
aes_cmac.o \
|
||||
- aes_gmac.o \
|
||||
fils_aead.o \
|
||||
cfg.o \
|
||||
ethtool.o \
|
||||
rx.o \
|
||||
--- a/net/mac80211/aes_ccm.c
|
||||
+++ b/net/mac80211/aes_ccm.c
|
||||
@@ -13,89 +13,132 @@
|
||||
@@ -13,103 +13,132 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/aead.h>
|
||||
|
@ -33,76 +33,101 @@
|
|||
#include "key.h"
|
||||
#include "aes_ccm.h"
|
||||
|
||||
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
-int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic,
|
||||
- size_t mic_len)
|
||||
+static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0,
|
||||
+ u8 *a, u8 *b)
|
||||
{
|
||||
- struct scatterlist sg[3];
|
||||
- struct aead_request *aead_req;
|
||||
- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
|
||||
- u8 *__aad;
|
||||
+ int i;
|
||||
+
|
||||
|
||||
- aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC);
|
||||
- if (!aead_req)
|
||||
- return -ENOMEM;
|
||||
+ crypto_cipher_encrypt_one(tfm, b, b_0);
|
||||
+
|
||||
|
||||
- __aad = (u8 *)aead_req + reqsize;
|
||||
- memcpy(__aad, aad, CCM_AAD_LEN);
|
||||
+ /* Extra Authenticate-only data (always two AES blocks) */
|
||||
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
+ aad[i] ^= b[i];
|
||||
+ crypto_cipher_encrypt_one(tfm, b, aad);
|
||||
+
|
||||
+ aad += AES_BLOCK_SIZE;
|
||||
+
|
||||
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
+ aad[i] ^= b[i];
|
||||
+ crypto_cipher_encrypt_one(tfm, a, aad);
|
||||
|
||||
- char aead_req_data[sizeof(struct aead_request) +
|
||||
- crypto_aead_reqsize(tfm)]
|
||||
- __aligned(__alignof__(struct aead_request));
|
||||
- struct aead_request *aead_req = (void *) aead_req_data;
|
||||
+ /* Mask out bits from auth-only-b_0 */
|
||||
+ b_0[0] &= 0x07;
|
||||
|
||||
- memset(aead_req, 0, sizeof(aead_req_data));
|
||||
+ /* S_0 is used to encrypt T (= MIC) */
|
||||
+ b_0[14] = 0;
|
||||
+ b_0[15] = 0;
|
||||
+ crypto_cipher_encrypt_one(tfm, s_0, b_0);
|
||||
+}
|
||||
|
||||
- sg_init_table(sg, 3);
|
||||
- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
|
||||
- sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
|
||||
- sg_set_buf(&sg[1], data, data_len);
|
||||
- sg_set_buf(&sg[2], mic, mic_len);
|
||||
+ aad += AES_BLOCK_SIZE;
|
||||
|
||||
- aead_request_set_tfm(aead_req, tfm);
|
||||
- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
|
||||
- aead_request_set_ad(aead_req, sg[0].length);
|
||||
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
+ aad[i] ^= b[i];
|
||||
+ crypto_cipher_encrypt_one(tfm, a, aad);
|
||||
|
||||
- crypto_aead_encrypt(aead_req);
|
||||
- kzfree(aead_req);
|
||||
+ /* Mask out bits from auth-only-b_0 */
|
||||
+ b_0[0] &= 0x07;
|
||||
|
||||
- return 0;
|
||||
+ /* S_0 is used to encrypt T (= MIC) */
|
||||
+ b_0[14] = 0;
|
||||
+ b_0[15] = 0;
|
||||
+ crypto_cipher_encrypt_one(tfm, s_0, b_0);
|
||||
}
|
||||
|
||||
-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic,
|
||||
- size_t mic_len)
|
||||
+
|
||||
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic,
|
||||
+ size_t mic_len)
|
||||
+{
|
||||
{
|
||||
- struct scatterlist sg[3];
|
||||
- struct aead_request *aead_req;
|
||||
- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
|
||||
- u8 *__aad;
|
||||
- int err;
|
||||
+ int i, j, last_len, num_blocks;
|
||||
+ u8 b[AES_BLOCK_SIZE];
|
||||
+ u8 s_0[AES_BLOCK_SIZE];
|
||||
+ u8 e[AES_BLOCK_SIZE];
|
||||
+ u8 *pos, *cpos;
|
||||
+
|
||||
|
||||
- if (data_len == 0)
|
||||
- return -EINVAL;
|
||||
+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
|
||||
+ last_len = data_len % AES_BLOCK_SIZE;
|
||||
+ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b);
|
||||
+
|
||||
|
||||
- aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC);
|
||||
- if (!aead_req)
|
||||
- return -ENOMEM;
|
||||
+ /* Process payload blocks */
|
||||
+ pos = data;
|
||||
+ cpos = data;
|
||||
+ for (j = 1; j <= num_blocks; j++) {
|
||||
+ int blen = (j == num_blocks && last_len) ?
|
||||
+ last_len : AES_BLOCK_SIZE;
|
||||
+
|
||||
|
||||
- __aad = (u8 *)aead_req + reqsize;
|
||||
- memcpy(__aad, aad, CCM_AAD_LEN);
|
||||
+ /* Authentication followed by encryption */
|
||||
+ for (i = 0; i < blen; i++)
|
||||
+ b[i] ^= pos[i];
|
||||
+ crypto_cipher_encrypt_one(tfm, b, b);
|
||||
+
|
||||
|
||||
- sg_init_table(sg, 3);
|
||||
- sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
|
||||
- sg_set_buf(&sg[1], data, data_len);
|
||||
- sg_set_buf(&sg[2], mic, mic_len);
|
||||
+ b_0[14] = (j >> 8) & 0xff;
|
||||
+ b_0[15] = j & 0xff;
|
||||
+ crypto_cipher_encrypt_one(tfm, e, b_0);
|
||||
|
@ -110,41 +135,26 @@
|
|||
+ *cpos++ = *pos++ ^ e[i];
|
||||
+ }
|
||||
|
||||
- crypto_aead_encrypt(aead_req);
|
||||
+ for (i = 0; i < mic_len; i++)
|
||||
+ mic[i] = b[i] ^ s_0[i];
|
||||
}
|
||||
|
||||
-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
u8 *data, size_t data_len, u8 *mic,
|
||||
size_t mic_len)
|
||||
{
|
||||
- struct scatterlist sg[3];
|
||||
- char aead_req_data[sizeof(struct aead_request) +
|
||||
- crypto_aead_reqsize(tfm)]
|
||||
- __aligned(__alignof__(struct aead_request));
|
||||
- struct aead_request *aead_req = (void *) aead_req_data;
|
||||
-
|
||||
- if (data_len == 0)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- memset(aead_req, 0, sizeof(aead_req_data));
|
||||
-
|
||||
- sg_init_table(sg, 3);
|
||||
- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
|
||||
- sg_set_buf(&sg[1], data, data_len);
|
||||
- sg_set_buf(&sg[2], mic, mic_len);
|
||||
-
|
||||
- aead_request_set_tfm(aead_req, tfm);
|
||||
- aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
|
||||
- aead_request_set_ad(aead_req, sg[0].length);
|
||||
+ for (i = 0; i < mic_len; i++)
|
||||
+ mic[i] = b[i] ^ s_0[i];
|
||||
+}
|
||||
|
||||
- err = crypto_aead_decrypt(aead_req);
|
||||
- kzfree(aead_req);
|
||||
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic,
|
||||
+ size_t mic_len)
|
||||
+{
|
||||
+ int i, j, last_len, num_blocks;
|
||||
+ u8 *pos, *cpos;
|
||||
+ u8 a[AES_BLOCK_SIZE];
|
||||
+ u8 b[AES_BLOCK_SIZE];
|
||||
+ u8 s_0[AES_BLOCK_SIZE];
|
||||
+
|
||||
|
||||
- return err;
|
||||
+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
|
||||
+ last_len = data_len % AES_BLOCK_SIZE;
|
||||
+ aes_ccm_prepare(tfm, b_0, aad, s_0, a, b);
|
||||
|
@ -171,8 +181,7 @@
|
|||
+ if ((mic[i] ^ s_0[i]) != a[i])
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
- return crypto_aead_decrypt(aead_req);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
|
@ -185,12 +194,12 @@
|
|||
{
|
||||
- struct crypto_aead *tfm;
|
||||
- int err;
|
||||
+ struct crypto_cipher *tfm;
|
||||
|
||||
-
|
||||
- tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
|
||||
- if (IS_ERR(tfm))
|
||||
- return tfm;
|
||||
-
|
||||
+ struct crypto_cipher *tfm;
|
||||
|
||||
- err = crypto_aead_setkey(tfm, key, key_len);
|
||||
- if (err)
|
||||
- goto free_aead;
|
||||
|
@ -215,73 +224,11 @@
|
|||
- crypto_free_aead(tfm);
|
||||
+ crypto_free_cipher(tfm);
|
||||
}
|
||||
--- a/net/mac80211/aes_ccm.h
|
||||
+++ b/net/mac80211/aes_ccm.h
|
||||
@@ -12,15 +12,15 @@
|
||||
|
||||
#include <linux/crypto.h>
|
||||
|
||||
-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
|
||||
- size_t key_len,
|
||||
- size_t mic_len);
|
||||
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
|
||||
+ size_t key_len,
|
||||
+ size_t mic_len);
|
||||
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
u8 *data, size_t data_len, u8 *mic,
|
||||
size_t mic_len);
|
||||
-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
u8 *data, size_t data_len, u8 *mic,
|
||||
size_t mic_len);
|
||||
-void ieee80211_aes_key_free(struct crypto_aead *tfm);
|
||||
+void ieee80211_aes_key_free(struct crypto_cipher *tfm);
|
||||
|
||||
#endif /* AES_CCM_H */
|
||||
--- a/net/mac80211/aes_gcm.h
|
||||
+++ b/net/mac80211/aes_gcm.h
|
||||
@@ -11,12 +11,28 @@
|
||||
|
||||
#include <linux/crypto.h>
|
||||
|
||||
-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic);
|
||||
-int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic);
|
||||
-struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
|
||||
- size_t key_len);
|
||||
-void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm);
|
||||
+static inline void
|
||||
+ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+static inline struct crypto_aead *
|
||||
+ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
|
||||
+{
|
||||
+}
|
||||
|
||||
#endif /* AES_GCM_H */
|
||||
--- a/net/mac80211/aes_gmac.h
|
||||
+++ b/net/mac80211/aes_gmac.h
|
||||
@@ -11,10 +11,22 @@
|
||||
|
||||
#include <linux/crypto.h>
|
||||
@@ -15,10 +15,22 @@
|
||||
#define GMAC_MIC_LEN 16
|
||||
#define GMAC_NONCE_LEN 12
|
||||
|
||||
-struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
|
||||
- size_t key_len);
|
||||
|
@ -320,7 +267,7 @@
|
|||
struct {
|
||||
--- a/net/mac80211/wpa.c
|
||||
+++ b/net/mac80211/wpa.c
|
||||
@@ -304,7 +304,8 @@ ieee80211_crypto_tkip_decrypt(struct iee
|
||||
@@ -305,7 +305,8 @@ ieee80211_crypto_tkip_decrypt(struct iee
|
||||
}
|
||||
|
||||
|
||||
|
@ -330,7 +277,7 @@
|
|||
{
|
||||
__le16 mask_fc;
|
||||
int a4_included, mgmt;
|
||||
@@ -334,14 +335,8 @@ static void ccmp_special_blocks(struct s
|
||||
@@ -335,14 +336,8 @@ static void ccmp_special_blocks(struct s
|
||||
else
|
||||
qos_tid = 0;
|
||||
|
||||
|
@ -347,7 +294,7 @@
|
|||
|
||||
/* Nonce: Nonce Flags | A2 | PN
|
||||
* Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
|
||||
@@ -349,6 +344,8 @@ static void ccmp_special_blocks(struct s
|
||||
@@ -350,6 +345,8 @@ static void ccmp_special_blocks(struct s
|
||||
b_0[1] = qos_tid | (mgmt << 4);
|
||||
memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
|
||||
memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
|
||||
|
@ -356,16 +303,31 @@
|
|||
|
||||
/* AAD (extra authenticate-only data) / masked 802.11 header
|
||||
* FC | A1 | A2 | A3 | SC | [A4] | [QC] */
|
||||
@@ -460,7 +457,7 @@ static int ccmp_encrypt_skb(struct ieee8
|
||||
@@ -406,7 +403,7 @@ static int ccmp_encrypt_skb(struct ieee8
|
||||
u8 *pos;
|
||||
u8 pn[6];
|
||||
u64 pn64;
|
||||
- u8 aad[CCM_AAD_LEN];
|
||||
+ u8 aad[2 * AES_BLOCK_SIZE];
|
||||
u8 b_0[AES_BLOCK_SIZE];
|
||||
|
||||
if (info->control.hw_key &&
|
||||
@@ -461,9 +458,11 @@ static int ccmp_encrypt_skb(struct ieee8
|
||||
return 0;
|
||||
|
||||
pos += IEEE80211_CCMP_HDR_LEN;
|
||||
- ccmp_special_blocks(skb, pn, b_0, aad);
|
||||
- return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
|
||||
- skb_put(skb, mic_len), mic_len);
|
||||
+ ccmp_special_blocks(skb, pn, b_0, aad, len);
|
||||
ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
|
||||
skb_put(skb, mic_len), mic_len);
|
||||
+ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
|
||||
+ skb_put(skb, mic_len), mic_len);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
@@ -537,7 +534,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
|
||||
|
||||
@@ -536,7 +535,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
|
||||
u8 aad[2 * AES_BLOCK_SIZE];
|
||||
u8 b_0[AES_BLOCK_SIZE];
|
||||
/* hardware didn't decrypt/verify MIC */
|
||||
|
@ -374,3 +336,113 @@
|
|||
|
||||
if (ieee80211_aes_ccm_decrypt(
|
||||
key->u.ccmp.tfm, b_0, aad,
|
||||
@@ -638,7 +637,7 @@ static int gcmp_encrypt_skb(struct ieee8
|
||||
u8 *pos;
|
||||
u8 pn[6];
|
||||
u64 pn64;
|
||||
- u8 aad[GCM_AAD_LEN];
|
||||
+ u8 aad[2 * AES_BLOCK_SIZE];
|
||||
u8 j_0[AES_BLOCK_SIZE];
|
||||
|
||||
if (info->control.hw_key &&
|
||||
@@ -695,8 +694,10 @@ static int gcmp_encrypt_skb(struct ieee8
|
||||
|
||||
pos += IEEE80211_GCMP_HDR_LEN;
|
||||
gcmp_special_blocks(skb, pn, j_0, aad);
|
||||
- return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
|
||||
- skb_put(skb, IEEE80211_GCMP_MIC_LEN));
|
||||
+ ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
|
||||
+ skb_put(skb, IEEE80211_GCMP_MIC_LEN));
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
ieee80211_tx_result
|
||||
@@ -1120,9 +1121,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct
|
||||
struct ieee80211_key *key = tx->key;
|
||||
struct ieee80211_mmie_16 *mmie;
|
||||
struct ieee80211_hdr *hdr;
|
||||
- u8 aad[GMAC_AAD_LEN];
|
||||
+ u8 aad[20];
|
||||
u64 pn64;
|
||||
- u8 nonce[GMAC_NONCE_LEN];
|
||||
+ u8 nonce[12];
|
||||
|
||||
if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
|
||||
return TX_DROP;
|
||||
@@ -1168,7 +1169,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_key *key = rx->key;
|
||||
struct ieee80211_mmie_16 *mmie;
|
||||
- u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN];
|
||||
+ u8 aad[20], mic[16], ipn[6], nonce[12];
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
if (!ieee80211_is_mgmt(hdr->frame_control))
|
||||
--- a/net/mac80211/aes_ccm.h
|
||||
+++ b/net/mac80211/aes_ccm.h
|
||||
@@ -12,17 +12,15 @@
|
||||
|
||||
#include <linux/crypto.h>
|
||||
|
||||
-#define CCM_AAD_LEN 32
|
||||
-
|
||||
-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
|
||||
- size_t key_len,
|
||||
- size_t mic_len);
|
||||
-int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic,
|
||||
- size_t mic_len);
|
||||
-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
|
||||
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
|
||||
+ size_t key_len,
|
||||
+ size_t mic_len);
|
||||
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic,
|
||||
+ size_t mic_len);
|
||||
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
|
||||
u8 *data, size_t data_len, u8 *mic,
|
||||
size_t mic_len);
|
||||
-void ieee80211_aes_key_free(struct crypto_aead *tfm);
|
||||
+void ieee80211_aes_key_free(struct crypto_cipher *tfm);
|
||||
|
||||
#endif /* AES_CCM_H */
|
||||
--- a/net/mac80211/aes_gcm.h
|
||||
+++ b/net/mac80211/aes_gcm.h
|
||||
@@ -11,14 +11,28 @@
|
||||
|
||||
#include <linux/crypto.h>
|
||||
|
||||
-#define GCM_AAD_LEN 32
|
||||
+static inline void
|
||||
+ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic)
|
||||
+{
|
||||
+}
|
||||
|
||||
-int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic);
|
||||
-int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
- u8 *data, size_t data_len, u8 *mic);
|
||||
-struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
|
||||
- size_t key_len);
|
||||
-void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm);
|
||||
+static inline int
|
||||
+ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
|
||||
+ u8 *data, size_t data_len, u8 *mic)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+static inline struct crypto_aead *
|
||||
+ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
|
||||
+{
|
||||
+}
|
||||
|
||||
#endif /* AES_GCM_H */
|
||||
|
|
|
@ -2,7 +2,7 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects
|
|||
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -1016,7 +1016,6 @@ static int ieee80211_stop_ap(struct wiph
|
||||
@@ -1014,7 +1014,6 @@ static int ieee80211_stop_ap(struct wiph
|
||||
sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
|
||||
|
||||
__sta_info_flush(sdata, true);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/mac80211_hwsim.c
|
||||
+++ b/drivers/net/wireless/mac80211_hwsim.c
|
||||
@@ -2662,7 +2662,7 @@ static int mac80211_hwsim_new_radio(stru
|
||||
@@ -2678,7 +2678,7 @@ static int mac80211_hwsim_new_radio(stru
|
||||
|
||||
tasklet_hrtimer_init(&data->beacon_timer,
|
||||
mac80211_hwsim_beacon,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
static int ieee80211_ifa6_changed(struct notifier_block *nb,
|
||||
unsigned long data, void *arg)
|
||||
{
|
||||
@@ -1101,14 +1101,14 @@ int ieee80211_register_hw(struct ieee802
|
||||
@@ -1111,14 +1111,14 @@ int ieee80211_register_hw(struct ieee802
|
||||
if (result)
|
||||
goto fail_flows;
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
|||
local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
|
||||
result = register_inet6addr_notifier(&local->ifa6_notifier);
|
||||
if (result)
|
||||
@@ -1117,13 +1117,13 @@ int ieee80211_register_hw(struct ieee802
|
||||
@@ -1127,13 +1127,13 @@ int ieee80211_register_hw(struct ieee802
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -52,7 +52,7 @@
|
|||
fail_ifa:
|
||||
#endif
|
||||
ieee80211_txq_teardown_flows(local);
|
||||
@@ -1153,10 +1153,10 @@ void ieee80211_unregister_hw(struct ieee
|
||||
@@ -1163,10 +1163,10 @@ void ieee80211_unregister_hw(struct ieee
|
||||
tasklet_kill(&local->tx_pending_tasklet);
|
||||
tasklet_kill(&local->tasklet);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -2175,7 +2175,7 @@ static int ieee80211_scan(struct wiphy *
|
||||
@@ -2165,7 +2165,7 @@ static int ieee80211_scan(struct wiphy *
|
||||
* the frames sent while scanning on other channel will be
|
||||
* lost)
|
||||
*/
|
||||
|
|
|
@ -1,953 +0,0 @@
|
|||
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
|
||||
Date: Fri, 2 Sep 2016 16:00:30 +0200
|
||||
Subject: [PATCH] ath9k: Switch to using mac80211 intermediate software
|
||||
queues.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This switches ath9k over to using the mac80211 intermediate software
|
||||
queueing mechanism for data packets. It removes the queueing inside the
|
||||
driver, except for the retry queue, and instead pulls from mac80211 when
|
||||
a packet is needed. The retry queue is used to store a packet that was
|
||||
pulled but can't be sent immediately.
|
||||
|
||||
The old code path in ath_tx_start that would queue packets has been
|
||||
removed completely, as has the qlen limit tunables (since there's no
|
||||
longer a queue in the driver to limit).
|
||||
|
||||
Based on Tim's original patch set, but reworked quite thoroughly.
|
||||
|
||||
Cc: Tim Shepard <shep@alum.mit.edu>
|
||||
Cc: Felix Fietkau <nbd@nbd.name>
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -91,7 +91,6 @@ int ath_descdma_setup(struct ath_softc *
|
||||
#define ATH_RXBUF 512
|
||||
#define ATH_TXBUF 512
|
||||
#define ATH_TXBUF_RESERVE 5
|
||||
-#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
|
||||
#define ATH_TXMAXTRY 13
|
||||
#define ATH_MAX_SW_RETRIES 30
|
||||
|
||||
@@ -145,7 +144,7 @@ int ath_descdma_setup(struct ath_softc *
|
||||
#define BAW_WITHIN(_start, _bawsz, _seqno) \
|
||||
((((_seqno) - (_start)) & 4095) < (_bawsz))
|
||||
|
||||
-#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
|
||||
+#define ATH_AN_2_TID(_an, _tidno) ath_node_to_tid(_an, _tidno)
|
||||
|
||||
#define IS_HT_RATE(rate) (rate & 0x80)
|
||||
#define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e))
|
||||
@@ -164,7 +163,6 @@ struct ath_txq {
|
||||
spinlock_t axq_lock;
|
||||
u32 axq_depth;
|
||||
u32 axq_ampdu_depth;
|
||||
- bool stopped;
|
||||
bool axq_tx_inprogress;
|
||||
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
|
||||
u8 txq_headidx;
|
||||
@@ -232,7 +230,6 @@ struct ath_buf {
|
||||
|
||||
struct ath_atx_tid {
|
||||
struct list_head list;
|
||||
- struct sk_buff_head buf_q;
|
||||
struct sk_buff_head retry_q;
|
||||
struct ath_node *an;
|
||||
struct ath_txq *txq;
|
||||
@@ -247,13 +244,13 @@ struct ath_atx_tid {
|
||||
s8 bar_index;
|
||||
bool active;
|
||||
bool clear_ps_filter;
|
||||
+ bool has_queued;
|
||||
};
|
||||
|
||||
struct ath_node {
|
||||
struct ath_softc *sc;
|
||||
struct ieee80211_sta *sta; /* station struct we're part of */
|
||||
struct ieee80211_vif *vif; /* interface with which we're associated */
|
||||
- struct ath_atx_tid tid[IEEE80211_NUM_TIDS];
|
||||
|
||||
u16 maxampdu;
|
||||
u8 mpdudensity;
|
||||
@@ -276,7 +273,6 @@ struct ath_tx_control {
|
||||
struct ath_node *an;
|
||||
struct ieee80211_sta *sta;
|
||||
u8 paprd;
|
||||
- bool force_channel;
|
||||
};
|
||||
|
||||
|
||||
@@ -293,7 +289,6 @@ struct ath_tx {
|
||||
struct ath_descdma txdma;
|
||||
struct ath_txq *txq_map[IEEE80211_NUM_ACS];
|
||||
struct ath_txq *uapsdq;
|
||||
- u32 txq_max_pending[IEEE80211_NUM_ACS];
|
||||
u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32];
|
||||
};
|
||||
|
||||
@@ -421,6 +416,22 @@ struct ath_offchannel {
|
||||
int duration;
|
||||
};
|
||||
|
||||
+static inline struct ath_atx_tid *
|
||||
+ath_node_to_tid(struct ath_node *an, u8 tidno)
|
||||
+{
|
||||
+ struct ieee80211_sta *sta = an->sta;
|
||||
+ struct ieee80211_vif *vif = an->vif;
|
||||
+ struct ieee80211_txq *txq;
|
||||
+
|
||||
+ BUG_ON(!vif);
|
||||
+ if (sta)
|
||||
+ txq = sta->txq[tidno % ARRAY_SIZE(sta->txq)];
|
||||
+ else
|
||||
+ txq = vif->txq;
|
||||
+
|
||||
+ return (struct ath_atx_tid *) txq->drv_priv;
|
||||
+}
|
||||
+
|
||||
#define case_rtn_string(val) case val: return #val
|
||||
|
||||
#define ath_for_each_chanctx(_sc, _ctx) \
|
||||
@@ -575,7 +586,6 @@ void ath_tx_edma_tasklet(struct ath_soft
|
||||
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
u16 tid, u16 *ssn);
|
||||
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||
|
||||
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
|
||||
void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
|
||||
@@ -585,6 +595,7 @@ void ath9k_release_buffered_frames(struc
|
||||
u16 tids, int nframes,
|
||||
enum ieee80211_frame_release_type reason,
|
||||
bool more_data);
|
||||
+void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue);
|
||||
|
||||
/********/
|
||||
/* VIFs */
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -1010,7 +1010,6 @@ static void ath_scan_send_probe(struct a
|
||||
goto error;
|
||||
|
||||
txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
|
||||
- txctl.force_channel = true;
|
||||
if (ath_tx_start(sc->hw, skb, &txctl))
|
||||
goto error;
|
||||
|
||||
@@ -1133,7 +1132,6 @@ ath_chanctx_send_vif_ps_frame(struct ath
|
||||
memset(&txctl, 0, sizeof(txctl));
|
||||
txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
|
||||
txctl.sta = sta;
|
||||
- txctl.force_channel = true;
|
||||
if (ath_tx_start(sc->hw, skb, &txctl)) {
|
||||
ieee80211_free_txskb(sc->hw, skb);
|
||||
return false;
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -600,7 +600,6 @@ static int read_file_xmit(struct seq_fil
|
||||
PR("MPDUs XRetried: ", xretries);
|
||||
PR("Aggregates: ", a_aggr);
|
||||
PR("AMPDUs Queued HW:", a_queued_hw);
|
||||
- PR("AMPDUs Queued SW:", a_queued_sw);
|
||||
PR("AMPDUs Completed:", a_completed);
|
||||
PR("AMPDUs Retried: ", a_retries);
|
||||
PR("AMPDUs XRetried: ", a_xretries);
|
||||
@@ -629,8 +628,7 @@ static void print_queue(struct ath_softc
|
||||
seq_printf(file, "%s: %d ", "qnum", txq->axq_qnum);
|
||||
seq_printf(file, "%s: %2d ", "qdepth", txq->axq_depth);
|
||||
seq_printf(file, "%s: %2d ", "ampdu-depth", txq->axq_ampdu_depth);
|
||||
- seq_printf(file, "%s: %3d ", "pending", txq->pending_frames);
|
||||
- seq_printf(file, "%s: %d\n", "stopped", txq->stopped);
|
||||
+ seq_printf(file, "%s: %3d\n", "pending", txq->pending_frames);
|
||||
|
||||
ath_txq_unlock(sc, txq);
|
||||
}
|
||||
@@ -1208,7 +1206,6 @@ static const char ath9k_gstrings_stats[]
|
||||
AMKSTR(d_tx_mpdu_xretries),
|
||||
AMKSTR(d_tx_aggregates),
|
||||
AMKSTR(d_tx_ampdus_queued_hw),
|
||||
- AMKSTR(d_tx_ampdus_queued_sw),
|
||||
AMKSTR(d_tx_ampdus_completed),
|
||||
AMKSTR(d_tx_ampdu_retries),
|
||||
AMKSTR(d_tx_ampdu_xretries),
|
||||
@@ -1288,7 +1285,6 @@ void ath9k_get_et_stats(struct ieee80211
|
||||
AWDATA(xretries);
|
||||
AWDATA(a_aggr);
|
||||
AWDATA(a_queued_hw);
|
||||
- AWDATA(a_queued_sw);
|
||||
AWDATA(a_completed);
|
||||
AWDATA(a_retries);
|
||||
AWDATA(a_xretries);
|
||||
@@ -1346,14 +1342,6 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
read_file_xmit);
|
||||
debugfs_create_devm_seqfile(sc->dev, "queues", sc->debug.debugfs_phy,
|
||||
read_file_queues);
|
||||
- debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
||||
- &sc->tx.txq_max_pending[IEEE80211_AC_BK]);
|
||||
- debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
||||
- &sc->tx.txq_max_pending[IEEE80211_AC_BE]);
|
||||
- debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
||||
- &sc->tx.txq_max_pending[IEEE80211_AC_VI]);
|
||||
- debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
||||
- &sc->tx.txq_max_pending[IEEE80211_AC_VO]);
|
||||
debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy,
|
||||
read_file_misc);
|
||||
debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy,
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.h
|
||||
@@ -147,7 +147,6 @@ struct ath_interrupt_stats {
|
||||
* @completed: Total MPDUs (non-aggr) completed
|
||||
* @a_aggr: Total no. of aggregates queued
|
||||
* @a_queued_hw: Total AMPDUs queued to hardware
|
||||
- * @a_queued_sw: Total AMPDUs queued to software queues
|
||||
* @a_completed: Total AMPDUs completed
|
||||
* @a_retries: No. of AMPDUs retried (SW)
|
||||
* @a_xretries: No. of AMPDUs dropped due to xretries
|
||||
@@ -174,7 +173,6 @@ struct ath_tx_stats {
|
||||
u32 xretries;
|
||||
u32 a_aggr;
|
||||
u32 a_queued_hw;
|
||||
- u32 a_queued_sw;
|
||||
u32 a_completed;
|
||||
u32 a_retries;
|
||||
u32 a_xretries;
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
|
||||
@@ -52,8 +52,8 @@ static ssize_t read_file_node_aggr(struc
|
||||
"TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
|
||||
"BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");
|
||||
|
||||
- for (tidno = 0, tid = &an->tid[tidno];
|
||||
- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
|
||||
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
|
||||
+ tid = ath_node_to_tid(an, tidno);
|
||||
txq = tid->txq;
|
||||
ath_txq_lock(sc, txq);
|
||||
if (tid->active) {
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -358,7 +358,6 @@ static int ath9k_init_queues(struct ath_
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
|
||||
sc->tx.txq_map[i]->mac80211_qnum = i;
|
||||
- sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -877,6 +876,7 @@ static void ath9k_set_hw_capab(struct at
|
||||
hw->max_rate_tries = 10;
|
||||
hw->sta_data_size = sizeof(struct ath_node);
|
||||
hw->vif_data_size = sizeof(struct ath_vif);
|
||||
+ hw->txq_data_size = sizeof(struct ath_atx_tid);
|
||||
hw->extra_tx_headroom = 4;
|
||||
|
||||
hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1902,9 +1902,11 @@ static int ath9k_ampdu_action(struct iee
|
||||
bool flush = false;
|
||||
int ret = 0;
|
||||
struct ieee80211_sta *sta = params->sta;
|
||||
+ struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||
enum ieee80211_ampdu_mlme_action action = params->action;
|
||||
u16 tid = params->tid;
|
||||
u16 *ssn = ¶ms->ssn;
|
||||
+ struct ath_atx_tid *atid;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
@@ -1937,9 +1939,9 @@ static int ath9k_ampdu_action(struct iee
|
||||
ath9k_ps_restore(sc);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
- ath9k_ps_wakeup(sc);
|
||||
- ath_tx_aggr_resume(sc, sta, tid);
|
||||
- ath9k_ps_restore(sc);
|
||||
+ atid = ath_node_to_tid(an, tid);
|
||||
+ atid->baw_size = IEEE80211_MIN_AMPDU_BUF <<
|
||||
+ sta->ht_cap.ampdu_factor;
|
||||
break;
|
||||
default:
|
||||
ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n");
|
||||
@@ -2701,4 +2703,5 @@ struct ieee80211_ops ath9k_ops = {
|
||||
.sw_scan_start = ath9k_sw_scan_start,
|
||||
.sw_scan_complete = ath9k_sw_scan_complete,
|
||||
.get_txpower = ath9k_get_txpower,
|
||||
+ .wake_tx_queue = ath9k_wake_tx_queue,
|
||||
};
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -67,6 +67,8 @@ static struct ath_buf *ath_tx_setup_buff
|
||||
struct ath_txq *txq,
|
||||
struct ath_atx_tid *tid,
|
||||
struct sk_buff *skb);
|
||||
+static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
+ struct ath_tx_control *txctl);
|
||||
|
||||
enum {
|
||||
MCS_HT20,
|
||||
@@ -137,6 +139,26 @@ static void ath_tx_queue_tid(struct ath_
|
||||
list_add_tail(&tid->list, list);
|
||||
}
|
||||
|
||||
+void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
|
||||
+{
|
||||
+ struct ath_softc *sc = hw->priv;
|
||||
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
+ struct ath_atx_tid *tid = (struct ath_atx_tid *) queue->drv_priv;
|
||||
+ struct ath_txq *txq = tid->txq;
|
||||
+
|
||||
+ ath_dbg(common, QUEUE, "Waking TX queue: %pM (%d)\n",
|
||||
+ queue->sta ? queue->sta->addr : queue->vif->addr,
|
||||
+ tid->tidno);
|
||||
+
|
||||
+ ath_txq_lock(sc, txq);
|
||||
+
|
||||
+ tid->has_queued = true;
|
||||
+ ath_tx_queue_tid(sc, txq, tid);
|
||||
+ ath_txq_schedule(sc, txq);
|
||||
+
|
||||
+ ath_txq_unlock(sc, txq);
|
||||
+}
|
||||
+
|
||||
static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
@@ -164,7 +186,6 @@ static void ath_set_rates(struct ieee802
|
||||
static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ath_frame_info *fi = get_frame_info(skb);
|
||||
int q = fi->txq;
|
||||
|
||||
@@ -175,14 +196,6 @@ static void ath_txq_skb_done(struct ath_
|
||||
if (WARN_ON(--txq->pending_frames < 0))
|
||||
txq->pending_frames = 0;
|
||||
|
||||
- if (txq->stopped &&
|
||||
- txq->pending_frames < sc->tx.txq_max_pending[q]) {
|
||||
- if (ath9k_is_chanctx_enabled())
|
||||
- ieee80211_wake_queue(sc->hw, info->hw_queue);
|
||||
- else
|
||||
- ieee80211_wake_queue(sc->hw, q);
|
||||
- txq->stopped = false;
|
||||
- }
|
||||
}
|
||||
|
||||
static struct ath_atx_tid *
|
||||
@@ -192,9 +205,48 @@ ath_get_skb_tid(struct ath_softc *sc, st
|
||||
return ATH_AN_2_TID(an, tidno);
|
||||
}
|
||||
|
||||
+static struct sk_buff *
|
||||
+ath_tid_pull(struct ath_atx_tid *tid)
|
||||
+{
|
||||
+ struct ieee80211_txq *txq = container_of((void*)tid, struct ieee80211_txq, drv_priv);
|
||||
+ struct ath_softc *sc = tid->an->sc;
|
||||
+ struct ieee80211_hw *hw = sc->hw;
|
||||
+ struct ath_tx_control txctl = {
|
||||
+ .txq = tid->txq,
|
||||
+ .sta = tid->an->sta,
|
||||
+ };
|
||||
+ struct sk_buff *skb;
|
||||
+ struct ath_frame_info *fi;
|
||||
+ int q;
|
||||
+
|
||||
+ if (!tid->has_queued)
|
||||
+ return NULL;
|
||||
+
|
||||
+ skb = ieee80211_tx_dequeue(hw, txq);
|
||||
+ if (!skb) {
|
||||
+ tid->has_queued = false;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (ath_tx_prepare(hw, skb, &txctl)) {
|
||||
+ ieee80211_free_txskb(hw, skb);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ q = skb_get_queue_mapping(skb);
|
||||
+ if (tid->txq == sc->tx.txq_map[q]) {
|
||||
+ fi = get_frame_info(skb);
|
||||
+ fi->txq = q;
|
||||
+ ++tid->txq->pending_frames;
|
||||
+ }
|
||||
+
|
||||
+ return skb;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static bool ath_tid_has_buffered(struct ath_atx_tid *tid)
|
||||
{
|
||||
- return !skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q);
|
||||
+ return !skb_queue_empty(&tid->retry_q) || tid->has_queued;
|
||||
}
|
||||
|
||||
static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
|
||||
@@ -203,46 +255,11 @@ static struct sk_buff *ath_tid_dequeue(s
|
||||
|
||||
skb = __skb_dequeue(&tid->retry_q);
|
||||
if (!skb)
|
||||
- skb = __skb_dequeue(&tid->buf_q);
|
||||
+ skb = ath_tid_pull(tid);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * ath_tx_tid_change_state:
|
||||
- * - clears a-mpdu flag of previous session
|
||||
- * - force sequence number allocation to fix next BlockAck Window
|
||||
- */
|
||||
-static void
|
||||
-ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
-{
|
||||
- struct ath_txq *txq = tid->txq;
|
||||
- struct ieee80211_tx_info *tx_info;
|
||||
- struct sk_buff *skb, *tskb;
|
||||
- struct ath_buf *bf;
|
||||
- struct ath_frame_info *fi;
|
||||
-
|
||||
- skb_queue_walk_safe(&tid->buf_q, skb, tskb) {
|
||||
- fi = get_frame_info(skb);
|
||||
- bf = fi->bf;
|
||||
-
|
||||
- tx_info = IEEE80211_SKB_CB(skb);
|
||||
- tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
-
|
||||
- if (bf)
|
||||
- continue;
|
||||
-
|
||||
- bf = ath_tx_setup_buffer(sc, txq, tid, skb);
|
||||
- if (!bf) {
|
||||
- __skb_unlink(skb, &tid->buf_q);
|
||||
- ath_txq_skb_done(sc, txq, skb);
|
||||
- ieee80211_free_txskb(sc->hw, skb);
|
||||
- continue;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
-}
|
||||
-
|
||||
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_txq *txq = tid->txq;
|
||||
@@ -883,20 +900,16 @@ static int ath_compute_num_delims(struct
|
||||
|
||||
static struct ath_buf *
|
||||
ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
|
||||
- struct ath_atx_tid *tid, struct sk_buff_head **q)
|
||||
+ struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ath_frame_info *fi;
|
||||
- struct sk_buff *skb;
|
||||
+ struct sk_buff *skb, *first_skb = NULL;
|
||||
struct ath_buf *bf;
|
||||
u16 seqno;
|
||||
|
||||
while (1) {
|
||||
- *q = &tid->retry_q;
|
||||
- if (skb_queue_empty(*q))
|
||||
- *q = &tid->buf_q;
|
||||
-
|
||||
- skb = skb_peek(*q);
|
||||
+ skb = ath_tid_dequeue(tid);
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
@@ -908,7 +921,6 @@ ath_tx_get_tid_subframe(struct ath_softc
|
||||
bf->bf_state.stale = false;
|
||||
|
||||
if (!bf) {
|
||||
- __skb_unlink(skb, *q);
|
||||
ath_txq_skb_done(sc, txq, skb);
|
||||
ieee80211_free_txskb(sc->hw, skb);
|
||||
continue;
|
||||
@@ -937,8 +949,20 @@ ath_tx_get_tid_subframe(struct ath_softc
|
||||
seqno = bf->bf_state.seqno;
|
||||
|
||||
/* do not step over block-ack window */
|
||||
- if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno))
|
||||
+ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
|
||||
+ __skb_queue_tail(&tid->retry_q, skb);
|
||||
+
|
||||
+ /* If there are other skbs in the retry q, they are
|
||||
+ * probably within the BAW, so loop immediately to get
|
||||
+ * one of them. Otherwise the queue can get stuck. */
|
||||
+ if (!skb_queue_is_first(&tid->retry_q, skb) &&
|
||||
+ !WARN_ON(skb == first_skb)) {
|
||||
+ if(!first_skb) /* infinite loop prevention */
|
||||
+ first_skb = skb;
|
||||
+ continue;
|
||||
+ }
|
||||
break;
|
||||
+ }
|
||||
|
||||
if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
|
||||
struct ath_tx_status ts = {};
|
||||
@@ -946,7 +970,6 @@ ath_tx_get_tid_subframe(struct ath_softc
|
||||
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
list_add(&bf->list, &bf_head);
|
||||
- __skb_unlink(skb, *q);
|
||||
ath_tx_update_baw(sc, tid, seqno);
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, NULL, &ts, 0);
|
||||
continue;
|
||||
@@ -958,11 +981,10 @@ ath_tx_get_tid_subframe(struct ath_softc
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static bool
|
||||
+static int
|
||||
ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_atx_tid *tid, struct list_head *bf_q,
|
||||
- struct ath_buf *bf_first, struct sk_buff_head *tid_q,
|
||||
- int *aggr_len)
|
||||
+ struct ath_buf *bf_first)
|
||||
{
|
||||
#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
|
||||
struct ath_buf *bf = bf_first, *bf_prev = NULL;
|
||||
@@ -972,12 +994,13 @@ ath_tx_form_aggr(struct ath_softc *sc, s
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ath_frame_info *fi;
|
||||
struct sk_buff *skb;
|
||||
- bool closed = false;
|
||||
+
|
||||
|
||||
bf = bf_first;
|
||||
aggr_limit = ath_lookup_rate(sc, bf, tid);
|
||||
|
||||
- do {
|
||||
+ while (bf)
|
||||
+ {
|
||||
skb = bf->bf_mpdu;
|
||||
fi = get_frame_info(skb);
|
||||
|
||||
@@ -986,12 +1009,12 @@ ath_tx_form_aggr(struct ath_softc *sc, s
|
||||
if (nframes) {
|
||||
if (aggr_limit < al + bpad + al_delta ||
|
||||
ath_lookup_legacy(bf) || nframes >= h_baw)
|
||||
- break;
|
||||
+ goto stop;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||
if ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
|
||||
!(tx_info->flags & IEEE80211_TX_CTL_AMPDU))
|
||||
- break;
|
||||
+ goto stop;
|
||||
}
|
||||
|
||||
/* add padding for previous frame to aggregation length */
|
||||
@@ -1013,20 +1036,18 @@ ath_tx_form_aggr(struct ath_softc *sc, s
|
||||
ath_tx_addto_baw(sc, tid, bf);
|
||||
bf->bf_state.ndelim = ndelim;
|
||||
|
||||
- __skb_unlink(skb, tid_q);
|
||||
list_add_tail(&bf->list, bf_q);
|
||||
if (bf_prev)
|
||||
bf_prev->bf_next = bf;
|
||||
|
||||
bf_prev = bf;
|
||||
|
||||
- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
|
||||
- if (!bf) {
|
||||
- closed = true;
|
||||
- break;
|
||||
- }
|
||||
- } while (ath_tid_has_buffered(tid));
|
||||
-
|
||||
+ bf = ath_tx_get_tid_subframe(sc, txq, tid);
|
||||
+ }
|
||||
+ goto finish;
|
||||
+stop:
|
||||
+ __skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
|
||||
+finish:
|
||||
bf = bf_first;
|
||||
bf->bf_lastbf = bf_prev;
|
||||
|
||||
@@ -1037,9 +1058,7 @@ ath_tx_form_aggr(struct ath_softc *sc, s
|
||||
TX_STAT_INC(txq->axq_qnum, a_aggr);
|
||||
}
|
||||
|
||||
- *aggr_len = al;
|
||||
-
|
||||
- return closed;
|
||||
+ return al;
|
||||
#undef PADBYTES
|
||||
}
|
||||
|
||||
@@ -1416,18 +1435,15 @@ static void ath_tx_fill_desc(struct ath_
|
||||
static void
|
||||
ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_atx_tid *tid, struct list_head *bf_q,
|
||||
- struct ath_buf *bf_first, struct sk_buff_head *tid_q)
|
||||
+ struct ath_buf *bf_first)
|
||||
{
|
||||
struct ath_buf *bf = bf_first, *bf_prev = NULL;
|
||||
- struct sk_buff *skb;
|
||||
int nframes = 0;
|
||||
|
||||
do {
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
- skb = bf->bf_mpdu;
|
||||
|
||||
nframes++;
|
||||
- __skb_unlink(skb, tid_q);
|
||||
list_add_tail(&bf->list, bf_q);
|
||||
if (bf_prev)
|
||||
bf_prev->bf_next = bf;
|
||||
@@ -1436,13 +1452,15 @@ ath_tx_form_burst(struct ath_softc *sc,
|
||||
if (nframes >= 2)
|
||||
break;
|
||||
|
||||
- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
|
||||
+ bf = ath_tx_get_tid_subframe(sc, txq, tid);
|
||||
if (!bf)
|
||||
break;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||
+ __skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
|
||||
break;
|
||||
+ }
|
||||
|
||||
ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
} while (1);
|
||||
@@ -1453,34 +1471,33 @@ static bool ath_tx_sched_aggr(struct ath
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
- struct sk_buff_head *tid_q;
|
||||
struct list_head bf_q;
|
||||
int aggr_len = 0;
|
||||
- bool aggr, last = true;
|
||||
+ bool aggr;
|
||||
|
||||
if (!ath_tid_has_buffered(tid))
|
||||
return false;
|
||||
|
||||
INIT_LIST_HEAD(&bf_q);
|
||||
|
||||
- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
|
||||
+ bf = ath_tx_get_tid_subframe(sc, txq, tid);
|
||||
if (!bf)
|
||||
return false;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||
aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
|
||||
if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
|
||||
- (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
|
||||
+ (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
|
||||
+ __skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
|
||||
*stop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
if (aggr)
|
||||
- last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
|
||||
- tid_q, &aggr_len);
|
||||
+ aggr_len = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf);
|
||||
else
|
||||
- ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q);
|
||||
+ ath_tx_form_burst(sc, txq, tid, &bf_q, bf);
|
||||
|
||||
if (list_empty(&bf_q))
|
||||
return false;
|
||||
@@ -1523,9 +1540,6 @@ int ath_tx_aggr_start(struct ath_softc *
|
||||
an->mpdudensity = density;
|
||||
}
|
||||
|
||||
- /* force sequence number allocation for pending frames */
|
||||
- ath_tx_tid_change_state(sc, txtid);
|
||||
-
|
||||
txtid->active = true;
|
||||
*ssn = txtid->seq_start = txtid->seq_next;
|
||||
txtid->bar_index = -1;
|
||||
@@ -1550,7 +1564,6 @@ void ath_tx_aggr_stop(struct ath_softc *
|
||||
ath_txq_lock(sc, txq);
|
||||
txtid->active = false;
|
||||
ath_tx_flush_tid(sc, txtid);
|
||||
- ath_tx_tid_change_state(sc, txtid);
|
||||
ath_txq_unlock_complete(sc, txq);
|
||||
}
|
||||
|
||||
@@ -1560,14 +1573,12 @@ void ath_tx_aggr_sleep(struct ieee80211_
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_atx_tid *tid;
|
||||
struct ath_txq *txq;
|
||||
- bool buffered;
|
||||
int tidno;
|
||||
|
||||
ath_dbg(common, XMIT, "%s called\n", __func__);
|
||||
|
||||
- for (tidno = 0, tid = &an->tid[tidno];
|
||||
- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
|
||||
-
|
||||
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
|
||||
+ tid = ath_node_to_tid(an, tidno);
|
||||
txq = tid->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
@@ -1577,13 +1588,12 @@ void ath_tx_aggr_sleep(struct ieee80211_
|
||||
continue;
|
||||
}
|
||||
|
||||
- buffered = ath_tid_has_buffered(tid);
|
||||
+ if (!skb_queue_empty(&tid->retry_q))
|
||||
+ ieee80211_sta_set_buffered(sta, tid->tidno, true);
|
||||
|
||||
list_del_init(&tid->list);
|
||||
|
||||
ath_txq_unlock(sc, txq);
|
||||
-
|
||||
- ieee80211_sta_set_buffered(sta, tidno, buffered);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1596,49 +1606,20 @@ void ath_tx_aggr_wakeup(struct ath_softc
|
||||
|
||||
ath_dbg(common, XMIT, "%s called\n", __func__);
|
||||
|
||||
- for (tidno = 0, tid = &an->tid[tidno];
|
||||
- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
|
||||
-
|
||||
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
|
||||
+ tid = ath_node_to_tid(an, tidno);
|
||||
txq = tid->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
tid->clear_ps_filter = true;
|
||||
-
|
||||
if (ath_tid_has_buffered(tid)) {
|
||||
ath_tx_queue_tid(sc, txq, tid);
|
||||
ath_txq_schedule(sc, txq);
|
||||
}
|
||||
-
|
||||
ath_txq_unlock_complete(sc, txq);
|
||||
}
|
||||
}
|
||||
|
||||
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
- u16 tidno)
|
||||
-{
|
||||
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
- struct ath_atx_tid *tid;
|
||||
- struct ath_node *an;
|
||||
- struct ath_txq *txq;
|
||||
-
|
||||
- ath_dbg(common, XMIT, "%s called\n", __func__);
|
||||
-
|
||||
- an = (struct ath_node *)sta->drv_priv;
|
||||
- tid = ATH_AN_2_TID(an, tidno);
|
||||
- txq = tid->txq;
|
||||
-
|
||||
- ath_txq_lock(sc, txq);
|
||||
-
|
||||
- tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
|
||||
-
|
||||
- if (ath_tid_has_buffered(tid)) {
|
||||
- ath_tx_queue_tid(sc, txq, tid);
|
||||
- ath_txq_schedule(sc, txq);
|
||||
- }
|
||||
-
|
||||
- ath_txq_unlock_complete(sc, txq);
|
||||
-}
|
||||
-
|
||||
void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
u16 tids, int nframes,
|
||||
@@ -1651,7 +1632,6 @@ void ath9k_release_buffered_frames(struc
|
||||
struct ieee80211_tx_info *info;
|
||||
struct list_head bf_q;
|
||||
struct ath_buf *bf_tail = NULL, *bf;
|
||||
- struct sk_buff_head *tid_q;
|
||||
int sent = 0;
|
||||
int i;
|
||||
|
||||
@@ -1666,11 +1646,10 @@ void ath9k_release_buffered_frames(struc
|
||||
|
||||
ath_txq_lock(sc, tid->txq);
|
||||
while (nframes > 0) {
|
||||
- bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q);
|
||||
+ bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid);
|
||||
if (!bf)
|
||||
break;
|
||||
|
||||
- __skb_unlink(bf->bf_mpdu, tid_q);
|
||||
list_add_tail(&bf->list, &bf_q);
|
||||
ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
if (bf_isampdu(bf)) {
|
||||
@@ -1685,7 +1664,7 @@ void ath9k_release_buffered_frames(struc
|
||||
sent++;
|
||||
TX_STAT_INC(txq->axq_qnum, a_queued_hw);
|
||||
|
||||
- if (an->sta && !ath_tid_has_buffered(tid))
|
||||
+ if (an->sta && skb_queue_empty(&tid->retry_q))
|
||||
ieee80211_sta_set_buffered(an->sta, i, false);
|
||||
}
|
||||
ath_txq_unlock_complete(sc, tid->txq);
|
||||
@@ -1914,13 +1893,7 @@ bool ath_drain_all_txq(struct ath_softc
|
||||
if (!ATH_TXQ_SETUP(sc, i))
|
||||
continue;
|
||||
|
||||
- /*
|
||||
- * The caller will resume queues with ieee80211_wake_queues.
|
||||
- * Mark the queue as not stopped to prevent ath_tx_complete
|
||||
- * from waking the queue too early.
|
||||
- */
|
||||
txq = &sc->tx.txq[i];
|
||||
- txq->stopped = false;
|
||||
ath_draintxq(sc, txq);
|
||||
}
|
||||
|
||||
@@ -2319,16 +2292,14 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_txq *txq = txctl->txq;
|
||||
struct ath_atx_tid *tid = NULL;
|
||||
+ struct ath_node *an = NULL;
|
||||
struct ath_buf *bf;
|
||||
- bool queue, skip_uapsd = false, ps_resp;
|
||||
+ bool ps_resp;
|
||||
int q, ret;
|
||||
|
||||
if (vif)
|
||||
avp = (void *)vif->drv_priv;
|
||||
|
||||
- if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
|
||||
- txctl->force_channel = true;
|
||||
-
|
||||
ps_resp = !!(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE);
|
||||
|
||||
ret = ath_tx_prepare(hw, skb, txctl);
|
||||
@@ -2343,63 +2314,18 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
|
||||
q = skb_get_queue_mapping(skb);
|
||||
|
||||
- ath_txq_lock(sc, txq);
|
||||
- if (txq == sc->tx.txq_map[q]) {
|
||||
- fi->txq = q;
|
||||
- if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
|
||||
- !txq->stopped) {
|
||||
- if (ath9k_is_chanctx_enabled())
|
||||
- ieee80211_stop_queue(sc->hw, info->hw_queue);
|
||||
- else
|
||||
- ieee80211_stop_queue(sc->hw, q);
|
||||
- txq->stopped = true;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- queue = ieee80211_is_data_present(hdr->frame_control);
|
||||
-
|
||||
- /* If chanctx, queue all null frames while NOA could be there */
|
||||
- if (ath9k_is_chanctx_enabled() &&
|
||||
- ieee80211_is_nullfunc(hdr->frame_control) &&
|
||||
- !txctl->force_channel)
|
||||
- queue = true;
|
||||
-
|
||||
- /* Force queueing of all frames that belong to a virtual interface on
|
||||
- * a different channel context, to ensure that they are sent on the
|
||||
- * correct channel.
|
||||
- */
|
||||
- if (((avp && avp->chanctx != sc->cur_chan) ||
|
||||
- sc->cur_chan->stopped) && !txctl->force_channel) {
|
||||
- if (!txctl->an)
|
||||
- txctl->an = &avp->mcast_node;
|
||||
- queue = true;
|
||||
- skip_uapsd = true;
|
||||
- }
|
||||
-
|
||||
- if (txctl->an && queue)
|
||||
- tid = ath_get_skb_tid(sc, txctl->an, skb);
|
||||
-
|
||||
- if (!skip_uapsd && ps_resp) {
|
||||
- ath_txq_unlock(sc, txq);
|
||||
+ if (ps_resp)
|
||||
txq = sc->tx.uapsdq;
|
||||
- ath_txq_lock(sc, txq);
|
||||
- } else if (txctl->an && queue) {
|
||||
- WARN_ON(tid->txq != txctl->txq);
|
||||
|
||||
- if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
|
||||
- tid->clear_ps_filter = true;
|
||||
-
|
||||
- /*
|
||||
- * Add this frame to software queue for scheduling later
|
||||
- * for aggregation.
|
||||
- */
|
||||
- TX_STAT_INC(txq->axq_qnum, a_queued_sw);
|
||||
- __skb_queue_tail(&tid->buf_q, skb);
|
||||
- if (!txctl->an->sleeping)
|
||||
- ath_tx_queue_tid(sc, txq, tid);
|
||||
+ if (txctl->sta) {
|
||||
+ an = (struct ath_node *) sta->drv_priv;
|
||||
+ tid = ath_get_skb_tid(sc, an, skb);
|
||||
+ }
|
||||
|
||||
- ath_txq_schedule(sc, txq);
|
||||
- goto out;
|
||||
+ ath_txq_lock(sc, txq);
|
||||
+ if (txq == sc->tx.txq_map[q]) {
|
||||
+ fi->txq = q;
|
||||
+ ++txq->pending_frames;
|
||||
}
|
||||
|
||||
bf = ath_tx_setup_buffer(sc, txq, tid, skb);
|
||||
@@ -2892,9 +2818,8 @@ void ath_tx_node_init(struct ath_softc *
|
||||
struct ath_atx_tid *tid;
|
||||
int tidno, acno;
|
||||
|
||||
- for (tidno = 0, tid = &an->tid[tidno];
|
||||
- tidno < IEEE80211_NUM_TIDS;
|
||||
- tidno++, tid++) {
|
||||
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
|
||||
+ tid = ath_node_to_tid(an, tidno);
|
||||
tid->an = an;
|
||||
tid->tidno = tidno;
|
||||
tid->seq_start = tid->seq_next = 0;
|
||||
@@ -2902,11 +2827,14 @@ void ath_tx_node_init(struct ath_softc *
|
||||
tid->baw_head = tid->baw_tail = 0;
|
||||
tid->active = false;
|
||||
tid->clear_ps_filter = true;
|
||||
- __skb_queue_head_init(&tid->buf_q);
|
||||
+ tid->has_queued = false;
|
||||
__skb_queue_head_init(&tid->retry_q);
|
||||
INIT_LIST_HEAD(&tid->list);
|
||||
acno = TID_TO_WME_AC(tidno);
|
||||
tid->txq = sc->tx.txq_map[acno];
|
||||
+
|
||||
+ if (!an->sta)
|
||||
+ break; /* just one multicast ath_atx_tid */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2916,9 +2844,8 @@ void ath_tx_node_cleanup(struct ath_soft
|
||||
struct ath_txq *txq;
|
||||
int tidno;
|
||||
|
||||
- for (tidno = 0, tid = &an->tid[tidno];
|
||||
- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
|
||||
-
|
||||
+ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
|
||||
+ tid = ath_node_to_tid(an, tidno);
|
||||
txq = tid->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
@@ -2930,6 +2857,9 @@ void ath_tx_node_cleanup(struct ath_soft
|
||||
tid->active = false;
|
||||
|
||||
ath_txq_unlock(sc, txq);
|
||||
+
|
||||
+ if (!an->sta)
|
||||
+ break; /* just one multicast ath_atx_tid */
|
||||
}
|
||||
}
|
||||
|
|
@ -29,21 +29,6 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
- npend = ath9k_hw_numtxpending(ah, i);
|
||||
- if (npend)
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (ah->external_reset &&
|
||||
- (npend || type == ATH9K_RESET_COLD)) {
|
||||
- int reset_err = 0;
|
||||
-
|
||||
- ath_dbg(ath9k_hw_common(ah), RESET,
|
||||
- "reset MAC via external reset\n");
|
||||
-
|
||||
- reset_err = ah->external_reset();
|
||||
- if (reset_err) {
|
||||
- ath_err(ath9k_hw_common(ah),
|
||||
- "External reset failed, err=%d\n",
|
||||
- reset_err);
|
||||
- return false;
|
||||
+ if (type == ATH9K_RESET_COLD)
|
||||
+ return true;
|
||||
+
|
||||
|
@ -59,35 +44,47 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
+ for (i = 0; i < AR_NUM_QCU; i++) {
|
||||
+ if (ath9k_hw_numtxpending(ah, i))
|
||||
+ return true;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
- if (ah->external_reset &&
|
||||
- (npend || type == ATH9K_RESET_COLD)) {
|
||||
- int reset_err = 0;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
|
||||
- ath_dbg(ath9k_hw_common(ah), RESET,
|
||||
- "reset MAC via external reset\n");
|
||||
+static bool ath9k_hw_external_reset(struct ath_hw *ah, int type)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
|
||||
- reset_err = ah->external_reset();
|
||||
- if (reset_err) {
|
||||
- ath_err(ath9k_hw_common(ah),
|
||||
- "External reset failed, err=%d\n",
|
||||
- reset_err);
|
||||
- return false;
|
||||
- }
|
||||
+ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type))
|
||||
+ return true;
|
||||
+
|
||||
+ ath_dbg(ath9k_hw_common(ah), RESET,
|
||||
+ "reset MAC via external reset\n");
|
||||
|
||||
- REG_WRITE(ah, AR_RTC_RESET, 1);
|
||||
+ ath_dbg(ath9k_hw_common(ah), RESET,
|
||||
+ "reset MAC via external reset\n");
|
||||
+
|
||||
+ err = ah->external_reset();
|
||||
+ if (err) {
|
||||
+ ath_err(ath9k_hw_common(ah),
|
||||
+ "External reset failed, err=%d\n", err);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
+ if (AR_SREV_9550(ah)) {
|
||||
+ REG_WRITE(ah, AR_RTC_RESET, 0);
|
||||
+ udelay(10);
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
+ REG_WRITE(ah, AR_RTC_RESET, 1);
|
||||
+ udelay(10);
|
||||
+
|
|
@ -1,6 +1,7 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Tue, 27 Dec 2016 23:16:23 +0100
|
||||
Subject: [PATCH] ath9k: don't run periodic and nf calibation at the same time
|
||||
Subject: [PATCH] ath9k: don't run periodic and nf calibation at the same
|
||||
time
|
||||
|
||||
The checks already prevents periodic cal from being started while noise
|
||||
floor calibration runs. It is missing checks for the other way around.
|
|
@ -27,7 +27,7 @@ Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
|
|||
- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
|
||||
+ u32 reg = AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT;
|
||||
+
|
||||
+ if (!config_enabled(CPTCFG_ATH9K_TX99))
|
||||
+ if (!IS_ENABLED(CPTCFG_ATH9K_TX99))
|
||||
+ reg |= AR_DIAG_FORCE_RX_CLEAR;
|
||||
+ REG_SET_BIT(ah, AR_DIAG_SW, reg);
|
||||
|
|
@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|||
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -177,10 +177,25 @@ static void ath_send_bar(struct ath_atx_
|
||||
@@ -188,10 +188,25 @@ static void ath_send_bar(struct ath_atx_
|
||||
}
|
||||
|
||||
static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
|
@ -40,7 +40,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|||
}
|
||||
|
||||
static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
|
||||
@@ -1462,7 +1477,7 @@ ath_tx_form_burst(struct ath_softc *sc,
|
||||
@@ -1522,7 +1537,7 @@ ath_tx_form_burst(struct ath_softc *sc,
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|||
} while (1);
|
||||
}
|
||||
|
||||
@@ -1493,7 +1508,7 @@ static bool ath_tx_sched_aggr(struct ath
|
||||
@@ -1552,7 +1567,7 @@ static bool ath_tx_sched_aggr(struct ath
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|||
if (aggr)
|
||||
aggr_len = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf);
|
||||
else
|
||||
@@ -1651,7 +1666,7 @@ void ath9k_release_buffered_frames(struc
|
||||
@@ -1710,7 +1725,7 @@ void ath9k_release_buffered_frames(struc
|
||||
break;
|
||||
|
||||
list_add_tail(&bf->list, &bf_q);
|
||||
|
@ -67,7 +67,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|||
if (bf_isampdu(bf)) {
|
||||
ath_tx_addto_baw(sc, tid, bf);
|
||||
bf->bf_state.bf_type &= ~BUF_AGGR;
|
||||
@@ -2343,7 +2358,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
@@ -2410,7 +2425,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
if (txctl->paprd)
|
||||
bf->bf_state.bfs_paprd_timestamp = jiffies;
|
||||
|
||||
|
@ -76,7 +76,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|||
ath_tx_send_normal(sc, txq, tid, skb);
|
||||
|
||||
out:
|
||||
@@ -2382,7 +2397,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
|
||||
@@ -2449,7 +2464,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
|
||||
break;
|
||||
|
||||
bf->bf_lastbf = bf;
|
||||
|
@ -85,7 +85,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|||
ath_buf_set_rate(sc, bf, &info, fi->framelen, false);
|
||||
duration += info.rates[0].PktDuration;
|
||||
if (bf_tail)
|
||||
@@ -2898,7 +2913,7 @@ int ath9k_tx99_send(struct ath_softc *sc
|
||||
@@ -2968,7 +2983,7 @@ int ath9k_tx99_send(struct ath_softc *sc
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411.
|
|||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -2910,7 +2910,8 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
@@ -2931,7 +2931,8 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
{
|
||||
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
|
||||
struct ieee80211_channel *channel;
|
||||
|
@ -18,7 +18,7 @@ This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411.
|
|||
|
||||
if (!chan)
|
||||
return;
|
||||
@@ -2918,10 +2919,15 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
@@ -2939,10 +2940,15 @@ void ath9k_hw_apply_txpower(struct ath_h
|
||||
channel = chan->chan;
|
||||
chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
|
||||
new_pwr = min_t(int, chan_pwr, reg->power_limit);
|
|
@ -11,7 +11,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -175,6 +175,7 @@ struct ieee80211_tx_data {
|
||||
@@ -177,6 +177,7 @@ struct ieee80211_tx_data {
|
||||
struct ieee80211_tx_rate rate;
|
||||
|
||||
unsigned int flags;
|
||||
|
@ -21,7 +21,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -955,7 +955,7 @@ ieee80211_tx_h_fragment(struct ieee80211
|
||||
@@ -925,7 +925,7 @@ ieee80211_tx_h_fragment(struct ieee80211
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
int frag_threshold = tx->local->hw.wiphy->frag_threshold;
|
||||
|
@ -30,7 +30,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
int fragnum;
|
||||
|
||||
/* no matter what happens, tx->skb moves to tx->skbs */
|
||||
@@ -976,8 +976,6 @@ ieee80211_tx_h_fragment(struct ieee80211
|
||||
@@ -946,8 +946,6 @@ ieee80211_tx_h_fragment(struct ieee80211
|
||||
if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
|
||||
return TX_DROP;
|
||||
|
||||
|
@ -39,7 +39,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
/* internal error, why isn't DONTFRAG set? */
|
||||
if (WARN_ON(skb->len + FCS_LEN <= frag_threshold))
|
||||
return TX_DROP;
|
||||
@@ -1209,6 +1207,8 @@ ieee80211_tx_prepare(struct ieee80211_su
|
||||
@@ -1179,6 +1177,8 @@ ieee80211_tx_prepare(struct ieee80211_su
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
|
@ -48,7 +48,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
if (likely(sta)) {
|
||||
if (!IS_ERR(sta))
|
||||
tx->sta = sta;
|
||||
@@ -3414,6 +3414,7 @@ begin:
|
||||
@@ -3437,6 +3437,7 @@ begin:
|
||||
tx.local = local;
|
||||
tx.skb = skb;
|
||||
tx.sdata = vif_to_sdata(info->control.vif);
|
||||
|
@ -56,7 +56,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
|
||||
if (txq->sta)
|
||||
tx.sta = container_of(txq->sta, struct sta_info, sta);
|
||||
@@ -3584,6 +3585,7 @@ ieee80211_build_data_template(struct iee
|
||||
@@ -3731,6 +3732,7 @@ ieee80211_build_data_template(struct iee
|
||||
hdr = (void *)skb->data;
|
||||
tx.sta = sta_info_get(sdata, hdr->addr1);
|
||||
tx.skb = skb;
|
||||
|
@ -126,7 +126,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
if (!iv)
|
||||
return -1;
|
||||
|
||||
@@ -306,13 +306,14 @@ static int wep_encrypt_skb(struct ieee80
|
||||
@@ -307,13 +307,14 @@ static int wep_encrypt_skb(struct ieee80
|
||||
struct ieee80211_key_conf *hw_key = info->control.hw_key;
|
||||
|
||||
if (!hw_key) {
|
||||
|
@ -181,7 +181,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
len = skb->len - hdrlen;
|
||||
|
||||
if (info->control.hw_key)
|
||||
@@ -418,7 +417,7 @@ static int ccmp_encrypt_skb(struct ieee8
|
||||
@@ -419,7 +418,7 @@ static int ccmp_encrypt_skb(struct ieee8
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
len = skb->len - hdrlen;
|
||||
|
||||
if (info->control.hw_key)
|
||||
@@ -651,7 +650,7 @@ static int gcmp_encrypt_skb(struct ieee8
|
||||
@@ -652,7 +651,7 @@ static int gcmp_encrypt_skb(struct ieee8
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
len = skb->len - hdrlen;
|
||||
|
||||
if (info->control.hw_key)
|
||||
@@ -791,7 +790,6 @@ static ieee80211_tx_result
|
||||
@@ -792,7 +791,6 @@ static ieee80211_tx_result
|
||||
ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
@ -207,7 +207,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
struct ieee80211_key *key = tx->key;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
int hdrlen;
|
||||
@@ -807,8 +805,7 @@ ieee80211_crypto_cs_encrypt(struct ieee8
|
||||
@@ -808,8 +806,7 @@ ieee80211_crypto_cs_encrypt(struct ieee8
|
||||
pskb_expand_head(skb, iv_len, 0, GFP_ATOMIC)))
|
||||
return TX_DROP;
|
||||
|
|
@ -23,9 +23,9 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -2025,6 +2025,9 @@ struct ieee80211_txq {
|
||||
* drivers, mac80211 packet loss mechanism will not be triggered and driver
|
||||
* is completely depending on firmware event for station kickout.
|
||||
@@ -2043,6 +2043,9 @@ struct ieee80211_txq {
|
||||
* The stack will not do fragmentation.
|
||||
* The callback for @set_frag_threshold should be set as well.
|
||||
*
|
||||
+ * @IEEE80211_HW_NEEDS_ALIGNED4_SKBS: Driver need aligned skbs to four-byte.
|
||||
+ * Padding will be added after ieee80211_hdr, before IV/LLC.
|
||||
|
@ -33,28 +33,28 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
|
||||
*/
|
||||
enum ieee80211_hw_flags {
|
||||
@@ -2066,6 +2069,7 @@ enum ieee80211_hw_flags {
|
||||
IEEE80211_HW_TX_AMSDU,
|
||||
@@ -2085,6 +2088,7 @@ enum ieee80211_hw_flags {
|
||||
IEEE80211_HW_TX_FRAG_LIST,
|
||||
IEEE80211_HW_REPORTS_LOW_ACK,
|
||||
IEEE80211_HW_SUPPORTS_TX_FRAG,
|
||||
+ IEEE80211_HW_NEEDS_ALIGNED4_SKBS,
|
||||
|
||||
/* keep last, obviously */
|
||||
NUM_IEEE80211_HW_FLAGS
|
||||
--- a/net/mac80211/debugfs.c
|
||||
+++ b/net/mac80211/debugfs.c
|
||||
@@ -210,6 +210,7 @@ static const char *hw_flag_names[] = {
|
||||
FLAG(TX_AMSDU),
|
||||
@@ -211,6 +211,7 @@ static const char *hw_flag_names[] = {
|
||||
FLAG(TX_FRAG_LIST),
|
||||
FLAG(REPORTS_LOW_ACK),
|
||||
FLAG(SUPPORTS_TX_FRAG),
|
||||
+ FLAG(NEEDS_ALIGNED4_SKBS),
|
||||
#undef FLAG
|
||||
};
|
||||
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -1529,6 +1529,29 @@ ieee80211_have_rx_timestamp(struct ieee8
|
||||
return false;
|
||||
@@ -1553,6 +1553,29 @@ ieee80211_vif_get_num_mcast_if(struct ie
|
||||
return -1;
|
||||
}
|
||||
|
||||
+static inline unsigned int
|
||||
|
@ -96,7 +96,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
struct rcu_head rcu_head;
|
||||
--- a/net/mac80211/status.c
|
||||
+++ b/net/mac80211/status.c
|
||||
@@ -689,9 +689,22 @@ void ieee80211_tx_monitor(struct ieee802
|
||||
@@ -693,9 +693,22 @@ void ieee80211_tx_monitor(struct ieee802
|
||||
struct sk_buff *skb2;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
@ -137,7 +137,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1206,8 +1206,7 @@ ieee80211_tx_prepare(struct ieee80211_su
|
||||
@@ -1176,8 +1176,7 @@ ieee80211_tx_prepare(struct ieee80211_su
|
||||
info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
@ -147,7 +147,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
|
||||
if (likely(sta)) {
|
||||
if (!IS_ERR(sta))
|
||||
@@ -2158,7 +2157,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
|
||||
@@ -2152,7 +2151,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
|
||||
goto fail;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
|
||||
|
@ -156,7 +156,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
|
||||
if (skb->len < len_rthdr + hdrlen)
|
||||
goto fail;
|
||||
@@ -2376,7 +2375,7 @@ static struct sk_buff *ieee80211_build_h
|
||||
@@ -2370,7 +2369,7 @@ static struct sk_buff *ieee80211_build_h
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_sub_if_data *ap_sdata;
|
||||
enum nl80211_band band;
|
||||
|
@ -165,7 +165,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
|
||||
if (IS_ERR(sta))
|
||||
sta = NULL;
|
||||
@@ -2596,6 +2595,9 @@ static struct sk_buff *ieee80211_build_h
|
||||
@@ -2590,6 +2589,9 @@ static struct sk_buff *ieee80211_build_h
|
||||
hdrlen += 2;
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
/*
|
||||
* Drop unicast frames to unauthorised stations unless they are
|
||||
* EAPOL frames from the local station.
|
||||
@@ -2676,6 +2678,7 @@ static struct sk_buff *ieee80211_build_h
|
||||
@@ -2670,6 +2672,7 @@ static struct sk_buff *ieee80211_build_h
|
||||
|
||||
skb_pull(skb, skip_header_bytes);
|
||||
head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
|
||||
|
@ -183,7 +183,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
|
||||
/*
|
||||
* So we need to modify the skb header and hence need a copy of
|
||||
@@ -2708,6 +2711,9 @@ static struct sk_buff *ieee80211_build_h
|
||||
@@ -2702,6 +2705,9 @@ static struct sk_buff *ieee80211_build_h
|
||||
memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
|
||||
#endif
|
||||
|
||||
|
@ -193,7 +193,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
if (ieee80211_is_data_qos(fc)) {
|
||||
__le16 *qos_control;
|
||||
|
||||
@@ -2883,6 +2889,9 @@ void ieee80211_check_fast_xmit(struct st
|
||||
@@ -2877,6 +2883,9 @@ void ieee80211_check_fast_xmit(struct st
|
||||
fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
|
|||
/* We store the key here so there's no point in using rcu_dereference()
|
||||
* but that's fine because the code that changes the pointers will call
|
||||
* this function after doing so. For a single CPU that would be enough,
|
||||
@@ -3436,7 +3445,7 @@ begin:
|
||||
@@ -3464,7 +3473,7 @@ begin:
|
||||
|
||||
if (tx.key &&
|
||||
(tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
|
|
@ -10,7 +10,7 @@ Signed-off-by: Chaitanya TK <chaitanya.mgit@gmail.com>
|
|||
|
||||
--- a/include/linux/ieee80211.h
|
||||
+++ b/include/linux/ieee80211.h
|
||||
@@ -1551,6 +1551,7 @@ struct ieee80211_vht_operation {
|
||||
@@ -1553,6 +1553,7 @@ struct ieee80211_vht_operation {
|
||||
#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
|
||||
#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
|
||||
#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700
|
||||
|
@ -20,15 +20,16 @@ Signed-off-by: Chaitanya TK <chaitanya.mgit@gmail.com>
|
|||
#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -1166,13 +1166,14 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
@@ -1130,7 +1130,7 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
struct minstrel_ht_sta_priv *msp = priv_sta;
|
||||
struct minstrel_ht_sta *mi = &msp->ht;
|
||||
struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
|
||||
- u16 sta_cap = sta->ht_cap.cap;
|
||||
+ u16 ht_cap = sta->ht_cap.cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
|
||||
struct sta_info *sinfo = container_of(sta, struct sta_info, sta);
|
||||
int use_vht;
|
||||
int n_supported = 0;
|
||||
@@ -1138,6 +1138,7 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
int ack_dur;
|
||||
int stbc;
|
||||
int i;
|
||||
|
@ -36,7 +37,7 @@ Signed-off-by: Chaitanya TK <chaitanya.mgit@gmail.com>
|
|||
|
||||
/* fall back to the old minstrel for legacy stations */
|
||||
if (!sta->ht_cap.ht_supported)
|
||||
@@ -1210,16 +1211,24 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
@@ -1175,16 +1176,24 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
}
|
||||
mi->sample_tries = 4;
|
||||
|
||||
|
@ -66,7 +67,7 @@ Signed-off-by: Chaitanya TK <chaitanya.mgit@gmail.com>
|
|||
for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
|
||||
u32 gflags = minstrel_mcs_groups[i].flags;
|
||||
int bw, nss;
|
||||
@@ -1232,10 +1241,10 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
@@ -1197,10 +1206,10 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
|
||||
if (gflags & IEEE80211_TX_RC_SHORT_GI) {
|
||||
if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
|
|
@ -7,7 +7,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -1635,6 +1635,22 @@ void ath_tx_aggr_wakeup(struct ath_softc
|
||||
@@ -1694,6 +1694,22 @@ void ath_tx_aggr_wakeup(struct ath_softc
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
u16 tids, int nframes,
|
||||
@@ -1665,6 +1681,7 @@ void ath9k_release_buffered_frames(struc
|
||||
@@ -1724,6 +1740,7 @@ void ath9k_release_buffered_frames(struc
|
||||
if (!bf)
|
||||
break;
|
||||
|
||||
|
@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
list_add_tail(&bf->list, &bf_q);
|
||||
ath_set_rates(tid->an->vif, tid->an->sta, bf, true);
|
||||
if (bf_isampdu(bf)) {
|
||||
@@ -1688,6 +1705,9 @@ void ath9k_release_buffered_frames(struc
|
||||
@@ -1747,6 +1764,9 @@ void ath9k_release_buffered_frames(struc
|
||||
if (list_empty(&bf_q))
|
||||
return;
|
||||
|
|
@ -1,285 +0,0 @@
|
|||
From: Ben Greear <greearb@candelatech.com>
|
||||
Date: Thu, 6 Oct 2016 17:34:14 -0700
|
||||
Subject: [PATCH] ath10k: Add support for 160Mhz.
|
||||
|
||||
This patch was written by Sebastian Gottschall.
|
||||
|
||||
Signed-off-by: Ben Greear <greearb@candelatech.com>
|
||||
Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
|
||||
@@ -702,6 +702,10 @@ static void ath10k_htt_rx_h_rates(struct
|
||||
/* 80MHZ */
|
||||
case 2:
|
||||
status->vht_flag |= RX_VHT_FLAG_80MHZ;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ status->vht_flag |= RX_VHT_FLAG_160MHZ;
|
||||
+ break;
|
||||
}
|
||||
|
||||
status->flag |= RX_FLAG_VHT;
|
||||
@@ -926,7 +930,7 @@ static void ath10k_process_rx(struct ath
|
||||
*status = *rx_status;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_DATA,
|
||||
- "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
+ "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
skb,
|
||||
skb->len,
|
||||
ieee80211_get_SA(hdr),
|
||||
@@ -940,6 +944,7 @@ static void ath10k_process_rx(struct ath
|
||||
status->flag & RX_FLAG_VHT ? "vht" : "",
|
||||
status->flag & RX_FLAG_40MHZ ? "40" : "",
|
||||
status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "",
|
||||
+ status->vht_flag & RX_VHT_FLAG_160MHZ ? "160" : "",
|
||||
status->flag & RX_FLAG_SHORT_GI ? "sgi " : "",
|
||||
status->rate_idx,
|
||||
status->vht_nss,
|
||||
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||
@@ -568,10 +568,14 @@ chan_to_phymode(const struct cfg80211_ch
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
phymode = MODE_11AC_VHT80;
|
||||
break;
|
||||
+ case NL80211_CHAN_WIDTH_160:
|
||||
+ phymode = MODE_11AC_VHT160;
|
||||
+ break;
|
||||
+ case NL80211_CHAN_WIDTH_80P80:
|
||||
+ phymode = MODE_11AC_VHT80_80;
|
||||
+ break;
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
case NL80211_CHAN_WIDTH_10:
|
||||
- case NL80211_CHAN_WIDTH_80P80:
|
||||
- case NL80211_CHAN_WIDTH_160:
|
||||
phymode = MODE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
@@ -970,6 +974,7 @@ static int ath10k_monitor_vdev_start(str
|
||||
arg.vdev_id = vdev_id;
|
||||
arg.channel.freq = channel->center_freq;
|
||||
arg.channel.band_center_freq1 = chandef->center_freq1;
|
||||
+ arg.channel.band_center_freq2 = chandef->center_freq2;
|
||||
|
||||
/* TODO setup this dynamically, what in case we
|
||||
don't have any vifs? */
|
||||
@@ -1381,6 +1386,7 @@ static int ath10k_vdev_start_restart(str
|
||||
|
||||
arg.channel.freq = chandef->chan->center_freq;
|
||||
arg.channel.band_center_freq1 = chandef->center_freq1;
|
||||
+ arg.channel.band_center_freq2 = chandef->center_freq2;
|
||||
arg.channel.mode = chan_to_phymode(chandef);
|
||||
|
||||
arg.channel.min_power = 0;
|
||||
@@ -2444,6 +2450,9 @@ static void ath10k_peer_assoc_h_vht(stru
|
||||
if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
|
||||
arg->peer_flags |= ar->wmi.peer_flags->bw80;
|
||||
|
||||
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
|
||||
+ arg->peer_flags |= ar->wmi.peer_flags->bw160;
|
||||
+
|
||||
arg->peer_vht_rates.rx_max_rate =
|
||||
__le16_to_cpu(vht_cap->vht_mcs.rx_highest);
|
||||
arg->peer_vht_rates.rx_mcs_set =
|
||||
@@ -2545,7 +2554,17 @@ static void ath10k_peer_assoc_h_phymode(
|
||||
!ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
|
||||
if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
|
||||
phymode = MODE_11AC_VHT80;
|
||||
- else if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
|
||||
+ else if (sta->bandwidth == IEEE80211_STA_RX_BW_160) {
|
||||
+ phymode = MODE_11AC_VHT160;
|
||||
+ switch (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
|
||||
+ case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
|
||||
+ phymode = MODE_11AC_VHT160;
|
||||
+ break;
|
||||
+ case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
|
||||
+ phymode = MODE_11AC_VHT80_80;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
|
||||
phymode = MODE_11AC_VHT40;
|
||||
else if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
|
||||
phymode = MODE_11AC_VHT20;
|
||||
@@ -4277,6 +4296,10 @@ static struct ieee80211_sta_vht_cap ath1
|
||||
vht_cap.cap |= val;
|
||||
}
|
||||
|
||||
+ if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) && !(ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) {
|
||||
+ vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
|
||||
+ }
|
||||
+
|
||||
mcs_map = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
|
||||
@@ -6913,6 +6936,9 @@ static void ath10k_sta_rc_update(struct
|
||||
bw = WMI_PEER_CHWIDTH_80MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
+ bw = WMI_PEER_CHWIDTH_160MHZ;
|
||||
+ break;
|
||||
+ default:
|
||||
ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n",
|
||||
sta->bandwidth, sta->addr);
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
|
||||
@@ -3560,6 +3560,7 @@ static const struct wmi_peer_flags_map w
|
||||
.vht = WMI_TLV_PEER_VHT,
|
||||
.bw80 = WMI_TLV_PEER_80MHZ,
|
||||
.pmf = WMI_TLV_PEER_PMF,
|
||||
+ .bw160 = WMI_TLV_PEER_160MHZ,
|
||||
};
|
||||
|
||||
/************/
|
||||
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
|
||||
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
|
||||
@@ -543,6 +543,7 @@ enum wmi_tlv_peer_flags {
|
||||
WMI_TLV_PEER_VHT = 0x02000000,
|
||||
WMI_TLV_PEER_80MHZ = 0x04000000,
|
||||
WMI_TLV_PEER_PMF = 0x08000000,
|
||||
+ WMI_TLV_PEER_160MHZ = 0x20000000,
|
||||
};
|
||||
|
||||
enum wmi_tlv_tag {
|
||||
--- a/drivers/net/wireless/ath/ath10k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
|
||||
@@ -1576,6 +1576,7 @@ static const struct wmi_peer_flags_map w
|
||||
.bw80 = WMI_PEER_80MHZ,
|
||||
.vht_2g = WMI_PEER_VHT_2G,
|
||||
.pmf = WMI_PEER_PMF,
|
||||
+ .bw160 = WMI_PEER_160MHZ,
|
||||
};
|
||||
|
||||
static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = {
|
||||
@@ -1593,6 +1594,7 @@ static const struct wmi_peer_flags_map w
|
||||
.spatial_mux = WMI_10X_PEER_SPATIAL_MUX,
|
||||
.vht = WMI_10X_PEER_VHT,
|
||||
.bw80 = WMI_10X_PEER_80MHZ,
|
||||
+ .bw160 = WMI_10X_PEER_160MHZ,
|
||||
};
|
||||
|
||||
static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
|
||||
@@ -1612,6 +1614,7 @@ static const struct wmi_peer_flags_map w
|
||||
.bw80 = WMI_10_2_PEER_80MHZ,
|
||||
.vht_2g = WMI_10_2_PEER_VHT_2G,
|
||||
.pmf = WMI_10_2_PEER_PMF,
|
||||
+ .bw160 = WMI_10_2_PEER_160MHZ,
|
||||
};
|
||||
|
||||
void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
|
||||
@@ -1636,7 +1639,10 @@ void ath10k_wmi_put_wmi_channel(struct w
|
||||
|
||||
ch->mhz = __cpu_to_le32(arg->freq);
|
||||
ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
|
||||
- ch->band_center_freq2 = 0;
|
||||
+ if (arg->mode == MODE_11AC_VHT80_80)
|
||||
+ ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq2);
|
||||
+ else
|
||||
+ ch->band_center_freq2 = 0;
|
||||
ch->min_power = arg->min_power;
|
||||
ch->max_power = arg->max_power;
|
||||
ch->reg_power = arg->max_reg_power;
|
||||
--- a/drivers/net/wireless/ath/ath10k/wmi.h
|
||||
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
|
||||
@@ -1728,8 +1728,10 @@ enum wmi_phy_mode {
|
||||
MODE_11AC_VHT20_2G = 11,
|
||||
MODE_11AC_VHT40_2G = 12,
|
||||
MODE_11AC_VHT80_2G = 13,
|
||||
- MODE_UNKNOWN = 14,
|
||||
- MODE_MAX = 14
|
||||
+ MODE_11AC_VHT80_80 = 14,
|
||||
+ MODE_11AC_VHT160 = 15,
|
||||
+ MODE_UNKNOWN = 16,
|
||||
+ MODE_MAX = 16
|
||||
};
|
||||
|
||||
static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode)
|
||||
@@ -1757,6 +1759,10 @@ static inline const char *ath10k_wmi_phy
|
||||
return "11ac-vht40";
|
||||
case MODE_11AC_VHT80:
|
||||
return "11ac-vht80";
|
||||
+ case MODE_11AC_VHT160:
|
||||
+ return "11ac-vht160";
|
||||
+ case MODE_11AC_VHT80_80:
|
||||
+ return "11ac-vht80+80";
|
||||
case MODE_11AC_VHT20_2G:
|
||||
return "11ac-vht20-2g";
|
||||
case MODE_11AC_VHT40_2G:
|
||||
@@ -1811,6 +1817,7 @@ struct wmi_channel {
|
||||
struct wmi_channel_arg {
|
||||
u32 freq;
|
||||
u32 band_center_freq1;
|
||||
+ u32 band_center_freq2;
|
||||
bool passive;
|
||||
bool allow_ibss;
|
||||
bool allow_ht;
|
||||
@@ -1875,9 +1882,18 @@ enum wmi_channel_change_cause {
|
||||
#define WMI_VHT_CAP_MAX_MPDU_LEN_MASK 0x00000003
|
||||
#define WMI_VHT_CAP_RX_LDPC 0x00000010
|
||||
#define WMI_VHT_CAP_SGI_80MHZ 0x00000020
|
||||
+#define WMI_VHT_CAP_SGI_160MHZ 0x00000040
|
||||
#define WMI_VHT_CAP_TX_STBC 0x00000080
|
||||
#define WMI_VHT_CAP_RX_STBC_MASK 0x00000300
|
||||
#define WMI_VHT_CAP_RX_STBC_MASK_SHIFT 8
|
||||
+#define WMI_VHT_CAP_SU_BFER 0x00000800
|
||||
+#define WMI_VHT_CAP_SU_BFEE 0x00001000
|
||||
+#define WMI_VHT_CAP_MAX_CS_ANT_MASK 0x0000E000
|
||||
+#define WMI_VHT_CAP_MAX_CS_ANT_MASK_SHIFT 13
|
||||
+#define WMI_VHT_CAP_MAX_SND_DIM_MASK 0x00070000
|
||||
+#define WMI_VHT_CAP_MAX_SND_DIM_MASK_SHIFT 16
|
||||
+#define WMI_VHT_CAP_MU_BFER 0x00080000
|
||||
+#define WMI_VHT_CAP_MU_BFEE 0x00100000
|
||||
#define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP 0x03800000
|
||||
#define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT 23
|
||||
#define WMI_VHT_CAP_RX_FIXED_ANT 0x10000000
|
||||
@@ -1926,6 +1942,8 @@ enum {
|
||||
REGDMN_MODE_11AC_VHT40PLUS = 0x40000, /* 5Ghz, VHT40 + channels */
|
||||
REGDMN_MODE_11AC_VHT40MINUS = 0x80000, /* 5Ghz VHT40 - channels */
|
||||
REGDMN_MODE_11AC_VHT80 = 0x100000, /* 5Ghz, VHT80 channels */
|
||||
+ REGDMN_MODE_11AC_VHT160 = 0x200000, /* 5Ghz, VHT160 channels */
|
||||
+ REGDMN_MODE_11AC_VHT80_80 = 0x400000, /* 5Ghz, VHT80+80 channels */
|
||||
REGDMN_MODE_ALL = 0xffffffff
|
||||
};
|
||||
|
||||
@@ -5769,6 +5787,7 @@ enum wmi_peer_chwidth {
|
||||
WMI_PEER_CHWIDTH_20MHZ = 0,
|
||||
WMI_PEER_CHWIDTH_40MHZ = 1,
|
||||
WMI_PEER_CHWIDTH_80MHZ = 2,
|
||||
+ WMI_PEER_CHWIDTH_160MHZ = 3,
|
||||
};
|
||||
|
||||
enum wmi_peer_param {
|
||||
@@ -5859,6 +5878,7 @@ struct wmi_peer_flags_map {
|
||||
u32 bw80;
|
||||
u32 vht_2g;
|
||||
u32 pmf;
|
||||
+ u32 bw160;
|
||||
};
|
||||
|
||||
enum wmi_peer_flags {
|
||||
@@ -5878,6 +5898,7 @@ enum wmi_peer_flags {
|
||||
WMI_PEER_80MHZ = 0x04000000,
|
||||
WMI_PEER_VHT_2G = 0x08000000,
|
||||
WMI_PEER_PMF = 0x10000000,
|
||||
+ WMI_PEER_160MHZ = 0x20000000
|
||||
};
|
||||
|
||||
enum wmi_10x_peer_flags {
|
||||
@@ -5895,6 +5916,7 @@ enum wmi_10x_peer_flags {
|
||||
WMI_10X_PEER_SPATIAL_MUX = 0x00200000,
|
||||
WMI_10X_PEER_VHT = 0x02000000,
|
||||
WMI_10X_PEER_80MHZ = 0x04000000,
|
||||
+ WMI_10X_PEER_160MHZ = 0x20000000
|
||||
};
|
||||
|
||||
enum wmi_10_2_peer_flags {
|
||||
@@ -5914,6 +5936,7 @@ enum wmi_10_2_peer_flags {
|
||||
WMI_10_2_PEER_80MHZ = 0x04000000,
|
||||
WMI_10_2_PEER_VHT_2G = 0x08000000,
|
||||
WMI_10_2_PEER_PMF = 0x10000000,
|
||||
+ WMI_10_2_PEER_160MHZ = 0x20000000
|
||||
};
|
||||
|
||||
/*
|
|
@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -945,7 +945,8 @@ ath_tx_get_tid_subframe(struct ath_softc
|
||||
@@ -1004,7 +1004,8 @@ ath_tx_get_tid_subframe(struct ath_softc
|
||||
bf->bf_lastbf = bf;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
|
@ -1,275 +0,0 @@
|
|||
From: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
Date: Mon, 19 Sep 2016 19:00:10 +0800
|
||||
Subject: [PATCH] mac80211: Use rhltable instead of rhashtable
|
||||
|
||||
mac80211 currently uses rhashtable with insecure_elasticity set
|
||||
to true. The latter is because of duplicate objects. What's
|
||||
more, mac80211 walks the rhashtable chains by hand which is broken
|
||||
as rhashtable may contain multiple tables due to resizing or
|
||||
rehashing.
|
||||
|
||||
This patch fixes it by converting it to the newly added rhltable
|
||||
interface which is designed for use with duplicate objects.
|
||||
|
||||
With rhltable a lookup returns a list of objects instead of a
|
||||
single one. This is then fed into the existing for_each_sta_info
|
||||
macro.
|
||||
|
||||
This patch also deletes the sta_addr_hash function since rhashtable
|
||||
defaults to jhash.
|
||||
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -1233,7 +1233,7 @@ struct ieee80211_local {
|
||||
spinlock_t tim_lock;
|
||||
unsigned long num_sta;
|
||||
struct list_head sta_list;
|
||||
- struct rhashtable sta_hash;
|
||||
+ struct rhltable sta_hash;
|
||||
struct timer_list sta_cleanup;
|
||||
int sta_generation;
|
||||
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -4004,7 +4004,7 @@ static void __ieee80211_rx_handle_packet
|
||||
__le16 fc;
|
||||
struct ieee80211_rx_data rx;
|
||||
struct ieee80211_sub_if_data *prev;
|
||||
- struct rhash_head *tmp;
|
||||
+ struct rhlist_head *tmp;
|
||||
int err = 0;
|
||||
|
||||
fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
|
||||
@@ -4047,13 +4047,10 @@ static void __ieee80211_rx_handle_packet
|
||||
goto out;
|
||||
} else if (ieee80211_is_data(fc)) {
|
||||
struct sta_info *sta, *prev_sta;
|
||||
- const struct bucket_table *tbl;
|
||||
|
||||
prev_sta = NULL;
|
||||
|
||||
- tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
|
||||
-
|
||||
- for_each_sta_info(local, tbl, hdr->addr2, sta, tmp) {
|
||||
+ for_each_sta_info(local, hdr->addr2, sta, tmp) {
|
||||
if (!prev_sta) {
|
||||
prev_sta = sta;
|
||||
continue;
|
||||
--- a/net/mac80211/sta_info.c
|
||||
+++ b/net/mac80211/sta_info.c
|
||||
@@ -67,12 +67,10 @@
|
||||
|
||||
static const struct rhashtable_params sta_rht_params = {
|
||||
.nelem_hint = 3, /* start small */
|
||||
- .insecure_elasticity = true, /* Disable chain-length checks. */
|
||||
.automatic_shrinking = true,
|
||||
.head_offset = offsetof(struct sta_info, hash_node),
|
||||
.key_offset = offsetof(struct sta_info, addr),
|
||||
.key_len = ETH_ALEN,
|
||||
- .hashfn = sta_addr_hash,
|
||||
.max_size = CPTCFG_MAC80211_STA_HASH_MAX_SIZE,
|
||||
};
|
||||
|
||||
@@ -80,8 +78,8 @@ static const struct rhashtable_params st
|
||||
static int sta_info_hash_del(struct ieee80211_local *local,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
- return rhashtable_remove_fast(&local->sta_hash, &sta->hash_node,
|
||||
- sta_rht_params);
|
||||
+ return rhltable_remove(&local->sta_hash, &sta->hash_node,
|
||||
+ sta_rht_params);
|
||||
}
|
||||
|
||||
static void __cleanup_single_sta(struct sta_info *sta)
|
||||
@@ -157,19 +155,22 @@ static void cleanup_single_sta(struct st
|
||||
sta_info_free(local, sta);
|
||||
}
|
||||
|
||||
+struct rhlist_head *sta_info_hash_lookup(struct ieee80211_local *local,
|
||||
+ const u8 *addr)
|
||||
+{
|
||||
+ return rhltable_lookup(&local->sta_hash, addr, sta_rht_params);
|
||||
+}
|
||||
+
|
||||
/* protected by RCU */
|
||||
struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *addr)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
+ struct rhlist_head *tmp;
|
||||
struct sta_info *sta;
|
||||
- struct rhash_head *tmp;
|
||||
- const struct bucket_table *tbl;
|
||||
|
||||
rcu_read_lock();
|
||||
- tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
|
||||
-
|
||||
- for_each_sta_info(local, tbl, addr, sta, tmp) {
|
||||
+ for_each_sta_info(local, addr, sta, tmp) {
|
||||
if (sta->sdata == sdata) {
|
||||
rcu_read_unlock();
|
||||
/* this is safe as the caller must already hold
|
||||
@@ -190,14 +191,11 @@ struct sta_info *sta_info_get_bss(struct
|
||||
const u8 *addr)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
+ struct rhlist_head *tmp;
|
||||
struct sta_info *sta;
|
||||
- struct rhash_head *tmp;
|
||||
- const struct bucket_table *tbl;
|
||||
|
||||
rcu_read_lock();
|
||||
- tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
|
||||
-
|
||||
- for_each_sta_info(local, tbl, addr, sta, tmp) {
|
||||
+ for_each_sta_info(local, addr, sta, tmp) {
|
||||
if (sta->sdata == sdata ||
|
||||
(sta->sdata->bss && sta->sdata->bss == sdata->bss)) {
|
||||
rcu_read_unlock();
|
||||
@@ -263,8 +261,8 @@ void sta_info_free(struct ieee80211_loca
|
||||
static int sta_info_hash_add(struct ieee80211_local *local,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
- return rhashtable_insert_fast(&local->sta_hash, &sta->hash_node,
|
||||
- sta_rht_params);
|
||||
+ return rhltable_insert(&local->sta_hash, &sta->hash_node,
|
||||
+ sta_rht_params);
|
||||
}
|
||||
|
||||
static void sta_deliver_ps_frames(struct work_struct *wk)
|
||||
@@ -453,9 +451,9 @@ static int sta_info_insert_check(struct
|
||||
is_multicast_ether_addr(sta->sta.addr)))
|
||||
return -EINVAL;
|
||||
|
||||
- /* Strictly speaking this isn't necessary as we hold the mutex, but
|
||||
- * the rhashtable code can't really deal with that distinction. We
|
||||
- * do require the mutex for correctness though.
|
||||
+ /* The RCU read lock is required by rhashtable due to
|
||||
+ * asynchronous resize/rehash. We also require the mutex
|
||||
+ * for correctness.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
lockdep_assert_held(&sdata->local->sta_mtx);
|
||||
@@ -1043,16 +1041,11 @@ static void sta_info_cleanup(unsigned lo
|
||||
round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL));
|
||||
}
|
||||
|
||||
-u32 sta_addr_hash(const void *key, u32 length, u32 seed)
|
||||
-{
|
||||
- return jhash(key, ETH_ALEN, seed);
|
||||
-}
|
||||
-
|
||||
int sta_info_init(struct ieee80211_local *local)
|
||||
{
|
||||
int err;
|
||||
|
||||
- err = rhashtable_init(&local->sta_hash, &sta_rht_params);
|
||||
+ err = rhltable_init(&local->sta_hash, &sta_rht_params);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1068,7 +1061,7 @@ int sta_info_init(struct ieee80211_local
|
||||
void sta_info_stop(struct ieee80211_local *local)
|
||||
{
|
||||
del_timer_sync(&local->sta_cleanup);
|
||||
- rhashtable_destroy(&local->sta_hash);
|
||||
+ rhltable_destroy(&local->sta_hash);
|
||||
}
|
||||
|
||||
|
||||
@@ -1138,17 +1131,14 @@ struct ieee80211_sta *ieee80211_find_sta
|
||||
const u8 *localaddr)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
+ struct rhlist_head *tmp;
|
||||
struct sta_info *sta;
|
||||
- struct rhash_head *tmp;
|
||||
- const struct bucket_table *tbl;
|
||||
-
|
||||
- tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
|
||||
|
||||
/*
|
||||
* Just return a random station if localaddr is NULL
|
||||
* ... first in list.
|
||||
*/
|
||||
- for_each_sta_info(local, tbl, addr, sta, tmp) {
|
||||
+ for_each_sta_info(local, addr, sta, tmp) {
|
||||
if (localaddr &&
|
||||
!ether_addr_equal(sta->sdata->vif.addr, localaddr))
|
||||
continue;
|
||||
--- a/net/mac80211/sta_info.h
|
||||
+++ b/net/mac80211/sta_info.h
|
||||
@@ -455,7 +455,7 @@ struct sta_info {
|
||||
/* General information, mostly static */
|
||||
struct list_head list, free_list;
|
||||
struct rcu_head rcu_head;
|
||||
- struct rhash_head hash_node;
|
||||
+ struct rhlist_head hash_node;
|
||||
u8 addr[ETH_ALEN];
|
||||
struct ieee80211_local *local;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
@@ -638,6 +638,9 @@ rcu_dereference_protected_tid_tx(struct
|
||||
*/
|
||||
#define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
|
||||
|
||||
+struct rhlist_head *sta_info_hash_lookup(struct ieee80211_local *local,
|
||||
+ const u8 *addr);
|
||||
+
|
||||
/*
|
||||
* Get a STA info, must be under RCU read lock.
|
||||
*/
|
||||
@@ -647,17 +650,9 @@ struct sta_info *sta_info_get(struct iee
|
||||
struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *addr);
|
||||
|
||||
-u32 sta_addr_hash(const void *key, u32 length, u32 seed);
|
||||
-
|
||||
-#define _sta_bucket_idx(_tbl, _a) \
|
||||
- rht_bucket_index(_tbl, sta_addr_hash(_a, ETH_ALEN, (_tbl)->hash_rnd))
|
||||
-
|
||||
-#define for_each_sta_info(local, tbl, _addr, _sta, _tmp) \
|
||||
- rht_for_each_entry_rcu(_sta, _tmp, tbl, \
|
||||
- _sta_bucket_idx(tbl, _addr), \
|
||||
- hash_node) \
|
||||
- /* compare address and run code only if it matches */ \
|
||||
- if (ether_addr_equal(_sta->addr, (_addr)))
|
||||
+#define for_each_sta_info(local, _addr, _sta, _tmp) \
|
||||
+ rhl_for_each_entry_rcu(_sta, _tmp, \
|
||||
+ sta_info_hash_lookup(local, _addr), hash_node)
|
||||
|
||||
/*
|
||||
* Get STA info by index, BROKEN!
|
||||
--- a/net/mac80211/status.c
|
||||
+++ b/net/mac80211/status.c
|
||||
@@ -759,8 +759,8 @@ void ieee80211_tx_status(struct ieee8021
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
__le16 fc;
|
||||
struct ieee80211_supported_band *sband;
|
||||
+ struct rhlist_head *tmp;
|
||||
struct sta_info *sta;
|
||||
- struct rhash_head *tmp;
|
||||
int retry_count;
|
||||
int rates_idx;
|
||||
bool send_to_cooked;
|
||||
@@ -768,7 +768,6 @@ void ieee80211_tx_status(struct ieee8021
|
||||
struct ieee80211_bar *bar;
|
||||
int shift = 0;
|
||||
int tid = IEEE80211_NUM_TIDS;
|
||||
- const struct bucket_table *tbl;
|
||||
|
||||
rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
|
||||
|
||||
@@ -777,9 +776,7 @@ void ieee80211_tx_status(struct ieee8021
|
||||
sband = local->hw.wiphy->bands[info->band];
|
||||
fc = hdr->frame_control;
|
||||
|
||||
- tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
|
||||
-
|
||||
- for_each_sta_info(local, tbl, hdr->addr1, sta, tmp) {
|
||||
+ for_each_sta_info(local, hdr->addr1, sta, tmp) {
|
||||
/* skip wrong virtual interface */
|
||||
if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
|
||||
continue;
|
|
@ -21,7 +21,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
|
||||
struct ath_txq *txq,
|
||||
struct ath_atx_tid *tid,
|
||||
@@ -300,7 +300,7 @@ static void ath_tx_flush_tid(struct ath_
|
||||
@@ -311,7 +311,7 @@ static void ath_tx_flush_tid(struct ath_
|
||||
}
|
||||
|
||||
if (fi->baw_tracked) {
|
||||
|
@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
sendbar = true;
|
||||
}
|
||||
|
||||
@@ -316,10 +316,15 @@ static void ath_tx_flush_tid(struct ath_
|
||||
@@ -327,10 +327,15 @@ static void ath_tx_flush_tid(struct ath_
|
||||
}
|
||||
|
||||
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
|
||||
|
@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
index = ATH_BA_INDEX(tid->seq_start, seqno);
|
||||
cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
|
||||
|
||||
@@ -340,6 +345,9 @@ static void ath_tx_addto_baw(struct ath_
|
||||
@@ -351,6 +356,9 @@ static void ath_tx_addto_baw(struct ath_
|
||||
u16 seqno = bf->bf_state.seqno;
|
||||
int index, cindex;
|
||||
|
||||
|
@ -57,7 +57,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
index = ATH_BA_INDEX(tid->seq_start, seqno);
|
||||
cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
|
||||
__set_bit(cindex, tid->tx_buf);
|
||||
@@ -616,7 +624,7 @@ static void ath_tx_complete_aggr(struct
|
||||
@@ -627,7 +635,7 @@ static void ath_tx_complete_aggr(struct
|
||||
* complete the acked-ones/xretried ones; update
|
||||
* block-ack window
|
||||
*/
|
||||
|
@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
|
||||
memcpy(tx_info->control.rates, rates, sizeof(rates));
|
||||
@@ -646,7 +654,7 @@ static void ath_tx_complete_aggr(struct
|
||||
@@ -657,7 +665,7 @@ static void ath_tx_complete_aggr(struct
|
||||
* run out of tx buf.
|
||||
*/
|
||||
if (!tbf) {
|
||||
|
@ -75,7 +75,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
|
||||
ath_tx_complete_buf(sc, bf, txq,
|
||||
&bf_head, NULL, ts,
|
||||
@@ -987,11 +995,14 @@ ath_tx_get_tid_subframe(struct ath_softc
|
||||
@@ -1046,11 +1054,14 @@ ath_tx_get_tid_subframe(struct ath_softc
|
||||
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
list_add(&bf->list, &bf_head);
|
||||
|
@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
return bf;
|
||||
}
|
||||
|
||||
@@ -1049,8 +1060,6 @@ ath_tx_form_aggr(struct ath_softc *sc, s
|
||||
@@ -1108,8 +1119,6 @@ ath_tx_form_aggr(struct ath_softc *sc, s
|
||||
bf->bf_next = NULL;
|
||||
|
||||
/* link buffers of this frame to the aggregate */
|
||||
|
@ -100,7 +100,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
bf->bf_state.ndelim = ndelim;
|
||||
|
||||
list_add_tail(&bf->list, bf_q);
|
||||
@@ -1686,10 +1695,8 @@ void ath9k_release_buffered_frames(struc
|
||||
@@ -1745,10 +1754,8 @@ void ath9k_release_buffered_frames(struc
|
||||
ath9k_set_moredata(sc, bf, true);
|
||||
list_add_tail(&bf->list, &bf_q);
|
||||
ath_set_rates(tid->an->vif, tid->an->sta, bf, true);
|
|
@ -1,37 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Tue, 11 Oct 2016 11:24:07 +0200
|
||||
Subject: [PATCH] mac80211: fix sequence number allocation regression
|
||||
|
||||
The recent commit that moved around TX handlers dropped the sequence
|
||||
number allocation at the end of ieee80211_tx_dequeue and calls
|
||||
ieee80211_tx_h_sequence instead (for the non-fast-xmit case).
|
||||
However, it did not change the fast-xmit sequence allocation condition
|
||||
in ieee80211_xmit_fast_finish, which skipped seqno alloc if intermediate
|
||||
tx queues are being used.
|
||||
|
||||
Drop the now obsolete condition.
|
||||
|
||||
Fixes: bb42f2d13ffc ("mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue")
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3212,7 +3212,6 @@ static void ieee80211_xmit_fast_finish(s
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
- struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
u8 tid = IEEE80211_NUM_TIDS;
|
||||
|
||||
@@ -3224,8 +3223,7 @@ static void ieee80211_xmit_fast_finish(s
|
||||
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
*ieee80211_get_qos_ctl(hdr) = tid;
|
||||
- if (!ieee80211_get_txq(local, &sdata->vif, &sta->sta, skb))
|
||||
- hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
|
||||
+ hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
|
||||
} else {
|
||||
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
|
||||
hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number);
|
|
@ -164,7 +164,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||
static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -2915,8 +2915,6 @@ int ath_tx_init(struct ath_softc *sc, in
|
||||
@@ -2916,8 +2916,6 @@ int ath_tx_init(struct ath_softc *sc, in
|
||||
return error;
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Tue, 11 Oct 2016 19:45:41 +0200
|
||||
Subject: [PATCH] Revert "ath9k_hw: implement temperature compensation support
|
||||
for AR9003+"
|
||||
|
||||
This reverts commit 171f6402e4aa5cd3b8407f82501f7ea21fa54ccc.
|
||||
Some users report that this commit causes a regression in performance
|
||||
under some conditions.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
|
||||
@@ -33,7 +33,6 @@ struct coeff {
|
||||
|
||||
enum ar9003_cal_types {
|
||||
IQ_MISMATCH_CAL = BIT(0),
|
||||
- TEMP_COMP_CAL = BIT(1),
|
||||
};
|
||||
|
||||
static void ar9003_hw_setup_calibration(struct ath_hw *ah,
|
||||
@@ -59,12 +58,6 @@ static void ar9003_hw_setup_calibration(
|
||||
/* Kick-off cal */
|
||||
REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
|
||||
break;
|
||||
- case TEMP_COMP_CAL:
|
||||
- ath_dbg(common, CALIBRATE,
|
||||
- "starting Temperature Compensation Calibration\n");
|
||||
- REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_LOCAL);
|
||||
- REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_START);
|
||||
- break;
|
||||
default:
|
||||
ath_err(common, "Invalid calibration type\n");
|
||||
break;
|
||||
@@ -93,8 +86,7 @@ static bool ar9003_hw_per_calibration(st
|
||||
/*
|
||||
* Accumulate cal measures for active chains
|
||||
*/
|
||||
- if (cur_caldata->calCollect)
|
||||
- cur_caldata->calCollect(ah);
|
||||
+ cur_caldata->calCollect(ah);
|
||||
ah->cal_samples++;
|
||||
|
||||
if (ah->cal_samples >= cur_caldata->calNumSamples) {
|
||||
@@ -107,8 +99,7 @@ static bool ar9003_hw_per_calibration(st
|
||||
/*
|
||||
* Process accumulated data
|
||||
*/
|
||||
- if (cur_caldata->calPostProc)
|
||||
- cur_caldata->calPostProc(ah, numChains);
|
||||
+ cur_caldata->calPostProc(ah, numChains);
|
||||
|
||||
/* Calibration has finished. */
|
||||
caldata->CalValid |= cur_caldata->calType;
|
||||
@@ -323,16 +314,9 @@ static const struct ath9k_percal_data iq
|
||||
ar9003_hw_iqcalibrate
|
||||
};
|
||||
|
||||
-static const struct ath9k_percal_data temp_cal_single_sample = {
|
||||
- TEMP_COMP_CAL,
|
||||
- MIN_CAL_SAMPLES,
|
||||
- PER_MAX_LOG_COUNT,
|
||||
-};
|
||||
-
|
||||
static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
|
||||
{
|
||||
ah->iq_caldata.calData = &iq_cal_single_sample;
|
||||
- ah->temp_caldata.calData = &temp_cal_single_sample;
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
ah->enabled_cals |= TX_IQ_CAL;
|
||||
@@ -340,7 +324,7 @@ static void ar9003_hw_init_cal_settings(
|
||||
ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
|
||||
}
|
||||
|
||||
- ah->supp_cals = IQ_MISMATCH_CAL | TEMP_COMP_CAL;
|
||||
+ ah->supp_cals = IQ_MISMATCH_CAL;
|
||||
}
|
||||
|
||||
#define OFF_UPPER_LT 24
|
||||
@@ -1399,9 +1383,6 @@ static void ar9003_hw_init_cal_common(st
|
||||
INIT_CAL(&ah->iq_caldata);
|
||||
INSERT_CAL(ah, &ah->iq_caldata);
|
||||
|
||||
- INIT_CAL(&ah->temp_caldata);
|
||||
- INSERT_CAL(ah, &ah->temp_caldata);
|
||||
-
|
||||
/* Initialize current pointer to first element in list */
|
||||
ah->cal_list_curr = ah->cal_list;
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -830,7 +830,6 @@ struct ath_hw {
|
||||
/* Calibration */
|
||||
u32 supp_cals;
|
||||
struct ath9k_cal_list iq_caldata;
|
||||
- struct ath9k_cal_list temp_caldata;
|
||||
struct ath9k_cal_list adcgain_caldata;
|
||||
struct ath9k_cal_list adcdc_caldata;
|
||||
struct ath9k_cal_list *cal_list;
|
|
@ -0,0 +1,73 @@
|
|||
From: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
Date: Thu, 2 Feb 2017 10:57:40 +0100
|
||||
Subject: [PATCH] rt2x00: avoid introducing a USB dependency in the
|
||||
rt2x00lib module
|
||||
|
||||
As reported by Felix:
|
||||
|
||||
Though protected by an ifdef, introducing an usb symbol dependency in
|
||||
the rt2x00lib module is a major inconvenience for distributions that
|
||||
package kernel modules split into individual packages.
|
||||
|
||||
Get rid of this unnecessary dependency by calling the usb related
|
||||
function from a more suitable place.
|
||||
|
||||
Cc: Vishal Thanki <vishalthanki@gmail.com>
|
||||
Reported-by: Felix Fietkau <nbd@nbd.name>
|
||||
Fixes: 8b4c0009313f ("rt2x00usb: Use usb anchor to manage URB")
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
|
||||
@@ -1436,21 +1436,6 @@ void rt2x00lib_remove_dev(struct rt2x00_
|
||||
cancel_work_sync(&rt2x00dev->intf_work);
|
||||
cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
|
||||
cancel_work_sync(&rt2x00dev->sleep_work);
|
||||
-#if IS_ENABLED(CPTCFG_RT2X00_LIB_USB)
|
||||
- if (rt2x00_is_usb(rt2x00dev)) {
|
||||
- usb_kill_anchored_urbs(rt2x00dev->anchor);
|
||||
- hrtimer_cancel(&rt2x00dev->txstatus_timer);
|
||||
- cancel_work_sync(&rt2x00dev->rxdone_work);
|
||||
- cancel_work_sync(&rt2x00dev->txdone_work);
|
||||
- }
|
||||
-#endif
|
||||
- if (rt2x00dev->workqueue)
|
||||
- destroy_workqueue(rt2x00dev->workqueue);
|
||||
-
|
||||
- /*
|
||||
- * Free the tx status fifo.
|
||||
- */
|
||||
- kfifo_free(&rt2x00dev->txstatus_fifo);
|
||||
|
||||
/*
|
||||
* Kill the tx status tasklet.
|
||||
@@ -1466,6 +1451,14 @@ void rt2x00lib_remove_dev(struct rt2x00_
|
||||
*/
|
||||
rt2x00lib_uninitialize(rt2x00dev);
|
||||
|
||||
+ if (rt2x00dev->workqueue)
|
||||
+ destroy_workqueue(rt2x00dev->workqueue);
|
||||
+
|
||||
+ /*
|
||||
+ * Free the tx status fifo.
|
||||
+ */
|
||||
+ kfifo_free(&rt2x00dev->txstatus_fifo);
|
||||
+
|
||||
/*
|
||||
* Free extra components
|
||||
*/
|
||||
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
|
||||
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
|
||||
@@ -744,6 +744,11 @@ void rt2x00usb_uninitialize(struct rt2x0
|
||||
{
|
||||
struct data_queue *queue;
|
||||
|
||||
+ usb_kill_anchored_urbs(rt2x00dev->anchor);
|
||||
+ hrtimer_cancel(&rt2x00dev->txstatus_timer);
|
||||
+ cancel_work_sync(&rt2x00dev->rxdone_work);
|
||||
+ cancel_work_sync(&rt2x00dev->txdone_work);
|
||||
+
|
||||
queue_for_each(rt2x00dev, queue)
|
||||
rt2x00usb_free_entries(queue);
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
From f4737a62033d7f3e0db740c449fc62119da7ab8a Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Mon, 30 Jan 2017 16:09:51 +0100
|
||||
Subject: [PATCH] brcmfmac: check brcmf_bus_get_memdump result for error
|
||||
|
@ -15,8 +14,6 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|||
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/debug.c | 23 +++++++++++++++-------
|
||||
1 file changed, 16 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
|
|
@ -1,35 +0,0 @@
|
|||
From: Bob Copeland <me@bobcopeland.com>
|
||||
Date: Wed, 12 Oct 2016 08:24:54 -0400
|
||||
Subject: [PATCH] mac80211: fix up mismerge of ieee80211_tx_dequeue
|
||||
|
||||
Looks like this spinlock wound up on the wrong side of the
|
||||
linearize, and I also lost the part that re-enters the loop.
|
||||
Fix up to match mac80211-next.
|
||||
|
||||
Signed-off-by: Bob Copeland <me@bobcopeland.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3457,17 +3457,17 @@ begin:
|
||||
skb_queue_splice_tail(&tx.skbs, &txqi->frags);
|
||||
}
|
||||
|
||||
-out:
|
||||
- spin_unlock_bh(&fq->lock);
|
||||
-
|
||||
if (skb && skb_has_frag_list(skb) &&
|
||||
!ieee80211_hw_check(&local->hw, TX_FRAG_LIST)) {
|
||||
if (skb_linearize(skb)) {
|
||||
ieee80211_free_txskb(&local->hw, skb);
|
||||
- return NULL;
|
||||
+ goto begin;
|
||||
}
|
||||
}
|
||||
|
||||
+out:
|
||||
+ spin_unlock_bh(&fq->lock);
|
||||
+
|
||||
return skb;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_tx_dequeue);
|
|
@ -1,4 +1,3 @@
|
|||
From 36401cb7ffae731295a6dd1ce2b40d7ad74245f4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Mon, 30 Jan 2017 16:09:52 +0100
|
||||
Subject: [PATCH] brcmfmac: be more verbose when PSM's watchdog fires
|
||||
|
@ -13,8 +12,6 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|||
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
|
|
@ -1,56 +0,0 @@
|
|||
From: Michael Braun <michael-dev@fami-braun.de>
|
||||
Date: Sat, 15 Oct 2016 13:28:18 +0200
|
||||
Subject: [PATCH] mac80211: avoid extra memcpy in A-MSDU head creation
|
||||
|
||||
Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3069,11 +3069,11 @@ static bool ieee80211_amsdu_prepare_head
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr;
|
||||
- struct ethhdr amsdu_hdr;
|
||||
+ struct ethhdr *amsdu_hdr;
|
||||
int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
|
||||
int subframe_len = skb->len - hdr_len;
|
||||
void *data;
|
||||
- u8 *qc;
|
||||
+ u8 *qc, *h_80211_src, *h_80211_dst;
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
|
||||
return false;
|
||||
@@ -3081,19 +3081,22 @@ static bool ieee80211_amsdu_prepare_head
|
||||
if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
|
||||
return true;
|
||||
|
||||
- if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(amsdu_hdr),
|
||||
+ if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr),
|
||||
&subframe_len))
|
||||
return false;
|
||||
|
||||
- amsdu_hdr.h_proto = cpu_to_be16(subframe_len);
|
||||
- memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN);
|
||||
- memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN);
|
||||
-
|
||||
- data = skb_push(skb, sizeof(amsdu_hdr));
|
||||
- memmove(data, data + sizeof(amsdu_hdr), hdr_len);
|
||||
- memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr));
|
||||
-
|
||||
+ data = skb_push(skb, sizeof(*amsdu_hdr));
|
||||
+ memmove(data, data + sizeof(*amsdu_hdr), hdr_len);
|
||||
hdr = data;
|
||||
+ amsdu_hdr = data + hdr_len;
|
||||
+ /* h_80211_src/dst is addr* field within hdr */
|
||||
+ h_80211_src = data + fast_tx->sa_offs;
|
||||
+ h_80211_dst = data + fast_tx->da_offs;
|
||||
+
|
||||
+ amsdu_hdr->h_proto = cpu_to_be16(subframe_len);
|
||||
+ ether_addr_copy(amsdu_hdr->h_source, h_80211_src);
|
||||
+ ether_addr_copy(amsdu_hdr->h_dest, h_80211_dst);
|
||||
+
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
*qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
From: Michael Braun <michael-dev@fami-braun.de>
|
||||
Date: Sat, 15 Oct 2016 13:28:19 +0200
|
||||
Subject: [PATCH] mac80211: fix A-MSDU outer SA/DA
|
||||
|
||||
According to IEEE 802.11-2012 section 8.3.2 table 8-19, the outer SA/DA
|
||||
of A-MSDU frames need to be changed depending on FromDS/ToDS values.
|
||||
|
||||
Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
|
||||
[use ether_addr_copy and add alignment annotations]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -1438,7 +1438,7 @@ enum ieee80211_vif_flags {
|
||||
struct ieee80211_vif {
|
||||
enum nl80211_iftype type;
|
||||
struct ieee80211_bss_conf bss_conf;
|
||||
- u8 addr[ETH_ALEN];
|
||||
+ u8 addr[ETH_ALEN] __aligned(2);
|
||||
bool p2p;
|
||||
bool csa_active;
|
||||
bool mu_mimo_owner;
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -443,7 +443,7 @@ struct ieee80211_if_managed {
|
||||
struct ieee80211_mgd_auth_data *auth_data;
|
||||
struct ieee80211_mgd_assoc_data *assoc_data;
|
||||
|
||||
- u8 bssid[ETH_ALEN];
|
||||
+ u8 bssid[ETH_ALEN] __aligned(2);
|
||||
|
||||
u16 aid;
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3074,6 +3074,7 @@ static bool ieee80211_amsdu_prepare_head
|
||||
int subframe_len = skb->len - hdr_len;
|
||||
void *data;
|
||||
u8 *qc, *h_80211_src, *h_80211_dst;
|
||||
+ const u8 *bssid;
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
|
||||
return false;
|
||||
@@ -3097,6 +3098,28 @@ static bool ieee80211_amsdu_prepare_head
|
||||
ether_addr_copy(amsdu_hdr->h_source, h_80211_src);
|
||||
ether_addr_copy(amsdu_hdr->h_dest, h_80211_dst);
|
||||
|
||||
+ /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA
|
||||
+ * fields needs to be changed to BSSID for A-MSDU frames depending
|
||||
+ * on FromDS/ToDS values.
|
||||
+ */
|
||||
+ switch (sdata->vif.type) {
|
||||
+ case NL80211_IFTYPE_STATION:
|
||||
+ bssid = sdata->u.mgd.bssid;
|
||||
+ break;
|
||||
+ case NL80211_IFTYPE_AP:
|
||||
+ case NL80211_IFTYPE_AP_VLAN:
|
||||
+ bssid = sdata->vif.addr;
|
||||
+ break;
|
||||
+ default:
|
||||
+ bssid = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (bssid && ieee80211_has_fromds(hdr->frame_control))
|
||||
+ ether_addr_copy(h_80211_src, bssid);
|
||||
+
|
||||
+ if (bssid && ieee80211_has_tods(hdr->frame_control))
|
||||
+ ether_addr_copy(h_80211_dst, bssid);
|
||||
+
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
*qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 3 Nov 2016 12:10:34 +0100
|
||||
Subject: [PATCH] Revert "mac80211: allow using AP_LINK_PS with
|
||||
mac80211-generated TIM IE"
|
||||
|
||||
This reverts commit c68df2e7be0c1238ea3c281fd744a204ef3b15a0.
|
||||
|
||||
__sta_info_recalc_tim turns into a no-op if local->ops->set_tim is not
|
||||
set. This prevents the beacon TIM bit from being set for all drivers
|
||||
that do not implement this op (almost all of them), thus thoroughly
|
||||
essential AP mode powersave functionality.
|
||||
|
||||
Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
|
||||
Fixes: c68df2e7be0c ("mac80211: allow using AP_LINK_PS with mac80211-generated TIM IE")
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/sta_info.c
|
||||
+++ b/net/mac80211/sta_info.c
|
||||
@@ -688,7 +688,7 @@ static void __sta_info_recalc_tim(struct
|
||||
}
|
||||
|
||||
/* No need to do anything if the driver does all */
|
||||
- if (!local->ops->set_tim)
|
||||
+ if (ieee80211_hw_check(&local->hw, AP_LINK_PS))
|
||||
return;
|
||||
|
||||
if (sta->dead)
|
|
@ -1,30 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Fri, 4 Nov 2016 10:13:34 +0100
|
||||
Subject: [PATCH] mac80211: update A-MPDU flag on tx dequeue
|
||||
|
||||
The sequence number counter is used to derive the starting sequence
|
||||
number. Since that counter is updated on tx dequeue, the A-MPDU flag
|
||||
needs to be up to date at the tme of dequeue as well.
|
||||
|
||||
This patch prevents sending more A-MPDU frames after the session has
|
||||
been terminated and also ensures that aggregation starts right after the
|
||||
session has been established
|
||||
|
||||
Fixes: bb42f2d13ffc ("mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue")
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3462,6 +3462,11 @@ begin:
|
||||
goto begin;
|
||||
}
|
||||
|
||||
+ if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
|
||||
+ info->flags |= IEEE80211_TX_CTL_AMPDU;
|
||||
+ else
|
||||
+ info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
+
|
||||
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
|
||||
struct sta_info *sta = container_of(txq->sta, struct sta_info,
|
||||
sta);
|
|
@ -1,29 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Fri, 4 Nov 2016 10:17:38 +0100
|
||||
Subject: [PATCH] mac80211: remove bogus skb vif assignment
|
||||
|
||||
The call to ieee80211_txq_enqueue overwrites the vif pointer with the
|
||||
codel enqueue time, so setting it just before that call makes no sense.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1500,7 +1500,6 @@ static bool ieee80211_queue_skb(struct i
|
||||
struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct fq *fq = &local->fq;
|
||||
struct ieee80211_vif *vif;
|
||||
struct txq_info *txqi;
|
||||
@@ -1525,8 +1524,6 @@ static bool ieee80211_queue_skb(struct i
|
||||
if (!txqi)
|
||||
return false;
|
||||
|
||||
- info->control.vif = vif;
|
||||
-
|
||||
spin_lock_bh(&fq->lock);
|
||||
ieee80211_txq_enqueue(local, txqi, skb);
|
||||
spin_unlock_bh(&fq->lock);
|
|
@ -1,34 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Fri, 4 Nov 2016 10:18:51 +0100
|
||||
Subject: [PATCH] mac80211: fix A-MSDU aggregation with fast-xmit + txq
|
||||
|
||||
A-MSDU aggregation alters the QoS header after a frame has been
|
||||
enqueued, so it needs to be ready before enqueue and not overwritten
|
||||
again afterwards
|
||||
|
||||
Fixes: bb42f2d13ffc ("mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue")
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3245,7 +3245,6 @@ static void ieee80211_xmit_fast_finish(s
|
||||
|
||||
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
- *ieee80211_get_qos_ctl(hdr) = tid;
|
||||
hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
|
||||
} else {
|
||||
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
|
||||
@@ -3370,6 +3369,11 @@ static bool ieee80211_xmit_fast(struct i
|
||||
(tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
|
||||
info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
|
||||
|
||||
+ if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
|
||||
+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
+ *ieee80211_get_qos_ctl(hdr) = tid;
|
||||
+ }
|
||||
+
|
||||
__skb_queue_head_init(&tx.skbs);
|
||||
|
||||
tx.flags = IEEE80211_TX_UNICAST;
|
|
@ -1,29 +0,0 @@
|
|||
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Date: Tue, 15 Nov 2016 16:08:29 +0100
|
||||
Subject: [PATCH] ath9k: fix ath9k_hw_gpio_get() to return 0 or 1 on success
|
||||
|
||||
Commit b2d70d4944c1 ("ath9k: make GPIO API to support both of WMAC and
|
||||
SOC") refactored ath9k_hw_gpio_get() to support both WMAC and SOC GPIOs,
|
||||
changing the return on success from 1 to BIT(gpio). This broke some callers
|
||||
like ath_is_rfkill_set().
|
||||
|
||||
Instead of fixing all callers, change ath9k_hw_gpio_get() back to only
|
||||
return 0 or 1.
|
||||
|
||||
Fixes: b2d70d4944c1 ("ath9k: make GPIO API to support both of WMAC and SOC")
|
||||
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
---
|
||||
drivers/net/wireless/ath/ath9k/hw.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -2813,7 +2813,7 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah,
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
- return val;
|
||||
+ return !!val;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_gpio_get);
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
From b263e0bb9d4585ca3ec04d7257ca5308d21333bb Mon Sep 17 00:00:00 2001
|
||||
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
Date: Sun, 16 Oct 2016 22:59:05 +0200
|
||||
Subject: [PATCH 1/3] Documentation: dt: net: add ath9k wireless device binding
|
||||
|
||||
Add documentation how devicetree can be used to configure ath9k based
|
||||
devices.
|
||||
|
||||
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
Acked-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||
---
|
||||
.../devicetree/bindings/net/wireless/qca,ath9k.txt | 48 ++++++++++++++++++++++
|
||||
1 file changed, 48 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
|
||||
@@ -0,0 +1,48 @@
|
||||
+* Qualcomm Atheros ath9k wireless devices
|
||||
+
|
||||
+This node provides properties for configuring the ath9k wireless device. The
|
||||
+node is expected to be specified as a child node of the PCI controller to
|
||||
+which the wireless chip is connected.
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible: For PCI and PCIe devices this should be an identifier following
|
||||
+ the format as defined in "PCI Bus Binding to Open Firmware"
|
||||
+ Revision 2.1. One of the possible formats is "pciVVVV,DDDD"
|
||||
+ where VVVV is the PCI vendor ID and DDDD is PCI device ID.
|
||||
+ Typically QCA's PCI vendor ID 168c is used while the PCI device
|
||||
+ ID depends on the chipset - see the following (possibly
|
||||
+ incomplete) list:
|
||||
+ - 0023 for AR5416
|
||||
+ - 0024 for AR5418
|
||||
+ - 0027 for AR9160
|
||||
+ - 0029 for AR9220 and AR9223
|
||||
+ - 002a for AR9280 and AR9283
|
||||
+ - 002b for AR9285
|
||||
+ - 002c for AR2427
|
||||
+ - 002d for AR9227
|
||||
+ - 002e for AR9287
|
||||
+ - 0030 for AR9380, AR9381 and AR9382
|
||||
+ - 0032 for AR9485
|
||||
+ - 0033 for AR9580 and AR9590
|
||||
+ - 0034 for AR9462
|
||||
+ - 0036 for AR9565
|
||||
+ - 0037 for AR9485
|
||||
+- reg: Address and length of the register set for the device.
|
||||
+
|
||||
+Optional properties:
|
||||
+- qca,no-eeprom: Indicates that there is no physical EEPROM connected to the
|
||||
+ ath9k wireless chip (in this case the calibration /
|
||||
+ EEPROM data will be loaded from userspace using the
|
||||
+ kernel firmware loader).
|
||||
+- mac-address: See ethernet.txt in the parent directory
|
||||
+- local-mac-address: See ethernet.txt in the parent directory
|
||||
+
|
||||
+
|
||||
+In this example, the node is defined as child node of the PCI controller:
|
||||
+&pci0 {
|
||||
+ wifi@168c,002d {
|
||||
+ compatible = "pci168c,002d";
|
||||
+ reg = <0x7000 0 0 0 0x1000>;
|
||||
+ qca,no-eeprom;
|
||||
+ };
|
||||
+};
|
|
@ -1,42 +0,0 @@
|
|||
From 25b8b2d57def4854558c135228a52326a7d346ad Mon Sep 17 00:00:00 2001
|
||||
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
Date: Sun, 16 Oct 2016 22:59:06 +0200
|
||||
Subject: [PATCH 2/3] ath9k: add a helper to get the string representation of
|
||||
ath_bus_type
|
||||
|
||||
This can be used when the ath_bus_type has to be presented in a log
|
||||
message or firmware filename.
|
||||
|
||||
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||
---
|
||||
drivers/net/wireless/ath/ath.h | 6 ++++++
|
||||
drivers/net/wireless/ath/main.c | 7 +++++++
|
||||
2 files changed, 13 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath.h
|
||||
+++ b/drivers/net/wireless/ath/ath.h
|
||||
@@ -327,4 +327,10 @@ static inline const char *ath_opmode_to_
|
||||
}
|
||||
#endif
|
||||
|
||||
+extern const char *ath_bus_type_strings[];
|
||||
+static inline const char *ath_bus_type_to_string(enum ath_bus_type bustype)
|
||||
+{
|
||||
+ return ath_bus_type_strings[bustype];
|
||||
+}
|
||||
+
|
||||
#endif /* ATH_H */
|
||||
--- a/drivers/net/wireless/ath/main.c
|
||||
+++ b/drivers/net/wireless/ath/main.c
|
||||
@@ -90,3 +90,10 @@ void ath_printk(const char *level, const
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(ath_printk);
|
||||
+
|
||||
+const char *ath_bus_type_strings[] = {
|
||||
+ [ATH_PCI] = "pci",
|
||||
+ [ATH_AHB] = "ahb",
|
||||
+ [ATH_USB] = "usb",
|
||||
+};
|
||||
+EXPORT_SYMBOL(ath_bus_type_strings);
|
|
@ -1,85 +0,0 @@
|
|||
From cea03be5a848823cb8052e2e7b93cb2249d5f60c Mon Sep 17 00:00:00 2001
|
||||
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
Date: Sun, 16 Oct 2016 22:59:07 +0200
|
||||
Subject: [PATCH 3/3] ath9k: parse the device configuration from an OF node
|
||||
|
||||
This allows setting the MAC address and specifying that the firmware
|
||||
will be requested from userspace (because there might not be a hardware
|
||||
EEPROM connected to the chip) for ath9k based PCI devices using
|
||||
the device tree.
|
||||
|
||||
There is some out-of-tree code to "convert devicetree to
|
||||
ath9k_platform_data" (for example in OpenWrt and LEDE) which becomes
|
||||
obsolete with this patch.
|
||||
|
||||
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||
---
|
||||
drivers/net/wireless/ath/ath9k/init.c | 42 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 42 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ath9k_platform.h>
|
||||
#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_net.h>
|
||||
#include <linux/relay.h>
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
|
||||
@@ -554,6 +556,42 @@ static int ath9k_init_platform(struct at
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int ath9k_of_init(struct ath_softc *sc)
|
||||
+{
|
||||
+ struct device_node *np = sc->dev->of_node;
|
||||
+ struct ath_hw *ah = sc->sc_ah;
|
||||
+ struct ath_common *common = ath9k_hw_common(ah);
|
||||
+ enum ath_bus_type bus_type = common->bus_ops->ath_bus_type;
|
||||
+ const char *mac;
|
||||
+ char eeprom_name[100];
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!of_device_is_available(np))
|
||||
+ return 0;
|
||||
+
|
||||
+ ath_dbg(common, CONFIG, "parsing configuration from OF node\n");
|
||||
+
|
||||
+ if (of_property_read_bool(np, "qca,no-eeprom")) {
|
||||
+ /* ath9k-eeprom-<bus>-<id>.bin */
|
||||
+ scnprintf(eeprom_name, sizeof(eeprom_name),
|
||||
+ "ath9k-eeprom-%s-%s.bin",
|
||||
+ ath_bus_type_to_string(bus_type), dev_name(ah->dev));
|
||||
+
|
||||
+ ret = ath9k_eeprom_request(sc, eeprom_name);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ mac = of_get_mac_address(np);
|
||||
+ if (mac)
|
||||
+ ether_addr_copy(common->macaddr, mac);
|
||||
+
|
||||
+ ah->ah_flags &= ~AH_USE_EEPROM;
|
||||
+ ah->ah_flags |= AH_NO_EEP_SWAP;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
@@ -610,6 +648,10 @@ static int ath9k_init_softc(u16 devid, s
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ ret = ath9k_of_init(sc);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
if (ath9k_led_active_high != -1)
|
||||
ah->config.led_active_high = ath9k_led_active_high == 1;
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
From: Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de>
|
||||
Date: Mon, 12 Dec 2016 19:50:01 +0100
|
||||
Subject: [PATCH] ath9k: unlock rcu read when returning early
|
||||
|
||||
Starting with ath9k: use ieee80211_tx_status_noskb where possible
|
||||
[d94a461d7a7df68991fb9663531173f60ef89c68] the driver uses rcu_read_lock() &&
|
||||
rcu_read_unlock() yet on returning early in ath_tx_edma_tasklet() the unlock is
|
||||
missing leading to stalls and suspicious RCU usage:
|
||||
|
||||
===============================
|
||||
[ INFO: suspicious RCU usage. ]
|
||||
4.9.0-rc8 #11 Not tainted
|
||||
-------------------------------
|
||||
kernel/rcu/tree.c:705 Illegal idle entry in RCU read-side critical section.!
|
||||
|
||||
other info that might help us debug this:
|
||||
|
||||
RCU used illegally from idle CPU!
|
||||
rcu_scheduler_active = 1, debug_locks = 0
|
||||
RCU used illegally from extended quiescent state!
|
||||
1 lock held by swapper/7/0:
|
||||
#0:
|
||||
(
|
||||
rcu_read_lock
|
||||
){......}
|
||||
, at:
|
||||
[<ffffffffa06ed110>] ath_tx_edma_tasklet+0x0/0x450 [ath9k]
|
||||
|
||||
stack backtrace:
|
||||
CPU: 7 PID: 0 Comm: swapper/7 Not tainted 4.9.0-rc8 #11
|
||||
Hardware name: Acer Aspire V3-571G/VA50_HC_CR, BIOS V2.21 12/16/2013
|
||||
ffff88025efc3f38 ffffffff8132b1e5 ffff88017ede4540 0000000000000001
|
||||
ffff88025efc3f68 ffffffff810a25f7 ffff88025efcee60 ffff88017edebdd8
|
||||
ffff88025eeb5400 0000000000000091 ffff88025efc3f88 ffffffff810c3cd4
|
||||
Call Trace:
|
||||
<IRQ>
|
||||
[<ffffffff8132b1e5>] dump_stack+0x68/0x93
|
||||
[<ffffffff810a25f7>] lockdep_rcu_suspicious+0xd7/0x110
|
||||
[<ffffffff810c3cd4>] rcu_eqs_enter_common.constprop.85+0x154/0x200
|
||||
[<ffffffff810c5a54>] rcu_irq_exit+0x44/0xa0
|
||||
[<ffffffff81058631>] irq_exit+0x61/0xd0
|
||||
[<ffffffff81018d25>] do_IRQ+0x65/0x110
|
||||
[<ffffffff81672189>] common_interrupt+0x89/0x89
|
||||
<EOI>
|
||||
[<ffffffff814ffe11>] ? cpuidle_enter_state+0x151/0x200
|
||||
[<ffffffff814ffee2>] cpuidle_enter+0x12/0x20
|
||||
[<ffffffff8109a6ae>] call_cpuidle+0x1e/0x40
|
||||
[<ffffffff8109a8f6>] cpu_startup_entry+0x146/0x220
|
||||
[<ffffffff810336f8>] start_secondary+0x148/0x170
|
||||
|
||||
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -2757,7 +2757,7 @@ void ath_tx_edma_tasklet(struct ath_soft
|
||||
fifo_list = &txq->txq_fifo[txq->txq_tailidx];
|
||||
if (list_empty(fifo_list)) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
- return;
|
||||
+ break;
|
||||
}
|
||||
|
||||
bf = list_first_entry(fifo_list, struct ath_buf, list);
|
|
@ -1,27 +0,0 @@
|
|||
From: Ben Greear <greearb@candelatech.com>
|
||||
Date: Tue, 29 Nov 2016 14:00:28 -0800
|
||||
Subject: [PATCH] ath10k: wmi-alloc-chunk should use DMA_BIDIRECTIONAL.
|
||||
|
||||
These memory chunks are often used as 'swap' by the NIC,
|
||||
so it will be both reading and writing to these areas.
|
||||
|
||||
This seems to fix errors like this on my x86-64 machine:
|
||||
|
||||
kernel: DMAR: DMAR:[DMA Write] Request device [05:00.0] fault addr ff5de000
|
||||
DMAR:[fault reason 05] PTE Write access is not set
|
||||
|
||||
Tested-by: Marek Behun <kabel@blackhole.sk>
|
||||
Signed-off-by: Ben Greear <greearb@candelatech.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
|
||||
@@ -4495,7 +4495,7 @@ static int ath10k_wmi_alloc_chunk(struct
|
||||
if (!num_units)
|
||||
return -ENOMEM;
|
||||
|
||||
- paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_TO_DEVICE);
|
||||
+ paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(ar->dev, paddr)) {
|
||||
kfree(vaddr);
|
||||
return -ENOMEM;
|
|
@ -1,81 +0,0 @@
|
|||
From: Ben Greear <greearb@candelatech.com>
|
||||
Date: Mon, 5 Dec 2016 10:28:39 -0800
|
||||
Subject: [PATCH] ath10k: free host-mem with DMA_BIRECTIONAL flag.
|
||||
|
||||
Hopefully this fixes the problem reported by Kalle:
|
||||
|
||||
Noticed this in my log, but I don't have time to investigate this in
|
||||
detail right now:
|
||||
|
||||
[ 413.795346] IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready
|
||||
[ 414.158755] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
|
||||
[ 477.439659] ath10k_pci 0000:02:00.0: could not get mac80211 beacon
|
||||
[ 481.666630] ------------[ cut here ]------------
|
||||
[ 481.666669] WARNING: CPU: 0 PID: 1978 at lib/dma-debug.c:1155 check_unmap+0x320/0x8e0
|
||||
[ 481.666688] ath10k_pci 0000:02:00.0: DMA-API: device driver frees DMA memory with different direction [device address=0x000000002d130000] [size=63800 bytes] [mapped with DMA_BIDIRECTIONAL] [unmapped with DMA_TO_DEVICE]
|
||||
[ 481.666703] Modules linked in: ctr ccm ath10k_pci(E-) ath10k_core(E) ath(E) mac80211(E) cfg80211(E) snd_hda_codec_hdmi snd_hda_codec_idt snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm snd_seq_midi arc4 snd_rawmidi snd_seq_midi_event snd_seq btusb btintel snd_seq_device joydev coret
|
||||
[ 481.671468] CPU: 0 PID: 1978 Comm: rmmod Tainted: G E 4.9.0-rc7-wt+ #54
|
||||
[ 481.671478] Hardware name: Hewlett-Packard HP ProBook 6540b/1722, BIOS 68CDD Ver. F.04 01/27/2010
|
||||
[ 481.671489] ef49dcec c842ee92 c8b5830e ef49dd34 ef49dd20 c80850f5 c8b5a13c ef49dd50
|
||||
[ 481.671560] 000007ba c8b5830e 00000483 c8461830 c8461830 00000483 ef49ddcc f34e64b8
|
||||
[ 481.671641] c8b58360 ef49dd3c c80851bb 00000009 00000000 ef49dd34 c8b5a13c ef49dd50
|
||||
[ 481.671716] Call Trace:
|
||||
[ 481.671731] [<c842ee92>] dump_stack+0x76/0xb4
|
||||
[ 481.671745] [<c80850f5>] __warn+0xe5/0x100
|
||||
[ 481.671757] [<c8461830>] ? check_unmap+0x320/0x8e0
|
||||
[ 481.671769] [<c8461830>] ? check_unmap+0x320/0x8e0
|
||||
[ 481.671780] [<c80851bb>] warn_slowpath_fmt+0x3b/0x40
|
||||
[ 481.671791] [<c8461830>] check_unmap+0x320/0x8e0
|
||||
[ 481.671804] [<c8462054>] debug_dma_unmap_page+0x84/0xa0
|
||||
[ 481.671835] [<f937cd7a>] ath10k_wmi_free_host_mem+0x9a/0xe0 [ath10k_core]
|
||||
[ 481.671861] [<f9363400>] ath10k_core_destroy+0x50/0x60 [ath10k_core]
|
||||
[ 481.671875] [<f8e13969>] ath10k_pci_remove+0x79/0xa0 [ath10k_pci]
|
||||
[ 481.671889] [<c848d8d8>] pci_device_remove+0x38/0xb0
|
||||
[ 481.671901] [<c859fe4b>] __device_release_driver+0x7b/0x110
|
||||
[ 481.671913] [<c85a00e7>] driver_detach+0x97/0xa0
|
||||
[ 481.671923] [<c859ef8b>] bus_remove_driver+0x4b/0xb0
|
||||
[ 481.671934] [<c85a0cda>] driver_unregister+0x2a/0x60
|
||||
[ 481.671949] [<c848c888>] pci_unregister_driver+0x18/0x70
|
||||
[ 481.671965] [<f8e14dae>] ath10k_pci_exit+0xd/0x25f [ath10k_pci]
|
||||
[ 481.671979] [<c812bb84>] SyS_delete_module+0xf4/0x180
|
||||
[ 481.671995] [<c81f801b>] ? __might_fault+0x8b/0xa0
|
||||
[ 481.672009] [<c80037d0>] do_fast_syscall_32+0xa0/0x1e0
|
||||
[ 481.672025] [<c88d4c88>] sysenter_past_esp+0x45/0x74
|
||||
[ 481.672037] ---[ end trace 3fd23759e17e1622 ]---
|
||||
[ 481.672049] Mapped at:
|
||||
[ 481.672060] [ 481.672072] [<c846062c>] debug_dma_map_page.part.25+0x1c/0xf0
|
||||
[ 481.672083] [ 481.672095] [<c8460799>] debug_dma_map_page+0x99/0xc0
|
||||
[ 481.672106] [ 481.672132] [<f93745ec>] ath10k_wmi_alloc_chunk+0x12c/0x1f0 [ath10k_core]
|
||||
[ 481.672142] [ 481.672168] [<f937d0c4>] ath10k_wmi_event_service_ready_work+0x304/0x540 [ath10k_core]
|
||||
[ 481.672178] [ 481.672190] [<c80a3643>] process_one_work+0x1c3/0x670
|
||||
[ 482.137134] ath10k_pci 0000:02:00.0: pci irq msi oper_irq_mode 2 irq_mode 0 reset_mode 0
|
||||
[ 482.313144] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/pre-cal-pci-0000:02:00.0.bin failed with error -2
|
||||
[ 482.313274] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/cal-pci-0000:02:00.0.bin failed with error -2
|
||||
[ 482.313768] ath10k_pci 0000:02:00.0: qca988x hw2.0 target 0x4100016c chip_id 0x043202ff sub 0000:0000
|
||||
[ 482.313777] ath10k_pci 0000:02:00.0: kconfig debug 1 debugfs 1 tracing 1 dfs 0 testmode 1
|
||||
[ 482.313974] ath10k_pci 0000:02:00.0: firmware ver 10.2.4.70.59-2 api 5 features no-p2p,raw-mode,mfp,allows-mesh-bcast crc32 4159f498
|
||||
[ 482.369858] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/QCA988X/hw2.0/board-2.bin failed with error -2
|
||||
[ 482.370011] ath10k_pci 0000:02:00.0: board_file api 1 bmi_id N/A crc32 bebc7c08
|
||||
[ 483.596770] ath10k_pci 0000:02:00.0: htt-ver 2.1 wmi-op 5 htt-op 2 cal otp max-sta 128 raw 0 hwcrypto 1
|
||||
[ 483.701686] ath: EEPROM regdomain: 0x0
|
||||
[ 483.701706] ath: EEPROM indicates default country code should be used
|
||||
[ 483.701713] ath: doing EEPROM country->regdmn map search
|
||||
[ 483.701721] ath: country maps to regdmn code: 0x3a
|
||||
[ 483.701730] ath: Country alpha2 being used: US
|
||||
[ 483.701737] ath: Regpair used: 0x3a
|
||||
|
||||
Reported-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||
Signed-off-by: Ben Greear <greearb@candelatech.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
|
||||
@@ -8227,7 +8227,7 @@ void ath10k_wmi_free_host_mem(struct ath
|
||||
dma_unmap_single(ar->dev,
|
||||
ar->wmi.mem_chunks[i].paddr,
|
||||
ar->wmi.mem_chunks[i].len,
|
||||
- DMA_TO_DEVICE);
|
||||
+ DMA_BIDIRECTIONAL);
|
||||
kfree(ar->wmi.mem_chunks[i].vaddr);
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
From: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
|
||||
Date: Wed, 12 Oct 2016 12:59:02 +0530
|
||||
Subject: [PATCH] ath10k: Fix failure to send NULL func frame for 10.4
|
||||
|
||||
This partially reverts 'commit 2cdce425aa33
|
||||
("ath10k: Fix broken NULL func data frame status for 10.4")'
|
||||
Unfortunately this breaks sending NULL func and the existing
|
||||
issue of obtaining proper tx status for NULL function will be
|
||||
fixed. Also update the comments for feature flag added to be
|
||||
useless and not working
|
||||
|
||||
Fixes: 2cdce425aa33 "ath10k: Fix broken NULL func data frame status for
|
||||
10.4"
|
||||
Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.h
|
||||
@@ -556,10 +556,8 @@ enum ath10k_fw_features {
|
||||
*/
|
||||
ATH10K_FW_FEATURE_BTCOEX_PARAM = 14,
|
||||
|
||||
- /* Older firmware with HTT delivers incorrect tx status for null func
|
||||
- * frames to driver, but this fixed in 10.2 and 10.4 firmware versions.
|
||||
- * Also this workaround results in reporting of incorrect null func
|
||||
- * status for 10.4. This flag is used to skip the workaround.
|
||||
+ /* Unused flag and proven to be not working, enable this if you want
|
||||
+ * to experiment sending NULL func data frames in HTT TX
|
||||
*/
|
||||
ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15,
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||
@@ -3274,8 +3274,6 @@ ath10k_mac_tx_h_get_txmode(struct ath10k
|
||||
if (ar->htt.target_version_major < 3 &&
|
||||
(ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) &&
|
||||
!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
|
||||
- ar->running_fw->fw_file.fw_features) &&
|
||||
- !test_bit(ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return ATH10K_HW_TXRX_MGMT;
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
From: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
|
||||
Date: Wed, 30 Nov 2016 10:59:29 +0530
|
||||
Subject: [PATCH] ath10k: Fix soft lockup during firmware crash/hw-restart
|
||||
|
||||
During firmware crash (or) user requested manual restart
|
||||
the system gets into a soft lock up state because of the
|
||||
below root cause.
|
||||
|
||||
During user requested hardware restart / firmware crash
|
||||
the system goes into a soft lockup state as 'napi_synchronize'
|
||||
is called after 'napi_disable' (which sets 'NAPI_STATE_SCHED'
|
||||
bit) and it sleeps into infinite loop as it waits for
|
||||
'NAPI_STATE_SCHED' to be cleared. This condition is hit because
|
||||
'ath10k_hif_stop' is called twice as below (resulting in calling
|
||||
'napi_synchronize' after 'napi_disable')
|
||||
|
||||
'ath10k_core_restart' -> 'ath10k_hif_stop' (ATH10K_STATE_ON) ->
|
||||
-> 'ieee80211_restart_hw' -> 'ath10k_start' -> 'ath10k_halt' ->
|
||||
'ath10k_core_stop' -> 'ath10k_hif_stop' (ATH10K_STATE_RESTARTING)
|
||||
|
||||
Fix this by calling 'ath10k_halt' in ath10k_core_restart itself
|
||||
as it makes more sense before informing mac80211 to restart h/w
|
||||
Also remove 'ath10k_halt' in ath10k_start for the state of 'restarting'
|
||||
|
||||
Fixes: 3c97f5de1f28 ("ath10k: implement NAPI support")
|
||||
Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
||||
@@ -1534,7 +1534,7 @@ static void ath10k_core_restart(struct w
|
||||
switch (ar->state) {
|
||||
case ATH10K_STATE_ON:
|
||||
ar->state = ATH10K_STATE_RESTARTING;
|
||||
- ath10k_hif_stop(ar);
|
||||
+ ath10k_halt(ar);
|
||||
ath10k_scan_finish(ar);
|
||||
ieee80211_restart_hw(ar->hw);
|
||||
break;
|
||||
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
||||
@@ -4470,7 +4470,6 @@ static int ath10k_start(struct ieee80211
|
||||
ar->state = ATH10K_STATE_ON;
|
||||
break;
|
||||
case ATH10K_STATE_RESTARTING:
|
||||
- ath10k_halt(ar);
|
||||
ar->state = ATH10K_STATE_RESTARTED;
|
||||
break;
|
||||
case ATH10K_STATE_ON:
|
|
@ -1,196 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 14 Dec 2016 19:33:23 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: move supported bitrate mask out of
|
||||
group data
|
||||
|
||||
Improves dcache footprint by ensuring that fewer cache lines need to be
|
||||
touched.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -301,7 +301,7 @@ minstrel_ht_get_stats(struct minstrel_pr
|
||||
break;
|
||||
|
||||
/* short preamble */
|
||||
- if (!(mi->groups[group].supported & BIT(idx)))
|
||||
+ if (!(mi->supported[group] & BIT(idx)))
|
||||
idx += 4;
|
||||
}
|
||||
return &mi->groups[group].rates[idx];
|
||||
@@ -486,7 +486,7 @@ minstrel_ht_prob_rate_reduce_streams(str
|
||||
MCS_GROUP_RATES].streams;
|
||||
for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
|
||||
mg = &mi->groups[group];
|
||||
- if (!mg->supported || group == MINSTREL_CCK_GROUP)
|
||||
+ if (!mi->supported[group] || group == MINSTREL_CCK_GROUP)
|
||||
continue;
|
||||
|
||||
tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
|
||||
@@ -540,7 +540,7 @@ minstrel_ht_update_stats(struct minstrel
|
||||
for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
|
||||
|
||||
mg = &mi->groups[group];
|
||||
- if (!mg->supported)
|
||||
+ if (!mi->supported[group])
|
||||
continue;
|
||||
|
||||
mi->sample_count++;
|
||||
@@ -550,7 +550,7 @@ minstrel_ht_update_stats(struct minstrel
|
||||
tmp_group_tp_rate[j] = group;
|
||||
|
||||
for (i = 0; i < MCS_GROUP_RATES; i++) {
|
||||
- if (!(mg->supported & BIT(i)))
|
||||
+ if (!(mi->supported[group] & BIT(i)))
|
||||
continue;
|
||||
|
||||
index = MCS_GROUP_RATES * group + i;
|
||||
@@ -636,7 +636,7 @@ minstrel_set_next_sample_idx(struct mins
|
||||
mi->sample_group %= ARRAY_SIZE(minstrel_mcs_groups);
|
||||
mg = &mi->groups[mi->sample_group];
|
||||
|
||||
- if (!mg->supported)
|
||||
+ if (!mi->supported[mi->sample_group])
|
||||
continue;
|
||||
|
||||
if (++mg->index >= MCS_GROUP_RATES) {
|
||||
@@ -657,7 +657,7 @@ minstrel_downgrade_rate(struct minstrel_
|
||||
while (group > 0) {
|
||||
group--;
|
||||
|
||||
- if (!mi->groups[group].supported)
|
||||
+ if (!mi->supported[group])
|
||||
continue;
|
||||
|
||||
if (minstrel_mcs_groups[group].streams >
|
||||
@@ -994,7 +994,7 @@ minstrel_get_sample_rate(struct minstrel
|
||||
sample_idx = sample_table[mg->column][mg->index];
|
||||
minstrel_set_next_sample_idx(mi);
|
||||
|
||||
- if (!(mg->supported & BIT(sample_idx)))
|
||||
+ if (!(mi->supported[sample_group] & BIT(sample_idx)))
|
||||
return -1;
|
||||
|
||||
mrs = &mg->rates[sample_idx];
|
||||
@@ -1052,7 +1052,7 @@ static void
|
||||
minstrel_ht_check_cck_shortpreamble(struct minstrel_priv *mp,
|
||||
struct minstrel_ht_sta *mi, bool val)
|
||||
{
|
||||
- u8 supported = mi->groups[MINSTREL_CCK_GROUP].supported;
|
||||
+ u8 supported = mi->supported[MINSTREL_CCK_GROUP];
|
||||
|
||||
if (!supported || !mi->cck_supported_short)
|
||||
return;
|
||||
@@ -1061,7 +1061,7 @@ minstrel_ht_check_cck_shortpreamble(stru
|
||||
return;
|
||||
|
||||
supported ^= mi->cck_supported_short | (mi->cck_supported_short << 4);
|
||||
- mi->groups[MINSTREL_CCK_GROUP].supported = supported;
|
||||
+ mi->supported[MINSTREL_CCK_GROUP] = supported;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1154,7 +1154,7 @@ minstrel_ht_update_cck(struct minstrel_p
|
||||
mi->cck_supported_short |= BIT(i);
|
||||
}
|
||||
|
||||
- mi->groups[MINSTREL_CCK_GROUP].supported = mi->cck_supported;
|
||||
+ mi->supported[MINSTREL_CCK_GROUP] = mi->cck_supported;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1233,7 +1233,7 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
u32 gflags = minstrel_mcs_groups[i].flags;
|
||||
int bw, nss;
|
||||
|
||||
- mi->groups[i].supported = 0;
|
||||
+ mi->supported[i] = 0;
|
||||
if (i == MINSTREL_CCK_GROUP) {
|
||||
minstrel_ht_update_cck(mp, mi, sband, sta);
|
||||
continue;
|
||||
@@ -1265,8 +1265,8 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
if (use_vht && minstrel_vht_only)
|
||||
continue;
|
||||
#endif
|
||||
- mi->groups[i].supported = mcs->rx_mask[nss - 1];
|
||||
- if (mi->groups[i].supported)
|
||||
+ mi->supported[i] = mcs->rx_mask[nss - 1];
|
||||
+ if (mi->supported[i])
|
||||
n_supported++;
|
||||
continue;
|
||||
}
|
||||
@@ -1292,10 +1292,10 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
else
|
||||
bw = BW_20;
|
||||
|
||||
- mi->groups[i].supported = minstrel_get_valid_vht_rates(bw, nss,
|
||||
+ mi->supported[i] = minstrel_get_valid_vht_rates(bw, nss,
|
||||
vht_cap->vht_mcs.tx_mcs_map);
|
||||
|
||||
- if (mi->groups[i].supported)
|
||||
+ if (mi->supported[i])
|
||||
n_supported++;
|
||||
}
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.h
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.h
|
||||
@@ -52,9 +52,6 @@ struct minstrel_mcs_group_data {
|
||||
u8 index;
|
||||
u8 column;
|
||||
|
||||
- /* bitfield of supported MCS rates of this group */
|
||||
- u16 supported;
|
||||
-
|
||||
/* sorted rate set within a MCS group*/
|
||||
u16 max_group_tp_rate[MAX_THR_RATES];
|
||||
u16 max_group_prob_rate;
|
||||
@@ -101,6 +98,9 @@ struct minstrel_ht_sta {
|
||||
u8 cck_supported;
|
||||
u8 cck_supported_short;
|
||||
|
||||
+ /* Bitfield of supported MCS rates of all groups */
|
||||
+ u16 supported[MINSTREL_GROUPS_NB];
|
||||
+
|
||||
/* MCS rate group info and statistics */
|
||||
struct minstrel_mcs_group_data groups[MINSTREL_GROUPS_NB];
|
||||
};
|
||||
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
|
||||
@@ -24,7 +24,7 @@ minstrel_ht_stats_dump(struct minstrel_h
|
||||
char gimode = 'L';
|
||||
u32 gflags;
|
||||
|
||||
- if (!mi->groups[i].supported)
|
||||
+ if (!mi->supported[i])
|
||||
return p;
|
||||
|
||||
mg = &minstrel_mcs_groups[i];
|
||||
@@ -42,7 +42,7 @@ minstrel_ht_stats_dump(struct minstrel_h
|
||||
static const int bitrates[4] = { 10, 20, 55, 110 };
|
||||
int idx = i * MCS_GROUP_RATES + j;
|
||||
|
||||
- if (!(mi->groups[i].supported & BIT(j)))
|
||||
+ if (!(mi->supported[i] & BIT(j)))
|
||||
continue;
|
||||
|
||||
if (gflags & IEEE80211_TX_RC_MCS) {
|
||||
@@ -170,7 +170,7 @@ minstrel_ht_stats_csv_dump(struct minstr
|
||||
char gimode = 'L';
|
||||
u32 gflags;
|
||||
|
||||
- if (!mi->groups[i].supported)
|
||||
+ if (!mi->supported[i])
|
||||
return p;
|
||||
|
||||
mg = &minstrel_mcs_groups[i];
|
||||
@@ -188,7 +188,7 @@ minstrel_ht_stats_csv_dump(struct minstr
|
||||
static const int bitrates[4] = { 10, 20, 55, 110 };
|
||||
int idx = i * MCS_GROUP_RATES + j;
|
||||
|
||||
- if (!(mi->groups[i].supported & BIT(j)))
|
||||
+ if (!(mi->supported[i] & BIT(j)))
|
||||
continue;
|
||||
|
||||
if (gflags & IEEE80211_TX_RC_MCS) {
|
|
@ -1,70 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 14 Dec 2016 20:06:08 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: move short preamble check out of
|
||||
get_rate
|
||||
|
||||
Test short preamble support in minstrel_ht_update_caps instead of
|
||||
looking at the per-packet flag. Makes the code more efficient.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "rate.h"
|
||||
+#include "sta_info.h"
|
||||
#include "rc80211_minstrel.h"
|
||||
#include "rc80211_minstrel_ht.h"
|
||||
|
||||
@@ -1049,22 +1050,6 @@ minstrel_get_sample_rate(struct minstrel
|
||||
}
|
||||
|
||||
static void
|
||||
-minstrel_ht_check_cck_shortpreamble(struct minstrel_priv *mp,
|
||||
- struct minstrel_ht_sta *mi, bool val)
|
||||
-{
|
||||
- u8 supported = mi->supported[MINSTREL_CCK_GROUP];
|
||||
-
|
||||
- if (!supported || !mi->cck_supported_short)
|
||||
- return;
|
||||
-
|
||||
- if (supported & (mi->cck_supported_short << (val * 4)))
|
||||
- return;
|
||||
-
|
||||
- supported ^= mi->cck_supported_short | (mi->cck_supported_short << 4);
|
||||
- mi->supported[MINSTREL_CCK_GROUP] = supported;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
||||
struct ieee80211_tx_rate_control *txrc)
|
||||
{
|
||||
@@ -1087,7 +1072,6 @@ minstrel_ht_get_rate(void *priv, struct
|
||||
minstrel_aggr_check(sta, txrc->skb);
|
||||
|
||||
info->flags |= mi->tx_flags;
|
||||
- minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble);
|
||||
|
||||
#ifdef CPTCFG_MAC80211_DEBUGFS
|
||||
if (mp->fixed_rate_idx != -1)
|
||||
@@ -1168,6 +1152,7 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
|
||||
u16 ht_cap = sta->ht_cap.cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
|
||||
+ struct sta_info *sinfo = container_of(sta, struct sta_info, sta);
|
||||
int use_vht;
|
||||
int n_supported = 0;
|
||||
int ack_dur;
|
||||
@@ -1302,6 +1287,9 @@ minstrel_ht_update_caps(void *priv, stru
|
||||
if (!n_supported)
|
||||
goto use_legacy;
|
||||
|
||||
+ if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE))
|
||||
+ mi->cck_supported_short |= mi->cck_supported_short << 4;
|
||||
+
|
||||
/* create an initial rate table with the lowest supported rates */
|
||||
minstrel_ht_update_stats(mp, mi);
|
||||
minstrel_ht_update_rates(mp, mi);
|
|
@ -1,22 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 14 Dec 2016 20:09:14 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: make att_hist and succ_hist u32
|
||||
instead of u64
|
||||
|
||||
They are only used for debugging purposes and take a very long time to
|
||||
overflow. Visibly reduces the size of the per-sta rate control data.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel.h
|
||||
+++ b/net/mac80211/rc80211_minstrel.h
|
||||
@@ -59,7 +59,7 @@ struct minstrel_rate_stats {
|
||||
u16 success, last_success;
|
||||
|
||||
/* total attempts/success counters */
|
||||
- u64 att_hist, succ_hist;
|
||||
+ u32 att_hist, succ_hist;
|
||||
|
||||
/* statistis of packet delivery probability
|
||||
* cur_prob - current prob within last update intervall
|
|
@ -1,34 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 14 Dec 2016 20:12:25 +0100
|
||||
Subject: [PATCH] mac80211: check for MCS in ieee80211_duration before fetching
|
||||
chanctx
|
||||
|
||||
Makes the code a bit more efficient
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -63,6 +63,10 @@ static __le16 ieee80211_duration(struct
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
u32 rate_flags = 0;
|
||||
|
||||
+ /* assume HW handles this */
|
||||
+ if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))
|
||||
+ return 0;
|
||||
+
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(tx->sdata->vif.chanctx_conf);
|
||||
if (chanctx_conf) {
|
||||
@@ -71,10 +75,6 @@ static __le16 ieee80211_duration(struct
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
- /* assume HW handles this */
|
||||
- if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))
|
||||
- return 0;
|
||||
-
|
||||
/* uh huh? */
|
||||
if (WARN_ON_ONCE(tx->rate.idx < 0))
|
||||
return 0;
|
|
@ -1,192 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 14 Dec 2016 20:13:58 +0100
|
||||
Subject: [PATCH] mac80211: minstrel: remove cur_prob from debugfs
|
||||
|
||||
This field is redundant, because it is simply last success divided by
|
||||
last attempt count. Removing it from the rate stats struct saves about
|
||||
1.2 KiB per HT station.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel.c
|
||||
+++ b/net/mac80211/rc80211_minstrel.c
|
||||
@@ -159,21 +159,23 @@ minstrel_update_rates(struct minstrel_pr
|
||||
void
|
||||
minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
|
||||
{
|
||||
+ unsigned int cur_prob;
|
||||
+
|
||||
if (unlikely(mrs->attempts > 0)) {
|
||||
mrs->sample_skipped = 0;
|
||||
- mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
|
||||
+ cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
|
||||
if (unlikely(!mrs->att_hist)) {
|
||||
- mrs->prob_ewma = mrs->cur_prob;
|
||||
+ mrs->prob_ewma = cur_prob;
|
||||
} else {
|
||||
/* update exponential weighted moving variance */
|
||||
mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd,
|
||||
- mrs->cur_prob,
|
||||
+ cur_prob,
|
||||
mrs->prob_ewma,
|
||||
EWMA_LEVEL);
|
||||
|
||||
/*update exponential weighted moving avarage */
|
||||
mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
|
||||
- mrs->cur_prob,
|
||||
+ cur_prob,
|
||||
EWMA_LEVEL);
|
||||
}
|
||||
mrs->att_hist += mrs->attempts;
|
||||
--- a/net/mac80211/rc80211_minstrel.h
|
||||
+++ b/net/mac80211/rc80211_minstrel.h
|
||||
@@ -62,10 +62,8 @@ struct minstrel_rate_stats {
|
||||
u32 att_hist, succ_hist;
|
||||
|
||||
/* statistis of packet delivery probability
|
||||
- * cur_prob - current prob within last update intervall
|
||||
* prob_ewma - exponential weighted moving average of prob
|
||||
* prob_ewmsd - exp. weighted moving standard deviation of prob */
|
||||
- unsigned int cur_prob;
|
||||
unsigned int prob_ewma;
|
||||
u16 prob_ewmsd;
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_debugfs.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
|
||||
@@ -75,7 +75,7 @@ minstrel_stats_open(struct inode *inode,
|
||||
{
|
||||
struct minstrel_sta_info *mi = inode->i_private;
|
||||
struct minstrel_debugfs_info *ms;
|
||||
- unsigned int i, tp_max, tp_avg, prob, eprob;
|
||||
+ unsigned int i, tp_max, tp_avg, eprob;
|
||||
char *p;
|
||||
|
||||
ms = kmalloc(2048, GFP_KERNEL);
|
||||
@@ -86,9 +86,9 @@ minstrel_stats_open(struct inode *inode,
|
||||
p = ms->buf;
|
||||
p += sprintf(p, "\n");
|
||||
p += sprintf(p,
|
||||
- "best __________rate_________ ________statistics________ ________last_______ ______sum-of________\n");
|
||||
+ "best __________rate_________ ________statistics________ ____last_____ ______sum-of________\n");
|
||||
p += sprintf(p,
|
||||
- "rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n");
|
||||
+ "rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [retry|suc|att] [#success | #attempts]\n");
|
||||
|
||||
for (i = 0; i < mi->n_rates; i++) {
|
||||
struct minstrel_rate *mr = &mi->r[i];
|
||||
@@ -107,17 +107,15 @@ minstrel_stats_open(struct inode *inode,
|
||||
|
||||
tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
|
||||
tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
|
||||
- prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
|
||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
||||
|
||||
p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
|
||||
- " %3u.%1u %3u %3u %-3u "
|
||||
+ " %3u %3u %-3u "
|
||||
"%9llu %-9llu\n",
|
||||
tp_max / 10, tp_max % 10,
|
||||
tp_avg / 10, tp_avg % 10,
|
||||
eprob / 10, eprob % 10,
|
||||
mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
|
||||
- prob / 10, prob % 10,
|
||||
mrs->retry_count,
|
||||
mrs->last_success,
|
||||
mrs->last_attempts,
|
||||
@@ -148,7 +146,7 @@ minstrel_stats_csv_open(struct inode *in
|
||||
{
|
||||
struct minstrel_sta_info *mi = inode->i_private;
|
||||
struct minstrel_debugfs_info *ms;
|
||||
- unsigned int i, tp_max, tp_avg, prob, eprob;
|
||||
+ unsigned int i, tp_max, tp_avg, eprob;
|
||||
char *p;
|
||||
|
||||
ms = kmalloc(2048, GFP_KERNEL);
|
||||
@@ -175,16 +173,14 @@ minstrel_stats_csv_open(struct inode *in
|
||||
|
||||
tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
|
||||
tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
|
||||
- prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
|
||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
||||
|
||||
- p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
|
||||
+ p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
|
||||
"%llu,%llu,%d,%d\n",
|
||||
tp_max / 10, tp_max % 10,
|
||||
tp_avg / 10, tp_avg % 10,
|
||||
eprob / 10, eprob % 10,
|
||||
mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
|
||||
- prob / 10, prob % 10,
|
||||
mrs->retry_count,
|
||||
mrs->last_success,
|
||||
mrs->last_attempts,
|
||||
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
|
||||
@@ -19,7 +19,7 @@ static char *
|
||||
minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
|
||||
{
|
||||
const struct mcs_group *mg;
|
||||
- unsigned int j, tp_max, tp_avg, prob, eprob, tx_time;
|
||||
+ unsigned int j, tp_max, tp_avg, eprob, tx_time;
|
||||
char htmode = '2';
|
||||
char gimode = 'L';
|
||||
u32 gflags;
|
||||
@@ -83,17 +83,15 @@ minstrel_ht_stats_dump(struct minstrel_h
|
||||
|
||||
tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
|
||||
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
|
||||
- prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
|
||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
||||
|
||||
p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
|
||||
- " %3u.%1u %3u %3u %-3u "
|
||||
+ " %3u %3u %-3u "
|
||||
"%9llu %-9llu\n",
|
||||
tp_max / 10, tp_max % 10,
|
||||
tp_avg / 10, tp_avg % 10,
|
||||
eprob / 10, eprob % 10,
|
||||
mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
|
||||
- prob / 10, prob % 10,
|
||||
mrs->retry_count,
|
||||
mrs->last_success,
|
||||
mrs->last_attempts,
|
||||
@@ -130,9 +128,9 @@ minstrel_ht_stats_open(struct inode *ino
|
||||
|
||||
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) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n");
|
||||
+ "mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(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++)
|
||||
@@ -165,7 +163,7 @@ static char *
|
||||
minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
|
||||
{
|
||||
const struct mcs_group *mg;
|
||||
- unsigned int j, tp_max, tp_avg, prob, eprob, tx_time;
|
||||
+ unsigned int j, tp_max, tp_avg, eprob, tx_time;
|
||||
char htmode = '2';
|
||||
char gimode = 'L';
|
||||
u32 gflags;
|
||||
@@ -226,16 +224,14 @@ minstrel_ht_stats_csv_dump(struct minstr
|
||||
|
||||
tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
|
||||
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
|
||||
- prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
|
||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
||||
|
||||
- p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
|
||||
+ p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
|
||||
"%u,%llu,%llu,",
|
||||
tp_max / 10, tp_max % 10,
|
||||
tp_avg / 10, tp_avg % 10,
|
||||
eprob / 10, eprob % 10,
|
||||
mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
|
||||
- prob / 10, prob % 10,
|
||||
mrs->retry_count,
|
||||
mrs->last_success,
|
||||
mrs->last_attempts,
|
|
@ -1,22 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 14 Dec 2016 20:15:33 +0100
|
||||
Subject: [PATCH] mac80211: minstrel: reduce MINSTREL_SCALE
|
||||
|
||||
The loss of a bit of extra precision does not hurt the calculation, 12
|
||||
bits is still enough to calculate probabilities well. Reducing the scale
|
||||
makes it easier to avoid overflows
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel.h
|
||||
+++ b/net/mac80211/rc80211_minstrel.h
|
||||
@@ -14,7 +14,7 @@
|
||||
#define SAMPLE_COLUMNS 10 /* number of columns in sample table */
|
||||
|
||||
/* scaled fraction values */
|
||||
-#define MINSTREL_SCALE 16
|
||||
+#define MINSTREL_SCALE 12
|
||||
#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
|
||||
#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 14 Dec 2016 20:17:06 +0100
|
||||
Subject: [PATCH] mac80211: minstrel: store probability variance instead of
|
||||
standard deviation
|
||||
|
||||
This avoids the costly int_sqrt calls in the statistics update and moves
|
||||
it to the debugfs code instead.
|
||||
This also fixes an overflow in the previous standard deviation
|
||||
calculation.
|
||||
|
||||
Signed-off-by: Thomas Huehn <thomas.huehn@evernet-eg.de>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel.c
|
||||
+++ b/net/mac80211/rc80211_minstrel.c
|
||||
@@ -168,10 +168,10 @@ minstrel_calc_rate_stats(struct minstrel
|
||||
mrs->prob_ewma = cur_prob;
|
||||
} else {
|
||||
/* update exponential weighted moving variance */
|
||||
- mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd,
|
||||
- cur_prob,
|
||||
- mrs->prob_ewma,
|
||||
- EWMA_LEVEL);
|
||||
+ mrs->prob_ewmv = minstrel_ewmv(mrs->prob_ewmv,
|
||||
+ cur_prob,
|
||||
+ mrs->prob_ewma,
|
||||
+ EWMA_LEVEL);
|
||||
|
||||
/*update exponential weighted moving avarage */
|
||||
mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
|
||||
--- a/net/mac80211/rc80211_minstrel.h
|
||||
+++ b/net/mac80211/rc80211_minstrel.h
|
||||
@@ -36,21 +36,16 @@ minstrel_ewma(int old, int new, int weig
|
||||
}
|
||||
|
||||
/*
|
||||
- * Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation
|
||||
+ * Perform EWMV (Exponentially Weighted Moving Variance) calculation
|
||||
*/
|
||||
static inline int
|
||||
-minstrel_ewmsd(int old_ewmsd, int cur_prob, int prob_ewma, int weight)
|
||||
+minstrel_ewmv(int old_ewmv, int cur_prob, int prob_ewma, int weight)
|
||||
{
|
||||
- int diff, incr, tmp_var;
|
||||
+ int diff, incr;
|
||||
|
||||
- /* calculate exponential weighted moving variance */
|
||||
- diff = MINSTREL_TRUNC((cur_prob - prob_ewma) * 1000000);
|
||||
+ diff = cur_prob - prob_ewma;
|
||||
incr = (EWMA_DIV - weight) * diff / EWMA_DIV;
|
||||
- tmp_var = old_ewmsd * old_ewmsd;
|
||||
- tmp_var = weight * (tmp_var + diff * incr / 1000000) / EWMA_DIV;
|
||||
-
|
||||
- /* return standard deviation */
|
||||
- return (u16) int_sqrt(tmp_var);
|
||||
+ return weight * (old_ewmv + MINSTREL_TRUNC(diff * incr)) / EWMA_DIV;
|
||||
}
|
||||
|
||||
struct minstrel_rate_stats {
|
||||
@@ -65,7 +60,7 @@ struct minstrel_rate_stats {
|
||||
* prob_ewma - exponential weighted moving average of prob
|
||||
* prob_ewmsd - exp. weighted moving standard deviation of prob */
|
||||
unsigned int prob_ewma;
|
||||
- u16 prob_ewmsd;
|
||||
+ u16 prob_ewmv;
|
||||
|
||||
/* maximum retry counts */
|
||||
u8 retry_count;
|
||||
@@ -151,6 +146,14 @@ struct minstrel_debugfs_info {
|
||||
char buf[];
|
||||
};
|
||||
|
||||
+/* Get EWMSD (Exponentially Weighted Moving Standard Deviation) * 10 */
|
||||
+static inline int
|
||||
+minstrel_get_ewmsd10(struct minstrel_rate_stats *mrs)
|
||||
+{
|
||||
+ unsigned int ewmv = mrs->prob_ewmv;
|
||||
+ return int_sqrt(MINSTREL_TRUNC(ewmv * 1000 * 1000));
|
||||
+}
|
||||
+
|
||||
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);
|
||||
--- a/net/mac80211/rc80211_minstrel_debugfs.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
|
||||
@@ -93,6 +93,7 @@ minstrel_stats_open(struct inode *inode,
|
||||
for (i = 0; i < mi->n_rates; i++) {
|
||||
struct minstrel_rate *mr = &mi->r[i];
|
||||
struct minstrel_rate_stats *mrs = &mi->r[i].stats;
|
||||
+ unsigned int prob_ewmsd;
|
||||
|
||||
*(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' ';
|
||||
*(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' ';
|
||||
@@ -108,6 +109,7 @@ minstrel_stats_open(struct inode *inode,
|
||||
tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
|
||||
tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
|
||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
||||
+ prob_ewmsd = minstrel_get_ewmsd10(mrs);
|
||||
|
||||
p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
|
||||
" %3u %3u %-3u "
|
||||
@@ -115,7 +117,7 @@ minstrel_stats_open(struct inode *inode,
|
||||
tp_max / 10, tp_max % 10,
|
||||
tp_avg / 10, tp_avg % 10,
|
||||
eprob / 10, eprob % 10,
|
||||
- mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
|
||||
+ prob_ewmsd / 10, prob_ewmsd % 10,
|
||||
mrs->retry_count,
|
||||
mrs->last_success,
|
||||
mrs->last_attempts,
|
||||
@@ -159,6 +161,7 @@ minstrel_stats_csv_open(struct inode *in
|
||||
for (i = 0; i < mi->n_rates; i++) {
|
||||
struct minstrel_rate *mr = &mi->r[i];
|
||||
struct minstrel_rate_stats *mrs = &mi->r[i].stats;
|
||||
+ unsigned int prob_ewmsd;
|
||||
|
||||
p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : ""));
|
||||
p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : ""));
|
||||
@@ -174,13 +177,14 @@ minstrel_stats_csv_open(struct inode *in
|
||||
tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
|
||||
tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
|
||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
||||
+ prob_ewmsd = minstrel_get_ewmsd10(mrs);
|
||||
|
||||
p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
|
||||
"%llu,%llu,%d,%d\n",
|
||||
tp_max / 10, tp_max % 10,
|
||||
tp_avg / 10, tp_avg % 10,
|
||||
eprob / 10, eprob % 10,
|
||||
- mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
|
||||
+ prob_ewmsd / 10, prob_ewmsd % 10,
|
||||
mrs->retry_count,
|
||||
mrs->last_success,
|
||||
mrs->last_attempts,
|
||||
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
|
||||
@@ -41,6 +41,7 @@ minstrel_ht_stats_dump(struct minstrel_h
|
||||
struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
|
||||
static const int bitrates[4] = { 10, 20, 55, 110 };
|
||||
int idx = i * MCS_GROUP_RATES + j;
|
||||
+ unsigned int prob_ewmsd;
|
||||
|
||||
if (!(mi->supported[i] & BIT(j)))
|
||||
continue;
|
||||
@@ -84,6 +85,7 @@ minstrel_ht_stats_dump(struct minstrel_h
|
||||
tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
|
||||
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
|
||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
||||
+ prob_ewmsd = minstrel_get_ewmsd10(mrs);
|
||||
|
||||
p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
|
||||
" %3u %3u %-3u "
|
||||
@@ -91,7 +93,7 @@ minstrel_ht_stats_dump(struct minstrel_h
|
||||
tp_max / 10, tp_max % 10,
|
||||
tp_avg / 10, tp_avg % 10,
|
||||
eprob / 10, eprob % 10,
|
||||
- mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
|
||||
+ prob_ewmsd / 10, prob_ewmsd % 10,
|
||||
mrs->retry_count,
|
||||
mrs->last_success,
|
||||
mrs->last_attempts,
|
||||
@@ -185,6 +187,7 @@ minstrel_ht_stats_csv_dump(struct minstr
|
||||
struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
|
||||
static const int bitrates[4] = { 10, 20, 55, 110 };
|
||||
int idx = i * MCS_GROUP_RATES + j;
|
||||
+ unsigned int prob_ewmsd;
|
||||
|
||||
if (!(mi->supported[i] & BIT(j)))
|
||||
continue;
|
||||
@@ -225,13 +228,14 @@ minstrel_ht_stats_csv_dump(struct minstr
|
||||
tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
|
||||
tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
|
||||
eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
|
||||
+ prob_ewmsd = minstrel_get_ewmsd10(mrs);
|
||||
|
||||
p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
|
||||
"%u,%llu,%llu,",
|
||||
tp_max / 10, tp_max % 10,
|
||||
tp_avg / 10, tp_avg % 10,
|
||||
eprob / 10, eprob % 10,
|
||||
- mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
|
||||
+ prob_ewmsd / 10, prob_ewmsd % 10,
|
||||
mrs->retry_count,
|
||||
mrs->last_success,
|
||||
mrs->last_attempts,
|
|
@ -1,20 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 14 Dec 2016 20:19:56 +0100
|
||||
Subject: [PATCH] mac80211: minstrel: make prob_ewma u16 instead of u32
|
||||
|
||||
Saves about 1.2 KiB memory per station
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel.h
|
||||
+++ b/net/mac80211/rc80211_minstrel.h
|
||||
@@ -59,7 +59,7 @@ struct minstrel_rate_stats {
|
||||
/* statistis of packet delivery probability
|
||||
* prob_ewma - exponential weighted moving average of prob
|
||||
* prob_ewmsd - exp. weighted moving standard deviation of prob */
|
||||
- unsigned int prob_ewma;
|
||||
+ u16 prob_ewma;
|
||||
u16 prob_ewmv;
|
||||
|
||||
/* maximum retry counts */
|
|
@ -1,80 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 14 Dec 2016 20:23:29 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: remove obsolete #if for >= 3 streams
|
||||
|
||||
This was added during early development when 3x3 hardware was not very
|
||||
common yet. This is completely unnecessary now.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -155,67 +155,47 @@ MODULE_PARM_DESC(minstrel_vht_only,
|
||||
const struct mcs_group minstrel_mcs_groups[] = {
|
||||
MCS_GROUP(1, 0, BW_20),
|
||||
MCS_GROUP(2, 0, BW_20),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
MCS_GROUP(3, 0, BW_20),
|
||||
-#endif
|
||||
|
||||
MCS_GROUP(1, 1, BW_20),
|
||||
MCS_GROUP(2, 1, BW_20),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
MCS_GROUP(3, 1, BW_20),
|
||||
-#endif
|
||||
|
||||
MCS_GROUP(1, 0, BW_40),
|
||||
MCS_GROUP(2, 0, BW_40),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
MCS_GROUP(3, 0, BW_40),
|
||||
-#endif
|
||||
|
||||
MCS_GROUP(1, 1, BW_40),
|
||||
MCS_GROUP(2, 1, BW_40),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
MCS_GROUP(3, 1, BW_40),
|
||||
-#endif
|
||||
|
||||
CCK_GROUP,
|
||||
|
||||
#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
|
||||
VHT_GROUP(1, 0, BW_20),
|
||||
VHT_GROUP(2, 0, BW_20),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
VHT_GROUP(3, 0, BW_20),
|
||||
-#endif
|
||||
|
||||
VHT_GROUP(1, 1, BW_20),
|
||||
VHT_GROUP(2, 1, BW_20),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
VHT_GROUP(3, 1, BW_20),
|
||||
-#endif
|
||||
|
||||
VHT_GROUP(1, 0, BW_40),
|
||||
VHT_GROUP(2, 0, BW_40),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
VHT_GROUP(3, 0, BW_40),
|
||||
-#endif
|
||||
|
||||
VHT_GROUP(1, 1, BW_40),
|
||||
VHT_GROUP(2, 1, BW_40),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
VHT_GROUP(3, 1, BW_40),
|
||||
-#endif
|
||||
|
||||
VHT_GROUP(1, 0, BW_80),
|
||||
VHT_GROUP(2, 0, BW_80),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
VHT_GROUP(3, 0, BW_80),
|
||||
-#endif
|
||||
|
||||
VHT_GROUP(1, 1, BW_80),
|
||||
VHT_GROUP(2, 1, BW_80),
|
||||
-#if MINSTREL_MAX_STREAMS >= 3
|
||||
VHT_GROUP(3, 1, BW_80),
|
||||
#endif
|
||||
-#endif
|
||||
};
|
||||
|
||||
static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
|
|
@ -1,150 +0,0 @@
|
|||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Tue, 15 Nov 2016 12:05:11 +0100
|
||||
Subject: [PATCH] cfg80211: limit scan results cache size
|
||||
|
||||
It's possible to make scanning consume almost arbitrary amounts
|
||||
of memory, e.g. by sending beacon frames with random BSSIDs at
|
||||
high rates while somebody is scanning.
|
||||
|
||||
Limit the number of BSS table entries we're willing to cache to
|
||||
1000, limiting maximum memory usage to maybe 4-5MB, but lower
|
||||
in practice - that would be the case for having both full-sized
|
||||
beacon and probe response frames for each entry; this seems not
|
||||
possible in practice, so a limit of 1000 entries will likely be
|
||||
closer to 0.5 MB.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/wireless/core.h
|
||||
+++ b/net/wireless/core.h
|
||||
@@ -71,6 +71,7 @@ struct cfg80211_registered_device {
|
||||
struct list_head bss_list;
|
||||
struct rb_root bss_tree;
|
||||
u32 bss_generation;
|
||||
+ u32 bss_entries;
|
||||
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
|
||||
struct sk_buff *scan_msg;
|
||||
struct cfg80211_sched_scan_request __rcu *sched_scan_req;
|
||||
--- a/net/wireless/scan.c
|
||||
+++ b/net/wireless/scan.c
|
||||
@@ -57,6 +57,19 @@
|
||||
* also linked into the probe response struct.
|
||||
*/
|
||||
|
||||
+/*
|
||||
+ * Limit the number of BSS entries stored in mac80211. Each one is
|
||||
+ * a bit over 4k at most, so this limits to roughly 4-5M of memory.
|
||||
+ * If somebody wants to really attack this though, they'd likely
|
||||
+ * use small beacons, and only one type of frame, limiting each of
|
||||
+ * the entries to a much smaller size (in order to generate more
|
||||
+ * entries in total, so overhead is bigger.)
|
||||
+ */
|
||||
+static int bss_entries_limit = 1000;
|
||||
+module_param(bss_entries_limit, int, 0644);
|
||||
+MODULE_PARM_DESC(bss_entries_limit,
|
||||
+ "limit to number of scan BSS entries (per wiphy, default 1000)");
|
||||
+
|
||||
#define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
|
||||
|
||||
static void bss_free(struct cfg80211_internal_bss *bss)
|
||||
@@ -137,6 +150,10 @@ static bool __cfg80211_unlink_bss(struct
|
||||
|
||||
list_del_init(&bss->list);
|
||||
rb_erase(&bss->rbn, &rdev->bss_tree);
|
||||
+ rdev->bss_entries--;
|
||||
+ WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list),
|
||||
+ "rdev bss entries[%d]/list[empty:%d] corruption\n",
|
||||
+ rdev->bss_entries, list_empty(&rdev->bss_list));
|
||||
bss_ref_put(rdev, bss);
|
||||
return true;
|
||||
}
|
||||
@@ -163,6 +180,40 @@ static void __cfg80211_bss_expire(struct
|
||||
rdev->bss_generation++;
|
||||
}
|
||||
|
||||
+static bool cfg80211_bss_expire_oldest(struct cfg80211_registered_device *rdev)
|
||||
+{
|
||||
+ struct cfg80211_internal_bss *bss, *oldest = NULL;
|
||||
+ bool ret;
|
||||
+
|
||||
+ lockdep_assert_held(&rdev->bss_lock);
|
||||
+
|
||||
+ list_for_each_entry(bss, &rdev->bss_list, list) {
|
||||
+ if (atomic_read(&bss->hold))
|
||||
+ continue;
|
||||
+
|
||||
+ if (!list_empty(&bss->hidden_list) &&
|
||||
+ !bss->pub.hidden_beacon_bss)
|
||||
+ continue;
|
||||
+
|
||||
+ if (oldest && time_before(oldest->ts, bss->ts))
|
||||
+ continue;
|
||||
+ oldest = bss;
|
||||
+ }
|
||||
+
|
||||
+ if (WARN_ON(!oldest))
|
||||
+ return false;
|
||||
+
|
||||
+ /*
|
||||
+ * The callers make sure to increase rdev->bss_generation if anything
|
||||
+ * gets removed (and a new entry added), so there's no need to also do
|
||||
+ * it here.
|
||||
+ */
|
||||
+
|
||||
+ ret = __cfg80211_unlink_bss(rdev, oldest);
|
||||
+ WARN_ON(!ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
|
||||
bool send_message)
|
||||
{
|
||||
@@ -689,6 +740,7 @@ static bool cfg80211_combine_bsses(struc
|
||||
const u8 *ie;
|
||||
int i, ssidlen;
|
||||
u8 fold = 0;
|
||||
+ u32 n_entries = 0;
|
||||
|
||||
ies = rcu_access_pointer(new->pub.beacon_ies);
|
||||
if (WARN_ON(!ies))
|
||||
@@ -712,6 +764,12 @@ static bool cfg80211_combine_bsses(struc
|
||||
/* This is the bad part ... */
|
||||
|
||||
list_for_each_entry(bss, &rdev->bss_list, list) {
|
||||
+ /*
|
||||
+ * we're iterating all the entries anyway, so take the
|
||||
+ * opportunity to validate the list length accounting
|
||||
+ */
|
||||
+ n_entries++;
|
||||
+
|
||||
if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid))
|
||||
continue;
|
||||
if (bss->pub.channel != new->pub.channel)
|
||||
@@ -740,6 +798,10 @@ static bool cfg80211_combine_bsses(struc
|
||||
new->pub.beacon_ies);
|
||||
}
|
||||
|
||||
+ WARN_ONCE(n_entries != rdev->bss_entries,
|
||||
+ "rdev bss entries[%d]/list[len:%d] corruption\n",
|
||||
+ rdev->bss_entries, n_entries);
|
||||
+
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -894,7 +956,14 @@ cfg80211_bss_update(struct cfg80211_regi
|
||||
}
|
||||
}
|
||||
|
||||
+ if (rdev->bss_entries >= bss_entries_limit &&
|
||||
+ !cfg80211_bss_expire_oldest(rdev)) {
|
||||
+ kfree(new);
|
||||
+ goto drop;
|
||||
+ }
|
||||
+
|
||||
list_add_tail(&new->list, &rdev->bss_list);
|
||||
+ rdev->bss_entries++;
|
||||
rb_insert_bss(rdev, new);
|
||||
found = new;
|
||||
}
|
|
@ -1,651 +0,0 @@
|
|||
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
|
||||
Date: Mon, 5 Dec 2016 13:27:37 +0200
|
||||
Subject: [PATCH] ath9k: Introduce airtime fairness scheduling between stations
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This reworks the ath9k driver to schedule transmissions to connected
|
||||
stations in a way that enforces airtime fairness between them. It
|
||||
accomplishes this by measuring the time spent transmitting to or
|
||||
receiving from a station at TX and RX completion, and accounting this to
|
||||
a per-station, per-QoS level airtime deficit. Then, an FQ-CoDel based
|
||||
deficit scheduler is employed at packet dequeue time, to control which
|
||||
station gets the next transmission opportunity.
|
||||
|
||||
Airtime fairness can significantly improve the efficiency of the network
|
||||
when station rates vary. The following throughput values are from a
|
||||
simple three-station test scenario, where two stations operate at the
|
||||
highest HT20 rate, and one station at the lowest, and the scheduler is
|
||||
employed at the access point:
|
||||
|
||||
Before / After
|
||||
Fast station 1: 19.17 / 25.09 Mbps
|
||||
Fast station 2: 19.83 / 25.21 Mbps
|
||||
Slow station: 2.58 / 1.77 Mbps
|
||||
Total: 41.58 / 52.07 Mbps
|
||||
|
||||
The benefit of airtime fairness goes up the more stations are present.
|
||||
In a 30-station test with one station artificially limited to 1 Mbps,
|
||||
we have seen aggregate throughput go from 2.14 to 17.76 Mbps.
|
||||
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
|
||||
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -112,6 +112,8 @@ int ath_descdma_setup(struct ath_softc *
|
||||
#define ATH_TXFIFO_DEPTH 8
|
||||
#define ATH_TX_ERROR 0x01
|
||||
|
||||
+#define ATH_AIRTIME_QUANTUM 300 /* usec */
|
||||
+
|
||||
/* Stop tx traffic 1ms before the GO goes away */
|
||||
#define ATH_P2P_PS_STOP_TIME 1000
|
||||
|
||||
@@ -247,6 +249,9 @@ struct ath_atx_tid {
|
||||
bool has_queued;
|
||||
};
|
||||
|
||||
+void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
|
||||
+void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
|
||||
+
|
||||
struct ath_node {
|
||||
struct ath_softc *sc;
|
||||
struct ieee80211_sta *sta; /* station struct we're part of */
|
||||
@@ -258,9 +263,12 @@ struct ath_node {
|
||||
|
||||
bool sleeping;
|
||||
bool no_ps_filter;
|
||||
+ s64 airtime_deficit[IEEE80211_NUM_ACS];
|
||||
+ u32 airtime_rx_start;
|
||||
|
||||
#ifdef CPTCFG_ATH9K_STATION_STATISTICS
|
||||
struct ath_rx_rate_stats rx_rate_stats;
|
||||
+ struct ath_airtime_stats airtime_stats;
|
||||
#endif
|
||||
u8 key_idx[4];
|
||||
|
||||
@@ -317,10 +325,16 @@ struct ath_rx {
|
||||
/* Channel Context */
|
||||
/*******************/
|
||||
|
||||
+struct ath_acq {
|
||||
+ struct list_head acq_new;
|
||||
+ struct list_head acq_old;
|
||||
+ spinlock_t lock;
|
||||
+};
|
||||
+
|
||||
struct ath_chanctx {
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct list_head vifs;
|
||||
- struct list_head acq[IEEE80211_NUM_ACS];
|
||||
+ struct ath_acq acq[IEEE80211_NUM_ACS];
|
||||
int hw_queue_base;
|
||||
|
||||
/* do not dereference, use for comparison only */
|
||||
@@ -575,6 +589,8 @@ void ath_txq_schedule_all(struct ath_sof
|
||||
int ath_tx_init(struct ath_softc *sc, int nbufs);
|
||||
int ath_txq_update(struct ath_softc *sc, int qnum,
|
||||
struct ath9k_tx_queue_info *q);
|
||||
+u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
|
||||
+ int width, int half_gi, bool shortPreamble);
|
||||
void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop);
|
||||
void ath_assign_seq(struct ath_common *common, struct sk_buff *skb);
|
||||
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
@@ -963,6 +979,11 @@ void ath_ant_comb_scan(struct ath_softc
|
||||
|
||||
#define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
|
||||
|
||||
+#define AIRTIME_USE_TX BIT(0)
|
||||
+#define AIRTIME_USE_RX BIT(1)
|
||||
+#define AIRTIME_USE_NEW_QUEUES BIT(2)
|
||||
+#define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX)))
|
||||
+
|
||||
struct ath_softc {
|
||||
struct ieee80211_hw *hw;
|
||||
struct device *dev;
|
||||
@@ -1005,6 +1026,8 @@ struct ath_softc {
|
||||
short nbcnvifs;
|
||||
unsigned long ps_usecount;
|
||||
|
||||
+ u16 airtime_flags; /* AIRTIME_* */
|
||||
+
|
||||
struct ath_rx rx;
|
||||
struct ath_tx tx;
|
||||
struct ath_beacon beacon;
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -118,8 +118,11 @@ void ath_chanctx_init(struct ath_softc *
|
||||
INIT_LIST_HEAD(&ctx->vifs);
|
||||
ctx->txpower = ATH_TXPOWER_MAX;
|
||||
ctx->flush_timeout = HZ / 5; /* 200ms */
|
||||
- for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
|
||||
- INIT_LIST_HEAD(&ctx->acq[j]);
|
||||
+ for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) {
|
||||
+ INIT_LIST_HEAD(&ctx->acq[j].acq_new);
|
||||
+ INIT_LIST_HEAD(&ctx->acq[j].acq_old);
|
||||
+ spin_lock_init(&ctx->acq[j].lock);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,8 +1348,11 @@ void ath9k_offchannel_init(struct ath_so
|
||||
ctx->txpower = ATH_TXPOWER_MAX;
|
||||
cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(ctx->acq); i++)
|
||||
- INIT_LIST_HEAD(&ctx->acq[i]);
|
||||
+ for (i = 0; i < ARRAY_SIZE(ctx->acq); i++) {
|
||||
+ INIT_LIST_HEAD(&ctx->acq[i].acq_new);
|
||||
+ INIT_LIST_HEAD(&ctx->acq[i].acq_old);
|
||||
+ spin_lock_init(&ctx->acq[i].lock);
|
||||
+ }
|
||||
|
||||
sc->offchannel.chan.offchannel = true;
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1399,5 +1399,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
debugfs_create_file("tpc", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_tpc);
|
||||
|
||||
+ debugfs_create_u16("airtime_flags", S_IRUSR | S_IWUSR,
|
||||
+ sc->debug.debugfs_phy, &sc->airtime_flags);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.h
|
||||
@@ -221,6 +221,11 @@ struct ath_rx_rate_stats {
|
||||
} cck_stats[4];
|
||||
};
|
||||
|
||||
+struct ath_airtime_stats {
|
||||
+ u32 rx_airtime;
|
||||
+ u32 tx_airtime;
|
||||
+};
|
||||
+
|
||||
#define ANT_MAIN 0
|
||||
#define ANT_ALT 1
|
||||
|
||||
@@ -314,12 +319,20 @@ ath9k_debug_sync_cause(struct ath_softc
|
||||
void ath_debug_rate_stats(struct ath_softc *sc,
|
||||
struct ath_rx_status *rs,
|
||||
struct sk_buff *skb);
|
||||
+void ath_debug_airtime(struct ath_softc *sc,
|
||||
+ struct ath_node *an,
|
||||
+ u32 rx, u32 tx);
|
||||
#else
|
||||
static inline void ath_debug_rate_stats(struct ath_softc *sc,
|
||||
struct ath_rx_status *rs,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
+static inline void ath_debug_airtime(struct ath_softc *sc,
|
||||
+ struct ath_node *an,
|
||||
+ u32 rx, u32 tx)
|
||||
+{
|
||||
+}
|
||||
#endif /* CPTCFG_ATH9K_STATION_STATISTICS */
|
||||
|
||||
#endif /* DEBUG_H */
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
|
||||
@@ -242,6 +242,59 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
+void ath_debug_airtime(struct ath_softc *sc,
|
||||
+ struct ath_node *an,
|
||||
+ u32 rx,
|
||||
+ u32 tx)
|
||||
+{
|
||||
+ struct ath_airtime_stats *astats = &an->airtime_stats;
|
||||
+
|
||||
+ astats->rx_airtime += rx;
|
||||
+ astats->tx_airtime += tx;
|
||||
+}
|
||||
+
|
||||
+static ssize_t read_airtime(struct file *file, char __user *user_buf,
|
||||
+ size_t count, loff_t *ppos)
|
||||
+{
|
||||
+ struct ath_node *an = file->private_data;
|
||||
+ struct ath_airtime_stats *astats;
|
||||
+ static const char *qname[4] = {
|
||||
+ "VO", "VI", "BE", "BK"
|
||||
+ };
|
||||
+ u32 len = 0, size = 256;
|
||||
+ char *buf;
|
||||
+ size_t retval;
|
||||
+ int i;
|
||||
+
|
||||
+ buf = kzalloc(size, GFP_KERNEL);
|
||||
+ if (buf == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ astats = &an->airtime_stats;
|
||||
+
|
||||
+ len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime);
|
||||
+ len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime);
|
||||
+ len += scnprintf(buf + len, size - len, "Deficit: ");
|
||||
+ for (i = 0; i < 4; i++)
|
||||
+ len += scnprintf(buf+len, size - len, "%s: %lld us ", qname[i], an->airtime_deficit[i]);
|
||||
+ if (len < size)
|
||||
+ buf[len++] = '\n';
|
||||
+
|
||||
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
+ kfree(buf);
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static const struct file_operations fops_airtime = {
|
||||
+ .read = read_airtime,
|
||||
+ .open = simple_open,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .llseek = default_llseek,
|
||||
+};
|
||||
+
|
||||
+
|
||||
void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
@@ -251,4 +304,5 @@ void ath9k_sta_add_debugfs(struct ieee80
|
||||
|
||||
debugfs_create_file("node_aggr", S_IRUGO, dir, an, &fops_node_aggr);
|
||||
debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv);
|
||||
+ debugfs_create_file("airtime", S_IRUGO, dir, an, &fops_airtime);
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -620,6 +620,8 @@ static int ath9k_init_softc(u16 devid, s
|
||||
|
||||
/* Will be cleared in ath9k_start() */
|
||||
set_bit(ATH_OP_INVALID, &common->op_flags);
|
||||
+ sc->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX |
|
||||
+ AIRTIME_USE_NEW_QUEUES);
|
||||
|
||||
sc->sc_ah = ah;
|
||||
sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -70,10 +70,10 @@ static bool ath9k_has_pending_frames(str
|
||||
goto out;
|
||||
|
||||
if (txq->mac80211_qnum >= 0) {
|
||||
- struct list_head *list;
|
||||
+ struct ath_acq *acq;
|
||||
|
||||
- list = &sc->cur_chan->acq[txq->mac80211_qnum];
|
||||
- if (!list_empty(list))
|
||||
+ acq = &sc->cur_chan->acq[txq->mac80211_qnum];
|
||||
+ if (!list_empty(&acq->acq_new) || !list_empty(&acq->acq_old))
|
||||
pending = true;
|
||||
}
|
||||
out:
|
||||
--- a/drivers/net/wireless/ath/ath9k/recv.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/recv.c
|
||||
@@ -991,6 +991,70 @@ static void ath9k_apply_ampdu_details(st
|
||||
}
|
||||
}
|
||||
|
||||
+static void ath_rx_count_airtime(struct ath_softc *sc,
|
||||
+ struct ath_rx_status *rs,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ struct ath_node *an;
|
||||
+ struct ath_acq *acq;
|
||||
+ struct ath_vif *avp;
|
||||
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
+ struct ath_hw *ah = sc->sc_ah;
|
||||
+ struct ath_common *common = ath9k_hw_common(ah);
|
||||
+ struct ieee80211_sta *sta;
|
||||
+ struct ieee80211_rx_status *rxs;
|
||||
+ const struct ieee80211_rate *rate;
|
||||
+ bool is_sgi, is_40, is_sp;
|
||||
+ int phy;
|
||||
+ u16 len = rs->rs_datalen;
|
||||
+ u32 airtime = 0;
|
||||
+ u8 tidno, acno;
|
||||
+
|
||||
+ if (!ieee80211_is_data(hdr->frame_control))
|
||||
+ return;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+
|
||||
+ sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL);
|
||||
+ if (!sta)
|
||||
+ goto exit;
|
||||
+ an = (struct ath_node *) sta->drv_priv;
|
||||
+ avp = (struct ath_vif *) an->vif->drv_priv;
|
||||
+ tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
+ acno = TID_TO_WME_AC(tidno);
|
||||
+ acq = &avp->chanctx->acq[acno];
|
||||
+
|
||||
+ rxs = IEEE80211_SKB_RXCB(skb);
|
||||
+
|
||||
+ is_sgi = !!(rxs->flag & RX_FLAG_SHORT_GI);
|
||||
+ is_40 = !!(rxs->flag & RX_FLAG_40MHZ);
|
||||
+ is_sp = !!(rxs->flag & RX_FLAG_SHORTPRE);
|
||||
+
|
||||
+ if (!!(rxs->flag & RX_FLAG_HT)) {
|
||||
+ /* MCS rates */
|
||||
+
|
||||
+ airtime += ath_pkt_duration(sc, rxs->rate_idx, len,
|
||||
+ is_40, is_sgi, is_sp);
|
||||
+ } else {
|
||||
+
|
||||
+ phy = IS_CCK_RATE(rs->rs_rate) ? WLAN_RC_PHY_CCK : WLAN_RC_PHY_OFDM;
|
||||
+ rate = &common->sbands[rxs->band].bitrates[rxs->rate_idx];
|
||||
+ airtime += ath9k_hw_computetxtime(ah, phy, rate->bitrate * 100,
|
||||
+ len, rxs->rate_idx, is_sp);
|
||||
+ }
|
||||
+
|
||||
+ if (!!(sc->airtime_flags & AIRTIME_USE_RX)) {
|
||||
+ spin_lock_bh(&acq->lock);
|
||||
+ an->airtime_deficit[acno] -= airtime;
|
||||
+ if (an->airtime_deficit[acno] <= 0)
|
||||
+ __ath_tx_queue_tid(sc, ATH_AN_2_TID(an, tidno));
|
||||
+ spin_unlock_bh(&acq->lock);
|
||||
+ }
|
||||
+ ath_debug_airtime(sc, an, airtime, 0);
|
||||
+exit:
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
{
|
||||
struct ath_rxbuf *bf;
|
||||
@@ -1137,6 +1201,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
|
||||
ath9k_antenna_check(sc, &rs);
|
||||
ath9k_apply_ampdu_details(sc, &rs, rxs);
|
||||
ath_debug_rate_stats(sc, &rs, skb);
|
||||
+ ath_rx_count_airtime(sc, &rs, skb);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
if (ieee80211_is_ack(hdr->frame_control))
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -125,21 +125,44 @@ void ath_txq_unlock_complete(struct ath_
|
||||
ath_tx_status(hw, skb);
|
||||
}
|
||||
|
||||
-static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
|
||||
- struct ath_atx_tid *tid)
|
||||
+void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
- struct list_head *list;
|
||||
struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
|
||||
struct ath_chanctx *ctx = avp->chanctx;
|
||||
+ struct ath_acq *acq;
|
||||
+ struct list_head *tid_list;
|
||||
+ u8 acno = TID_TO_WME_AC(tid->tidno);
|
||||
|
||||
- if (!ctx)
|
||||
+ if (!ctx || !list_empty(&tid->list))
|
||||
return;
|
||||
|
||||
- list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
|
||||
- if (list_empty(&tid->list))
|
||||
- list_add_tail(&tid->list, list);
|
||||
+
|
||||
+ acq = &ctx->acq[acno];
|
||||
+ if ((sc->airtime_flags & AIRTIME_USE_NEW_QUEUES) &&
|
||||
+ tid->an->airtime_deficit[acno] > 0)
|
||||
+ tid_list = &acq->acq_new;
|
||||
+ else
|
||||
+ tid_list = &acq->acq_old;
|
||||
+
|
||||
+ list_add_tail(&tid->list, tid_list);
|
||||
}
|
||||
|
||||
+void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
+{
|
||||
+ struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
|
||||
+ struct ath_chanctx *ctx = avp->chanctx;
|
||||
+ struct ath_acq *acq;
|
||||
+
|
||||
+ if (!ctx || !list_empty(&tid->list))
|
||||
+ return;
|
||||
+
|
||||
+ acq = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
|
||||
+ spin_lock_bh(&acq->lock);
|
||||
+ __ath_tx_queue_tid(sc, tid);
|
||||
+ spin_unlock_bh(&acq->lock);
|
||||
+}
|
||||
+
|
||||
+
|
||||
void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
@@ -154,7 +177,7 @@ void ath9k_wake_tx_queue(struct ieee8021
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
tid->has_queued = true;
|
||||
- ath_tx_queue_tid(sc, txq, tid);
|
||||
+ ath_tx_queue_tid(sc, tid);
|
||||
ath_txq_schedule(sc, txq);
|
||||
|
||||
ath_txq_unlock(sc, txq);
|
||||
@@ -684,7 +707,7 @@ static void ath_tx_complete_aggr(struct
|
||||
|
||||
skb_queue_splice_tail(&bf_pending, &tid->retry_q);
|
||||
if (!an->sleeping) {
|
||||
- ath_tx_queue_tid(sc, txq, tid);
|
||||
+ ath_tx_queue_tid(sc, tid);
|
||||
|
||||
if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
|
||||
tid->clear_ps_filter = true;
|
||||
@@ -712,6 +735,53 @@ static bool bf_is_ampdu_not_probing(stru
|
||||
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
|
||||
}
|
||||
|
||||
+static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_txq *txq,
|
||||
+ struct ath_buf *bf, struct ath_tx_status *ts)
|
||||
+{
|
||||
+ struct ath_node *an;
|
||||
+ struct ath_acq *acq = &sc->cur_chan->acq[txq->mac80211_qnum];
|
||||
+ struct sk_buff *skb;
|
||||
+ struct ieee80211_hdr *hdr;
|
||||
+ struct ieee80211_hw *hw = sc->hw;
|
||||
+ struct ieee80211_tx_rate rates[4];
|
||||
+ struct ieee80211_sta *sta;
|
||||
+ int i;
|
||||
+ u32 airtime = 0;
|
||||
+
|
||||
+ skb = bf->bf_mpdu;
|
||||
+ if(!skb)
|
||||
+ return;
|
||||
+
|
||||
+ hdr = (struct ieee80211_hdr *)skb->data;
|
||||
+ memcpy(rates, bf->rates, sizeof(rates));
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+
|
||||
+ sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
|
||||
+ if(!sta)
|
||||
+ goto exit;
|
||||
+
|
||||
+
|
||||
+ an = (struct ath_node *) sta->drv_priv;
|
||||
+
|
||||
+ airtime += ts->duration * (ts->ts_longretry + 1);
|
||||
+
|
||||
+ for(i=0; i < ts->ts_rateindex; i++)
|
||||
+ airtime += ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i) * rates[i].count;
|
||||
+
|
||||
+ if (!!(sc->airtime_flags & AIRTIME_USE_TX)) {
|
||||
+ spin_lock_bh(&acq->lock);
|
||||
+ an->airtime_deficit[txq->mac80211_qnum] -= airtime;
|
||||
+ if (an->airtime_deficit[txq->mac80211_qnum] <= 0)
|
||||
+ __ath_tx_queue_tid(sc, ath_get_skb_tid(sc, an, skb));
|
||||
+ spin_unlock_bh(&acq->lock);
|
||||
+ }
|
||||
+ ath_debug_airtime(sc, an, 0, airtime);
|
||||
+
|
||||
+exit:
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_tx_status *ts, struct ath_buf *bf,
|
||||
struct list_head *bf_head)
|
||||
@@ -733,6 +803,7 @@ static void ath_tx_process_buffer(struct
|
||||
|
||||
ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc,
|
||||
ts->ts_rateindex);
|
||||
+ ath_tx_count_airtime(sc, txq, bf, ts);
|
||||
|
||||
hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
|
||||
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
|
||||
@@ -1094,8 +1165,8 @@ finish:
|
||||
* width - 0 for 20 MHz, 1 for 40 MHz
|
||||
* half_gi - to use 4us v/s 3.6 us for symbol time
|
||||
*/
|
||||
-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
|
||||
- int width, int half_gi, bool shortPreamble)
|
||||
+u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
|
||||
+ int width, int half_gi, bool shortPreamble)
|
||||
{
|
||||
u32 nbits, nsymbits, duration, nsymbols;
|
||||
int streams;
|
||||
@@ -1493,7 +1564,7 @@ ath_tx_form_burst(struct ath_softc *sc,
|
||||
}
|
||||
|
||||
static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
- struct ath_atx_tid *tid, bool *stop)
|
||||
+ struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
@@ -1515,7 +1586,6 @@ static bool ath_tx_sched_aggr(struct ath
|
||||
if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
|
||||
(!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
|
||||
__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
|
||||
- *stop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1639,7 +1709,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
|
||||
ath_txq_lock(sc, txq);
|
||||
tid->clear_ps_filter = true;
|
||||
if (ath_tid_has_buffered(tid)) {
|
||||
- ath_tx_queue_tid(sc, txq, tid);
|
||||
+ ath_tx_queue_tid(sc, tid);
|
||||
ath_txq_schedule(sc, txq);
|
||||
}
|
||||
ath_txq_unlock_complete(sc, txq);
|
||||
@@ -1956,9 +2026,10 @@ void ath_tx_cleanupq(struct ath_softc *s
|
||||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
- struct ath_atx_tid *tid, *last_tid;
|
||||
+ struct ath_atx_tid *tid;
|
||||
struct list_head *tid_list;
|
||||
- bool sent = false;
|
||||
+ struct ath_acq *acq;
|
||||
+ bool active = AIRTIME_ACTIVE(sc->airtime_flags);
|
||||
|
||||
if (txq->mac80211_qnum < 0)
|
||||
return;
|
||||
@@ -1967,48 +2038,55 @@ void ath_txq_schedule(struct ath_softc *
|
||||
return;
|
||||
|
||||
spin_lock_bh(&sc->chan_lock);
|
||||
- tid_list = &sc->cur_chan->acq[txq->mac80211_qnum];
|
||||
-
|
||||
- if (list_empty(tid_list)) {
|
||||
- spin_unlock_bh(&sc->chan_lock);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
rcu_read_lock();
|
||||
+ acq = &sc->cur_chan->acq[txq->mac80211_qnum];
|
||||
|
||||
- last_tid = list_entry(tid_list->prev, struct ath_atx_tid, list);
|
||||
- while (!list_empty(tid_list)) {
|
||||
- bool stop = false;
|
||||
-
|
||||
- if (sc->cur_chan->stopped)
|
||||
- break;
|
||||
-
|
||||
- tid = list_first_entry(tid_list, struct ath_atx_tid, list);
|
||||
- list_del_init(&tid->list);
|
||||
+ if (sc->cur_chan->stopped)
|
||||
+ goto out;
|
||||
|
||||
- if (ath_tx_sched_aggr(sc, txq, tid, &stop))
|
||||
- sent = true;
|
||||
+begin:
|
||||
+ tid_list = &acq->acq_new;
|
||||
+ if (list_empty(tid_list)) {
|
||||
+ tid_list = &acq->acq_old;
|
||||
+ if (list_empty(tid_list))
|
||||
+ goto out;
|
||||
+ }
|
||||
+ tid = list_first_entry(tid_list, struct ath_atx_tid, list);
|
||||
|
||||
- /*
|
||||
- * add tid to round-robin queue if more frames
|
||||
- * are pending for the tid
|
||||
- */
|
||||
- if (ath_tid_has_buffered(tid))
|
||||
- ath_tx_queue_tid(sc, txq, tid);
|
||||
+ if (active && tid->an->airtime_deficit[txq->mac80211_qnum] <= 0) {
|
||||
+ spin_lock_bh(&acq->lock);
|
||||
+ tid->an->airtime_deficit[txq->mac80211_qnum] += ATH_AIRTIME_QUANTUM;
|
||||
+ list_move_tail(&tid->list, &acq->acq_old);
|
||||
+ spin_unlock_bh(&acq->lock);
|
||||
+ goto begin;
|
||||
+ }
|
||||
|
||||
- if (stop)
|
||||
- break;
|
||||
+ if (!ath_tid_has_buffered(tid)) {
|
||||
+ spin_lock_bh(&acq->lock);
|
||||
+ if ((tid_list == &acq->acq_new) && !list_empty(&acq->acq_old))
|
||||
+ list_move_tail(&tid->list, &acq->acq_old);
|
||||
+ else {
|
||||
+ list_del_init(&tid->list);
|
||||
+ }
|
||||
+ spin_unlock_bh(&acq->lock);
|
||||
+ goto begin;
|
||||
+ }
|
||||
|
||||
- if (tid == last_tid) {
|
||||
- if (!sent)
|
||||
- break;
|
||||
|
||||
- sent = false;
|
||||
- last_tid = list_entry(tid_list->prev,
|
||||
- struct ath_atx_tid, list);
|
||||
+ /*
|
||||
+ * If we succeed in scheduling something, immediately restart to make
|
||||
+ * sure we keep the HW busy.
|
||||
+ */
|
||||
+ if(ath_tx_sched_aggr(sc, txq, tid)) {
|
||||
+ if (!active) {
|
||||
+ spin_lock_bh(&acq->lock);
|
||||
+ list_move_tail(&tid->list, &acq->acq_old);
|
||||
+ spin_unlock_bh(&acq->lock);
|
||||
}
|
||||
+ goto begin;
|
||||
}
|
||||
|
||||
+out:
|
||||
rcu_read_unlock();
|
||||
spin_unlock_bh(&sc->chan_lock);
|
||||
}
|
||||
@@ -2862,6 +2940,9 @@ void ath_tx_node_init(struct ath_softc *
|
||||
struct ath_atx_tid *tid;
|
||||
int tidno, acno;
|
||||
|
||||
+ for (acno = 0; acno < IEEE80211_NUM_ACS; acno++)
|
||||
+ an->airtime_deficit[acno] = ATH_AIRTIME_QUANTUM;
|
||||
+
|
||||
for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
|
||||
tid = ath_node_to_tid(an, tidno);
|
||||
tid->an = an;
|
|
@ -1,62 +0,0 @@
|
|||
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
|
||||
Date: Mon, 5 Dec 2016 13:27:38 +0200
|
||||
Subject: [PATCH] ath9k: Turn ath_txq_lock/unlock() into static inlines.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
These are one-line functions that just call spin_lock/unlock_bh(); turn
|
||||
them into static inlines to avoid the function call overhead.
|
||||
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
|
||||
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -569,6 +569,15 @@ static inline void ath_chanctx_check_act
|
||||
|
||||
#endif /* CPTCFG_ATH9K_CHANNEL_CONTEXT */
|
||||
|
||||
+static inline void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
|
||||
+{
|
||||
+ spin_lock_bh(&txq->axq_lock);
|
||||
+}
|
||||
+static inline void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
|
||||
+{
|
||||
+ spin_unlock_bh(&txq->axq_lock);
|
||||
+}
|
||||
+
|
||||
void ath_startrecv(struct ath_softc *sc);
|
||||
bool ath_stoprecv(struct ath_softc *sc);
|
||||
u32 ath_calcrxfilter(struct ath_softc *sc);
|
||||
@@ -576,8 +585,6 @@ int ath_rx_init(struct ath_softc *sc, in
|
||||
void ath_rx_cleanup(struct ath_softc *sc);
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
|
||||
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
|
||||
-void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq);
|
||||
-void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq);
|
||||
void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq);
|
||||
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
|
||||
bool ath_drain_all_txq(struct ath_softc *sc);
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -98,18 +98,6 @@ static void ath_tx_status(struct ieee802
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
-void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
|
||||
- __acquires(&txq->axq_lock)
|
||||
-{
|
||||
- spin_lock_bh(&txq->axq_lock);
|
||||
-}
|
||||
-
|
||||
-void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
|
||||
- __releases(&txq->axq_lock)
|
||||
-{
|
||||
- spin_unlock_bh(&txq->axq_lock);
|
||||
-}
|
||||
-
|
||||
void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
|
||||
__releases(&txq->axq_lock)
|
||||
{
|
|
@ -1,23 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Tue, 27 Dec 2016 12:15:14 +0100
|
||||
Subject: [PATCH] ath5k: drop bogus warning on drv_set_key with unsupported
|
||||
cipher
|
||||
|
||||
Simply return -EOPNOTSUPP instead.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
|
||||
@@ -502,8 +502,7 @@ ath5k_set_key(struct ieee80211_hw *hw, e
|
||||
break;
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
- WARN_ON(1);
|
||||
- return -EINVAL;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&ah->lock);
|
|
@ -1,101 +0,0 @@
|
|||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Wed, 4 Jan 2017 18:58:30 +0100
|
||||
Subject: [PATCH] cfg80211: move function checking range fit to util.c
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It is needed for another cfg80211 helper that will be out of reg.c so
|
||||
move it to common util.c file and make it non-static.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/wireless/core.h
|
||||
+++ b/net/wireless/core.h
|
||||
@@ -429,6 +429,9 @@ int cfg80211_change_iface(struct cfg8021
|
||||
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
|
||||
void cfg80211_process_wdev_events(struct wireless_dev *wdev);
|
||||
|
||||
+bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
|
||||
+ u32 center_freq_khz, u32 bw_khz);
|
||||
+
|
||||
/**
|
||||
* cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
|
||||
* @wiphy: the wiphy to validate against
|
||||
--- a/net/wireless/reg.c
|
||||
+++ b/net/wireless/reg.c
|
||||
@@ -748,21 +748,6 @@ static bool is_valid_rd(const struct iee
|
||||
return true;
|
||||
}
|
||||
|
||||
-static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range,
|
||||
- u32 center_freq_khz, u32 bw_khz)
|
||||
-{
|
||||
- u32 start_freq_khz, end_freq_khz;
|
||||
-
|
||||
- start_freq_khz = center_freq_khz - (bw_khz/2);
|
||||
- end_freq_khz = center_freq_khz + (bw_khz/2);
|
||||
-
|
||||
- if (start_freq_khz >= freq_range->start_freq_khz &&
|
||||
- end_freq_khz <= freq_range->end_freq_khz)
|
||||
- return true;
|
||||
-
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
/**
|
||||
* freq_in_rule_band - tells us if a frequency is in a frequency band
|
||||
* @freq_range: frequency rule we want to query
|
||||
@@ -1070,7 +1055,7 @@ freq_reg_info_regd(u32 center_freq,
|
||||
if (!band_rule_found)
|
||||
band_rule_found = freq_in_rule_band(fr, center_freq);
|
||||
|
||||
- bw_fits = reg_does_bw_fit(fr, center_freq, bw);
|
||||
+ bw_fits = cfg80211_does_bw_fit_range(fr, center_freq, bw);
|
||||
|
||||
if (band_rule_found && bw_fits)
|
||||
return rr;
|
||||
@@ -1138,11 +1123,13 @@ static uint32_t reg_rule_to_chan_bw_flag
|
||||
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
||||
|
||||
/* If we get a reg_rule we can assume that at least 5Mhz fit */
|
||||
- if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
|
||||
- MHZ_TO_KHZ(10)))
|
||||
+ if (!cfg80211_does_bw_fit_range(freq_range,
|
||||
+ MHZ_TO_KHZ(chan->center_freq),
|
||||
+ MHZ_TO_KHZ(10)))
|
||||
bw_flags |= IEEE80211_CHAN_NO_10MHZ;
|
||||
- if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
|
||||
- MHZ_TO_KHZ(20)))
|
||||
+ if (!cfg80211_does_bw_fit_range(freq_range,
|
||||
+ MHZ_TO_KHZ(chan->center_freq),
|
||||
+ MHZ_TO_KHZ(20)))
|
||||
bw_flags |= IEEE80211_CHAN_NO_20MHZ;
|
||||
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(10))
|
||||
--- a/net/wireless/util.c
|
||||
+++ b/net/wireless/util.c
|
||||
@@ -1788,6 +1788,21 @@ void cfg80211_free_nan_func(struct cfg80
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_free_nan_func);
|
||||
|
||||
+bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
|
||||
+ u32 center_freq_khz, u32 bw_khz)
|
||||
+{
|
||||
+ u32 start_freq_khz, end_freq_khz;
|
||||
+
|
||||
+ start_freq_khz = center_freq_khz - (bw_khz / 2);
|
||||
+ end_freq_khz = center_freq_khz + (bw_khz / 2);
|
||||
+
|
||||
+ if (start_freq_khz >= freq_range->start_freq_khz &&
|
||||
+ end_freq_khz <= freq_range->end_freq_khz)
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
|
||||
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
|
||||
const unsigned char rfc1042_header[] __aligned(2) =
|
|
@ -1,211 +0,0 @@
|
|||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Wed, 4 Jan 2017 18:58:31 +0100
|
||||
Subject: [PATCH] cfg80211: support ieee80211-freq-limit DT property
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This patch adds a helper for reading that new property and applying
|
||||
limitations of supported channels specified this way.
|
||||
It is used with devices that normally support a wide wireless band but
|
||||
in a given config are limited to some part of it (usually due to board
|
||||
design). For example a dual-band chipset may be able to support one band
|
||||
only because of used antennas.
|
||||
It's also common that tri-band routers have separated radios for lower
|
||||
and higher part of 5 GHz band and it may be impossible to say which is
|
||||
which without a DT info.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
[add new function to documentation, fix link]
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
create mode 100644 net/wireless/of.c
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -311,6 +311,34 @@ struct ieee80211_supported_band {
|
||||
struct ieee80211_sta_vht_cap vht_cap;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * wiphy_read_of_freq_limits - read frequency limits from device tree
|
||||
+ *
|
||||
+ * @wiphy: the wireless device to get extra limits for
|
||||
+ *
|
||||
+ * Some devices may have extra limitations specified in DT. This may be useful
|
||||
+ * for chipsets that normally support more bands but are limited due to board
|
||||
+ * design (e.g. by antennas or external power amplifier).
|
||||
+ *
|
||||
+ * This function reads info from DT and uses it to *modify* channels (disable
|
||||
+ * unavailable ones). It's usually a *bad* idea to use it in drivers with
|
||||
+ * shared channel data as DT limitations are device specific. You should make
|
||||
+ * sure to call it only if channels in wiphy are copied and can be modified
|
||||
+ * without affecting other devices.
|
||||
+ *
|
||||
+ * As this function access device node it has to be called after set_wiphy_dev.
|
||||
+ * It also modifies channels so they have to be set first.
|
||||
+ * If using this helper, call it before wiphy_register().
|
||||
+ */
|
||||
+#ifdef CONFIG_OF
|
||||
+void wiphy_read_of_freq_limits(struct wiphy *wiphy);
|
||||
+#else /* CONFIG_OF */
|
||||
+static inline void wiphy_read_of_freq_limits(struct wiphy *wiphy)
|
||||
+{
|
||||
+}
|
||||
+#endif /* !CONFIG_OF */
|
||||
+
|
||||
+
|
||||
/*
|
||||
* Wireless hardware/device configuration structures and methods
|
||||
*/
|
||||
--- a/net/wireless/Makefile
|
||||
+++ b/net/wireless/Makefile
|
||||
@@ -11,6 +11,7 @@ obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
|
||||
|
||||
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
|
||||
cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o
|
||||
+cfg80211-$(CONFIG_OF) += of.o
|
||||
cfg80211-$(CPTCFG_CFG80211_DEBUGFS) += debugfs.o
|
||||
cfg80211-$(CPTCFG_CFG80211_WEXT) += wext-compat.o wext-sme.o
|
||||
cfg80211-$(CPTCFG_CFG80211_INTERNAL_REGDB) += regdb.o
|
||||
--- /dev/null
|
||||
+++ b/net/wireless/of.c
|
||||
@@ -0,0 +1,138 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and/or distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/of.h>
|
||||
+#include <net/cfg80211.h>
|
||||
+#include "core.h"
|
||||
+
|
||||
+static bool wiphy_freq_limits_valid_chan(struct wiphy *wiphy,
|
||||
+ struct ieee80211_freq_range *freq_limits,
|
||||
+ unsigned int n_freq_limits,
|
||||
+ struct ieee80211_channel *chan)
|
||||
+{
|
||||
+ u32 bw = MHZ_TO_KHZ(20);
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < n_freq_limits; i++) {
|
||||
+ struct ieee80211_freq_range *limit = &freq_limits[i];
|
||||
+
|
||||
+ if (cfg80211_does_bw_fit_range(limit,
|
||||
+ MHZ_TO_KHZ(chan->center_freq),
|
||||
+ bw))
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static void wiphy_freq_limits_apply(struct wiphy *wiphy,
|
||||
+ struct ieee80211_freq_range *freq_limits,
|
||||
+ unsigned int n_freq_limits)
|
||||
+{
|
||||
+ enum nl80211_band band;
|
||||
+ int i;
|
||||
+
|
||||
+ if (WARN_ON(!n_freq_limits))
|
||||
+ return;
|
||||
+
|
||||
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
||||
+ struct ieee80211_supported_band *sband = wiphy->bands[band];
|
||||
+
|
||||
+ if (!sband)
|
||||
+ continue;
|
||||
+
|
||||
+ for (i = 0; i < sband->n_channels; i++) {
|
||||
+ struct ieee80211_channel *chan = &sband->channels[i];
|
||||
+
|
||||
+ if (chan->flags & IEEE80211_CHAN_DISABLED)
|
||||
+ continue;
|
||||
+
|
||||
+ if (!wiphy_freq_limits_valid_chan(wiphy, freq_limits,
|
||||
+ n_freq_limits,
|
||||
+ chan)) {
|
||||
+ pr_debug("Disabling freq %d MHz as it's out of OF limits\n",
|
||||
+ chan->center_freq);
|
||||
+ chan->flags |= IEEE80211_CHAN_DISABLED;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void wiphy_read_of_freq_limits(struct wiphy *wiphy)
|
||||
+{
|
||||
+ struct device *dev = wiphy_dev(wiphy);
|
||||
+ struct device_node *np;
|
||||
+ struct property *prop;
|
||||
+ struct ieee80211_freq_range *freq_limits;
|
||||
+ unsigned int n_freq_limits;
|
||||
+ const __be32 *p;
|
||||
+ int len, i;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (!dev)
|
||||
+ return;
|
||||
+ np = dev_of_node(dev);
|
||||
+ if (!np)
|
||||
+ return;
|
||||
+
|
||||
+ prop = of_find_property(np, "ieee80211-freq-limit", &len);
|
||||
+ if (!prop)
|
||||
+ return;
|
||||
+
|
||||
+ if (!len || len % sizeof(u32) || len / sizeof(u32) % 2) {
|
||||
+ dev_err(dev, "ieee80211-freq-limit wrong format");
|
||||
+ return;
|
||||
+ }
|
||||
+ n_freq_limits = len / sizeof(u32) / 2;
|
||||
+
|
||||
+ freq_limits = kcalloc(n_freq_limits, sizeof(*freq_limits), GFP_KERNEL);
|
||||
+ if (!freq_limits) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto out_kfree;
|
||||
+ }
|
||||
+
|
||||
+ p = NULL;
|
||||
+ for (i = 0; i < n_freq_limits; i++) {
|
||||
+ struct ieee80211_freq_range *limit = &freq_limits[i];
|
||||
+
|
||||
+ p = of_prop_next_u32(prop, p, &limit->start_freq_khz);
|
||||
+ if (!p) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out_kfree;
|
||||
+ }
|
||||
+
|
||||
+ p = of_prop_next_u32(prop, p, &limit->end_freq_khz);
|
||||
+ if (!p) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out_kfree;
|
||||
+ }
|
||||
+
|
||||
+ if (!limit->start_freq_khz ||
|
||||
+ !limit->end_freq_khz ||
|
||||
+ limit->start_freq_khz >= limit->end_freq_khz) {
|
||||
+ err = -EINVAL;
|
||||
+ goto out_kfree;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ wiphy_freq_limits_apply(wiphy, freq_limits, n_freq_limits);
|
||||
+
|
||||
+out_kfree:
|
||||
+ kfree(freq_limits);
|
||||
+ if (err)
|
||||
+ dev_err(dev, "Failed to get limits: %d\n", err);
|
||||
+}
|
||||
+EXPORT_SYMBOL(wiphy_read_of_freq_limits);
|
|
@ -1,41 +0,0 @@
|
|||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 11 Jan 2017 23:30:20 +0100
|
||||
Subject: [PATCH] mac80211: initialize SMPS field in HT capabilities
|
||||
|
||||
ibss and mesh modes copy the ht capabilites from the band without
|
||||
overriding the SMPS state. Unfortunately the default value 0 for the
|
||||
SMPS field means static SMPS instead of disabled.
|
||||
|
||||
This results in HT ibss and mesh setups using only single-stream rates,
|
||||
even though SMPS is not supposed to be active.
|
||||
|
||||
Initialize SMPS to disabled for all bands on ieee80211_hw_register to
|
||||
ensure that the value is sane where it is not overriden with the real
|
||||
SMPS state.
|
||||
|
||||
Reported-by: Elektra Wagenrad <onelektra@gmx.net>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -908,10 +908,15 @@ int ieee80211_register_hw(struct ieee802
|
||||
supp_ht = supp_ht || sband->ht_cap.ht_supported;
|
||||
supp_vht = supp_vht || sband->vht_cap.vht_supported;
|
||||
|
||||
- if (sband->ht_cap.ht_supported)
|
||||
- local->rx_chains =
|
||||
- max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
|
||||
- local->rx_chains);
|
||||
+ if (!sband->ht_cap.ht_supported)
|
||||
+ continue;
|
||||
+
|
||||
+ local->rx_chains =
|
||||
+ max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
|
||||
+ local->rx_chains);
|
||||
+
|
||||
+ sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
|
||||
+ IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||
|
||||
/* TODO: consider VHT for RX chains, hopefully it's the same */
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
From a17d93ff3a950fefaea40e4a4bf3669b9137c533 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Greear <greearb@candelatech.com>
|
||||
Date: Wed, 14 Dec 2016 11:30:38 -0800
|
||||
Subject: [PATCH] mac80211: fix legacy and invalid rx-rate report
|
||||
|
||||
This fixes obtaining the rate info via sta_set_sinfo
|
||||
when the rx rate is invalid (for instance, on IBSS
|
||||
interface that has received no frames from one of its
|
||||
peers).
|
||||
|
||||
Also initialize rinfo->flags for legacy rates, to not
|
||||
rely on the whole sinfo being initialized to zero.
|
||||
|
||||
Signed-off-by: Ben Greear <greearb@candelatech.com>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
net/mac80211/sta_info.c | 14 ++++++++------
|
||||
1 file changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/net/mac80211/sta_info.c
|
||||
+++ b/net/mac80211/sta_info.c
|
||||
@@ -1975,6 +1975,7 @@ static void sta_stats_decode_rate(struct
|
||||
u16 brate;
|
||||
unsigned int shift;
|
||||
|
||||
+ rinfo->flags = 0;
|
||||
sband = local->hw.wiphy->bands[(rate >> 4) & 0xf];
|
||||
brate = sband->bitrates[rate & 0xf].bitrate;
|
||||
if (rinfo->bw == RATE_INFO_BW_5)
|
||||
@@ -1990,14 +1991,15 @@ static void sta_stats_decode_rate(struct
|
||||
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
}
|
||||
|
||||
-static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
|
||||
+static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
|
||||
{
|
||||
u16 rate = ACCESS_ONCE(sta_get_last_rx_stats(sta)->last_rate);
|
||||
|
||||
if (rate == STA_STATS_RATE_INVALID)
|
||||
- rinfo->flags = 0;
|
||||
- else
|
||||
- sta_stats_decode_rate(sta->local, rate, rinfo);
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ sta_stats_decode_rate(sta->local, rate, rinfo);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void sta_set_tidstats(struct sta_info *sta,
|
||||
@@ -2202,8 +2204,8 @@ void sta_set_sinfo(struct sta_info *sta,
|
||||
}
|
||||
|
||||
if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE))) {
|
||||
- sta_set_rate_info_rx(sta, &sinfo->rxrate);
|
||||
- sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
|
||||
+ if (sta_set_rate_info_rx(sta, &sinfo->rxrate) == 0)
|
||||
+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
|
||||
}
|
||||
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TID_STATS);
|
|
@ -1,41 +0,0 @@
|
|||
From 35f432a03e41d3bf08c51ede917f94e2288fbe8c Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Mon, 2 Jan 2017 11:19:29 +0100
|
||||
Subject: [PATCH] mac80211: initialize fast-xmit 'info' later
|
||||
|
||||
In ieee80211_xmit_fast(), 'info' is initialized to point to the skb
|
||||
that's passed in, but that skb may later be replaced by a clone (if
|
||||
it was shared), leading to an invalid pointer.
|
||||
|
||||
This can lead to use-after-free and also later crashes since the
|
||||
real SKB's info->hw_queue doesn't get initialized properly.
|
||||
|
||||
Fix this by assigning info only later, when it's needed, after the
|
||||
skb replacement (may have) happened.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Reported-by: Ben Greear <greearb@candelatech.com>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
net/mac80211/tx.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3297,7 +3297,7 @@ static bool ieee80211_xmit_fast(struct i
|
||||
int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
|
||||
int hw_headroom = sdata->local->hw.extra_tx_headroom;
|
||||
struct ethhdr eth;
|
||||
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
+ struct ieee80211_tx_info *info;
|
||||
struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
|
||||
struct ieee80211_tx_data tx;
|
||||
ieee80211_tx_result r;
|
||||
@@ -3361,6 +3361,7 @@ static bool ieee80211_xmit_fast(struct i
|
||||
memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
|
||||
memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
|
||||
|
||||
+ info = IEEE80211_SKB_CB(skb);
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->band = fast_tx->band;
|
||||
info->control.vif = &sdata->vif;
|
|
@ -1,99 +0,0 @@
|
|||
From 1c3d185a9a0b136a58e73b02912d593d0303d1da Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Tue, 18 Oct 2016 23:12:08 +0300
|
||||
Subject: [PATCH] mac80211: fix tid_agg_rx NULL dereference
|
||||
|
||||
On drivers setting the SUPPORTS_REORDERING_BUFFER hardware flag,
|
||||
we crash when the peer sends an AddBA request while we already
|
||||
have a session open on the seame TID; this is because on those
|
||||
drivers, the tid_agg_rx is left NULL even though the session is
|
||||
valid, and the agg_session_valid bit is set.
|
||||
|
||||
To fix this, store the dialog tokens outside the tid_agg_rx to
|
||||
be able to compare them to the received AddBA request.
|
||||
|
||||
Fixes: f89e07d4cf26 ("mac80211: agg-rx: refuse ADDBA Request with timeout update")
|
||||
Reported-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
net/mac80211/agg-rx.c | 8 ++------
|
||||
net/mac80211/debugfs_sta.c | 2 +-
|
||||
net/mac80211/sta_info.h | 4 ++--
|
||||
3 files changed, 5 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/net/mac80211/agg-rx.c
|
||||
+++ b/net/mac80211/agg-rx.c
|
||||
@@ -315,11 +315,7 @@ void __ieee80211_start_rx_ba_session(str
|
||||
mutex_lock(&sta->ampdu_mlme.mtx);
|
||||
|
||||
if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
|
||||
- tid_agg_rx = rcu_dereference_protected(
|
||||
- sta->ampdu_mlme.tid_rx[tid],
|
||||
- lockdep_is_held(&sta->ampdu_mlme.mtx));
|
||||
-
|
||||
- if (tid_agg_rx->dialog_token == dialog_token) {
|
||||
+ if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
|
||||
ht_dbg_ratelimited(sta->sdata,
|
||||
"updated AddBA Req from %pM on tid %u\n",
|
||||
sta->sta.addr, tid);
|
||||
@@ -396,7 +392,6 @@ void __ieee80211_start_rx_ba_session(str
|
||||
}
|
||||
|
||||
/* update data */
|
||||
- tid_agg_rx->dialog_token = dialog_token;
|
||||
tid_agg_rx->ssn = start_seq_num;
|
||||
tid_agg_rx->head_seq_num = start_seq_num;
|
||||
tid_agg_rx->buf_size = buf_size;
|
||||
@@ -418,6 +413,7 @@ end:
|
||||
if (status == WLAN_STATUS_SUCCESS) {
|
||||
__set_bit(tid, sta->ampdu_mlme.agg_session_valid);
|
||||
__clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
|
||||
+ sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
|
||||
}
|
||||
mutex_unlock(&sta->ampdu_mlme.mtx);
|
||||
|
||||
--- a/net/mac80211/debugfs_sta.c
|
||||
+++ b/net/mac80211/debugfs_sta.c
|
||||
@@ -205,7 +205,7 @@ static ssize_t sta_agg_status_read(struc
|
||||
p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
|
||||
p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_rx);
|
||||
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
|
||||
- tid_rx ? tid_rx->dialog_token : 0);
|
||||
+ tid_rx ? sta->ampdu_mlme.tid_rx_token[i] : 0);
|
||||
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
|
||||
tid_rx ? tid_rx->ssn : 0);
|
||||
|
||||
--- a/net/mac80211/sta_info.h
|
||||
+++ b/net/mac80211/sta_info.h
|
||||
@@ -184,7 +184,6 @@ struct tid_ampdu_tx {
|
||||
* @ssn: Starting Sequence Number expected to be aggregated.
|
||||
* @buf_size: buffer size for incoming A-MPDUs
|
||||
* @timeout: reset timer value (in TUs).
|
||||
- * @dialog_token: dialog token for aggregation session
|
||||
* @rcu_head: RCU head used for freeing this struct
|
||||
* @reorder_lock: serializes access to reorder buffer, see below.
|
||||
* @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and
|
||||
@@ -213,7 +212,6 @@ struct tid_ampdu_rx {
|
||||
u16 ssn;
|
||||
u16 buf_size;
|
||||
u16 timeout;
|
||||
- u8 dialog_token;
|
||||
bool auto_seq;
|
||||
bool removed;
|
||||
};
|
||||
@@ -225,6 +223,7 @@ struct tid_ampdu_rx {
|
||||
* to tid_tx[idx], which are protected by the sta spinlock)
|
||||
* tid_start_tx is also protected by sta->lock.
|
||||
* @tid_rx: aggregation info for Rx per TID -- RCU protected
|
||||
+ * @tid_rx_token: dialog tokens for valid aggregation sessions
|
||||
* @tid_rx_timer_expired: bitmap indicating on which TIDs the
|
||||
* RX timer expired until the work for it runs
|
||||
* @tid_rx_stop_requested: bitmap indicating which BA sessions per TID the
|
||||
@@ -243,6 +242,7 @@ struct sta_ampdu_mlme {
|
||||
struct mutex mtx;
|
||||
/* rx */
|
||||
struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS];
|
||||
+ u8 tid_rx_token[IEEE80211_NUM_TIDS];
|
||||
unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
|
||||
unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
|
||||
unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
|
|
@ -1,107 +0,0 @@
|
|||
From: Michal Kazior <michal.kazior@tieto.com>
|
||||
Date: Fri, 13 Jan 2017 13:32:51 +0100
|
||||
Subject: [PATCH] mac80211: prevent skb/txq mismatch
|
||||
|
||||
Station structure is considered as not uploaded
|
||||
(to driver) until drv_sta_state() finishes. This
|
||||
call is however done after the structure is
|
||||
attached to mac80211 internal lists and hashes.
|
||||
This means mac80211 can lookup (and use) station
|
||||
structure before it is uploaded to a driver.
|
||||
|
||||
If this happens (structure exists, but
|
||||
sta->uploaded is false) fast_tx path can still be
|
||||
taken. Deep in the fastpath call the sta->uploaded
|
||||
is checked against to derive "pubsta" argument for
|
||||
ieee80211_get_txq(). If sta->uploaded is false
|
||||
(and sta is actually non-NULL) ieee80211_get_txq()
|
||||
effectively downgraded to vif->txq.
|
||||
|
||||
At first glance this may look innocent but coerces
|
||||
mac80211 into a state that is almost guaranteed
|
||||
(codel may drop offending skb) to crash because a
|
||||
station-oriented skb gets queued up on
|
||||
vif-oriented txq. The ieee80211_tx_dequeue() ends
|
||||
up looking at info->control.flags and tries to use
|
||||
txq->sta which in the fail case is NULL.
|
||||
|
||||
It's probably pointless to pretend one can
|
||||
downgrade skb from sta-txq to vif-txq.
|
||||
|
||||
Since downgrading unicast traffic to vif->txq must
|
||||
not be done there's no txq to put a frame on if
|
||||
sta->uploaded is false. Therefore the code is made
|
||||
to fall back to regular tx() op path if the
|
||||
described condition is hit.
|
||||
|
||||
Only drivers using wake_tx_queue were affected.
|
||||
|
||||
Example crash dump before fix:
|
||||
|
||||
Unable to handle kernel paging request at virtual address ffffe26c
|
||||
PC is at ieee80211_tx_dequeue+0x204/0x690 [mac80211]
|
||||
[<bf4252a4>] (ieee80211_tx_dequeue [mac80211]) from
|
||||
[<bf4b1388>] (ath10k_mac_tx_push_txq+0x54/0x1c0 [ath10k_core])
|
||||
[<bf4b1388>] (ath10k_mac_tx_push_txq [ath10k_core]) from
|
||||
[<bf4bdfbc>] (ath10k_htt_txrx_compl_task+0xd78/0x11d0 [ath10k_core])
|
||||
[<bf4bdfbc>] (ath10k_htt_txrx_compl_task [ath10k_core])
|
||||
[<bf51c5a4>] (ath10k_pci_napi_poll+0x54/0xe8 [ath10k_pci])
|
||||
[<bf51c5a4>] (ath10k_pci_napi_poll [ath10k_pci]) from
|
||||
[<c0572e90>] (net_rx_action+0xac/0x160)
|
||||
|
||||
Reported-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
|
||||
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -798,7 +798,7 @@ static __le16 ieee80211_tx_next_seq(stru
|
||||
|
||||
static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
|
||||
struct ieee80211_vif *vif,
|
||||
- struct ieee80211_sta *pubsta,
|
||||
+ struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
@@ -812,10 +812,13 @@ static struct txq_info *ieee80211_get_tx
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
return NULL;
|
||||
|
||||
- if (pubsta) {
|
||||
+ if (sta) {
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
|
||||
- txq = pubsta->txq[tid];
|
||||
+ if (!sta->uploaded)
|
||||
+ return NULL;
|
||||
+
|
||||
+ txq = sta->sta.txq[tid];
|
||||
} else if (vif) {
|
||||
txq = vif->txq;
|
||||
}
|
||||
@@ -1503,23 +1506,17 @@ static bool ieee80211_queue_skb(struct i
|
||||
struct fq *fq = &local->fq;
|
||||
struct ieee80211_vif *vif;
|
||||
struct txq_info *txqi;
|
||||
- struct ieee80211_sta *pubsta;
|
||||
|
||||
if (!local->ops->wake_tx_queue ||
|
||||
sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
||||
return false;
|
||||
|
||||
- if (sta && sta->uploaded)
|
||||
- pubsta = &sta->sta;
|
||||
- else
|
||||
- pubsta = NULL;
|
||||
-
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
sdata = container_of(sdata->bss,
|
||||
struct ieee80211_sub_if_data, u.ap);
|
||||
|
||||
vif = &sdata->vif;
|
||||
- txqi = ieee80211_get_txq(local, vif, pubsta, skb);
|
||||
+ txqi = ieee80211_get_txq(local, vif, sta, skb);
|
||||
|
||||
if (!txqi)
|
||||
return false;
|
|
@ -1,43 +0,0 @@
|
|||
From d3532ea6ce4ea501e421d130555e59edc2945f99 Mon Sep 17 00:00:00 2001
|
||||
From: Arnd Bergmann <arnd@arndb.de>
|
||||
Date: Tue, 18 Oct 2016 00:13:40 +0200
|
||||
Subject: [PATCH] brcmfmac: avoid maybe-uninitialized warning in
|
||||
brcmf_cfg80211_start_ap
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
A bugfix added a sanity check around the assignment and use of the
|
||||
'is_11d' variable, which looks correct to me, but as the function is
|
||||
rather complex already, this confuses the compiler to the point where
|
||||
it can no longer figure out if the variable is always initialized
|
||||
correctly:
|
||||
|
||||
brcm80211/brcmfmac/cfg80211.c: In function ‘brcmf_cfg80211_start_ap’:
|
||||
brcm80211/brcmfmac/cfg80211.c:4586:10: error: ‘is_11d’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
|
||||
|
||||
This adds an initialization for the newly introduced case in which
|
||||
the variable should not really be used, in order to make the warning
|
||||
go away.
|
||||
|
||||
Fixes: b3589dfe0212 ("brcmfmac: ignore 11d configuration errors")
|
||||
Cc: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Cc: Kalle Valo <kvalo@codeaurora.org>
|
||||
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -4516,7 +4516,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
|
||||
/* store current 11d setting */
|
||||
if (brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_REGULATORY,
|
||||
&ifp->vif->is_11d)) {
|
||||
- supports_11d = false;
|
||||
+ is_11d = supports_11d = false;
|
||||
} else {
|
||||
country_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
|
||||
settings->beacon.tail_len,
|
|
@ -1,174 +0,0 @@
|
|||
From b073ac1fcf42376018f6db6acc885dfd2cc9ff02 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Mon, 26 Sep 2016 23:51:44 +0200
|
||||
Subject: [PATCH] brcmfmac: proto: add callback for queuing TX data
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
So far our core code was calling brcmf_fws_process_skb which wasn't
|
||||
a proper thing to do. If case of devices using msgbuf protocol fwsignal
|
||||
shouldn't be used. It was an unnecessary extra layer simply calling
|
||||
a protocol specifix txdata function.
|
||||
|
||||
Please note we already have txdata callback, but it's used for calls
|
||||
between bcdc and fwsignal so it couldn't be simply used there.
|
||||
|
||||
This makes core code more generic (instead of bcdc/fwsignal specific).
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 12 ++++++++++++
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 8 +++++++-
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c | 15 +++++----------
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h | 1 +
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 6 +++---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c | 2 +-
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h | 9 +++++++++
|
||||
7 files changed, 38 insertions(+), 15 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
|
||||
@@ -326,6 +326,17 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int brcmf_proto_bcdc_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, ifidx);
|
||||
+
|
||||
+ if (!brcmf_fws_queue_skbs(drvr->fws))
|
||||
+ return brcmf_proto_txdata(drvr, ifidx, 0, skb);
|
||||
+
|
||||
+ return brcmf_fws_process_skb(ifp, skb);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
|
||||
struct sk_buff *pktbuf)
|
||||
@@ -375,6 +386,7 @@ int brcmf_proto_bcdc_attach(struct brcmf
|
||||
drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
|
||||
drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
|
||||
drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
|
||||
+ drvr->proto->tx_queue_data = brcmf_proto_bcdc_tx_queue_data;
|
||||
drvr->proto->txdata = brcmf_proto_bcdc_txdata;
|
||||
drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
|
||||
drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||
@@ -239,7 +239,13 @@ static netdev_tx_t brcmf_netdev_start_xm
|
||||
if (eh->h_proto == htons(ETH_P_PAE))
|
||||
atomic_inc(&ifp->pend_8021x_cnt);
|
||||
|
||||
- ret = brcmf_fws_process_skb(ifp, skb);
|
||||
+ /* determine the priority */
|
||||
+ if ((skb->priority == 0) || (skb->priority > 7))
|
||||
+ skb->priority = cfg80211_classify8021d(skb, NULL);
|
||||
+
|
||||
+ ret = brcmf_proto_tx_queue_data(drvr, ifp->ifidx, skb);
|
||||
+ if (ret < 0)
|
||||
+ brcmf_txfinalize(ifp, skb, false);
|
||||
|
||||
done:
|
||||
if (ret) {
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
|
||||
@@ -2100,16 +2100,6 @@ int brcmf_fws_process_skb(struct brcmf_i
|
||||
int rc = 0;
|
||||
|
||||
brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
|
||||
- /* determine the priority */
|
||||
- if ((skb->priority == 0) || (skb->priority > 7))
|
||||
- skb->priority = cfg80211_classify8021d(skb, NULL);
|
||||
-
|
||||
- if (fws->avoid_queueing) {
|
||||
- rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
|
||||
- if (rc < 0)
|
||||
- brcmf_txfinalize(ifp, skb, false);
|
||||
- return rc;
|
||||
- }
|
||||
|
||||
/* set control buffer information */
|
||||
skcb->if_flags = 0;
|
||||
@@ -2442,6 +2432,11 @@ void brcmf_fws_deinit(struct brcmf_pub *
|
||||
kfree(fws);
|
||||
}
|
||||
|
||||
+bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws)
|
||||
+{
|
||||
+ return !fws->avoid_queueing;
|
||||
+}
|
||||
+
|
||||
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
|
||||
{
|
||||
if (!fws->creditmap_received)
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
int brcmf_fws_init(struct brcmf_pub *drvr);
|
||||
void brcmf_fws_deinit(struct brcmf_pub *drvr);
|
||||
+bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws);
|
||||
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
|
||||
void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb);
|
||||
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -782,8 +782,8 @@ static int brcmf_msgbuf_schedule_txdata(
|
||||
}
|
||||
|
||||
|
||||
-static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx,
|
||||
- u8 offset, struct sk_buff *skb)
|
||||
+static int brcmf_msgbuf_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
|
||||
+ struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
|
||||
struct brcmf_flowring *flow = msgbuf->flow;
|
||||
@@ -1467,7 +1467,7 @@ int brcmf_proto_msgbuf_attach(struct brc
|
||||
drvr->proto->hdrpull = brcmf_msgbuf_hdrpull;
|
||||
drvr->proto->query_dcmd = brcmf_msgbuf_query_dcmd;
|
||||
drvr->proto->set_dcmd = brcmf_msgbuf_set_dcmd;
|
||||
- drvr->proto->txdata = brcmf_msgbuf_txdata;
|
||||
+ drvr->proto->tx_queue_data = brcmf_msgbuf_tx_queue_data;
|
||||
drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
|
||||
drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
|
||||
drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
|
||||
@@ -51,7 +51,7 @@ int brcmf_proto_attach(struct brcmf_pub
|
||||
drvr->bus_if->proto_type);
|
||||
goto fail;
|
||||
}
|
||||
- if ((proto->txdata == NULL) || (proto->hdrpull == NULL) ||
|
||||
+ if (!proto->tx_queue_data || (proto->hdrpull == NULL) ||
|
||||
(proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
|
||||
(proto->configure_addr_mode == NULL) ||
|
||||
(proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL)) {
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
|
||||
@@ -33,6 +33,8 @@ struct brcmf_proto {
|
||||
void *buf, uint len);
|
||||
int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
|
||||
uint len);
|
||||
+ int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx,
|
||||
+ struct sk_buff *skb);
|
||||
int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
|
||||
struct sk_buff *skb);
|
||||
void (*configure_addr_mode)(struct brcmf_pub *drvr, int ifidx,
|
||||
@@ -74,6 +76,13 @@ static inline int brcmf_proto_set_dcmd(s
|
||||
{
|
||||
return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
|
||||
}
|
||||
+
|
||||
+static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ return drvr->proto->tx_queue_data(drvr, ifidx, skb);
|
||||
+}
|
||||
+
|
||||
static inline int brcmf_proto_txdata(struct brcmf_pub *drvr, int ifidx,
|
||||
u8 offset, struct sk_buff *skb)
|
||||
{
|
|
@ -1,62 +0,0 @@
|
|||
From e1c122d55f9ec5608ca98a9a846fd39cdf3ed7d7 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Fri, 14 Oct 2016 09:45:59 +0200
|
||||
Subject: [PATCH] brcmfmac: print name of connect status event
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This simplifies debugging. Format %s (%u) comes from similar debugging
|
||||
message in brcmf_fweh_event_worker.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 ++-
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | 4 ++--
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h | 2 ++
|
||||
3 files changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -5506,7 +5506,8 @@ brcmf_notify_connect_status_ap(struct br
|
||||
u32 reason = e->reason;
|
||||
struct station_info sinfo;
|
||||
|
||||
- brcmf_dbg(CONN, "event %d, reason %d\n", event, reason);
|
||||
+ brcmf_dbg(CONN, "event %s (%u), reason %d\n",
|
||||
+ brcmf_fweh_event_name(event), event, reason);
|
||||
if (event == BRCMF_E_LINK && reason == BRCMF_E_REASON_LINK_BSSCFG_DIS &&
|
||||
ndev != cfg_to_ndev(cfg)) {
|
||||
brcmf_dbg(CONN, "AP mode link down\n");
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
|
||||
@@ -69,7 +69,7 @@ static struct brcmf_fweh_event_name fweh
|
||||
*
|
||||
* @code: code to lookup.
|
||||
*/
|
||||
-static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
|
||||
+const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(fweh_event_names); i++) {
|
||||
@@ -79,7 +79,7 @@ static const char *brcmf_fweh_event_name
|
||||
return "unknown";
|
||||
}
|
||||
#else
|
||||
-static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
|
||||
+const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
|
||||
{
|
||||
return "nodebug";
|
||||
}
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
|
||||
@@ -287,6 +287,8 @@ struct brcmf_fweh_info {
|
||||
void *data);
|
||||
};
|
||||
|
||||
+const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code);
|
||||
+
|
||||
void brcmf_fweh_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_fweh_detach(struct brcmf_pub *drvr);
|
||||
int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
|
|
@ -1,45 +0,0 @@
|
|||
From f25ba69c638b24097840a96bd3caf5599f9a3616 Mon Sep 17 00:00:00 2001
|
||||
From: Wright Feng <wefe@cypress.com>
|
||||
Date: Fri, 18 Nov 2016 09:59:52 +0800
|
||||
Subject: [PATCH] brcmfmac: update beacon IE after bss up and clear when AP
|
||||
stopped
|
||||
|
||||
Firmware doesn't update beacon/Probe Response vendor IEs correctly when
|
||||
bss is down, so we move brcmf_config_ap_mgmt_ie after BSS up. And host
|
||||
driver should clear IEs when AP stopped so that the IEs in host side will
|
||||
be synced with in firmware side.
|
||||
|
||||
Signed-off-by: Wright Feng <wright.feng@cypress.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -4578,8 +4578,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
|
||||
brcmf_configure_opensecurity(ifp);
|
||||
}
|
||||
|
||||
- brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
|
||||
-
|
||||
/* Parameters shared by all radio interfaces */
|
||||
if (!mbss) {
|
||||
if ((supports_11d) && (is_11d != ifp->vif->is_11d)) {
|
||||
@@ -4708,6 +4706,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
+ brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
|
||||
set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
|
||||
brcmf_net_setcarrier(ifp, true);
|
||||
|
||||
@@ -4764,6 +4763,8 @@ static int brcmf_cfg80211_stop_ap(struct
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
|
||||
if (err < 0)
|
||||
brcmf_err("BRCMF_C_UP error %d\n", err);
|
||||
+
|
||||
+ brcmf_vif_clear_mgmt_ies(ifp->vif);
|
||||
} else {
|
||||
bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);
|
||||
bss_enable.enable = cpu_to_le32(0);
|
|
@ -1,490 +0,0 @@
|
|||
From be4b092cab84b2ecc01ee7f4da6a044279430b6f Mon Sep 17 00:00:00 2001
|
||||
From: Franky Lin <franky.lin@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:20 +0000
|
||||
Subject: [PATCH] brcmfmac: add pcie host dongle interface rev6 support
|
||||
|
||||
In rev6 of pcie host dongle interface protocol, host needs to maximum
|
||||
supported ring number from dongle shared memory and set up ring buffer
|
||||
and ring indices offset accordingly.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 +-
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 38 +++--
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | 4 +
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 171 ++++++++++++---------
|
||||
4 files changed, 132 insertions(+), 91 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
|
||||
@@ -22,10 +22,12 @@
|
||||
/* IDs of the 6 default common rings of msgbuf protocol */
|
||||
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0
|
||||
#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT 1
|
||||
+#define BRCMF_H2D_MSGRING_FLOWRING_IDSTART 2
|
||||
#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE 2
|
||||
#define BRCMF_D2H_MSGRING_TX_COMPLETE 3
|
||||
#define BRCMF_D2H_MSGRING_RX_COMPLETE 4
|
||||
|
||||
+
|
||||
#define BRCMF_NROF_H2D_COMMON_MSGRINGS 2
|
||||
#define BRCMF_NROF_D2H_COMMON_MSGRINGS 3
|
||||
#define BRCMF_NROF_COMMON_MSGRINGS (BRCMF_NROF_H2D_COMMON_MSGRINGS + \
|
||||
@@ -95,14 +97,18 @@ struct brcmf_bus_ops {
|
||||
* @flowrings: commonrings which are dynamically created and destroyed for data.
|
||||
* @rx_dataoffset: if set then all rx data has this this offset.
|
||||
* @max_rxbufpost: maximum number of buffers to post for rx.
|
||||
- * @nrof_flowrings: number of flowrings.
|
||||
+ * @max_flowrings: maximum number of tx flow rings supported.
|
||||
+ * @max_submissionrings: maximum number of submission rings(h2d) supported.
|
||||
+ * @max_completionrings: maximum number of completion rings(d2h) supported.
|
||||
*/
|
||||
struct brcmf_bus_msgbuf {
|
||||
struct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
|
||||
struct brcmf_commonring **flowrings;
|
||||
u32 rx_dataoffset;
|
||||
u32 max_rxbufpost;
|
||||
- u32 nrof_flowrings;
|
||||
+ u16 max_flowrings;
|
||||
+ u16 max_submissionrings;
|
||||
+ u16 max_completionrings;
|
||||
};
|
||||
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -87,11 +87,6 @@ struct msgbuf_common_hdr {
|
||||
__le32 request_id;
|
||||
};
|
||||
|
||||
-struct msgbuf_buf_addr {
|
||||
- __le32 low_addr;
|
||||
- __le32 high_addr;
|
||||
-};
|
||||
-
|
||||
struct msgbuf_ioctl_req_hdr {
|
||||
struct msgbuf_common_hdr msg;
|
||||
__le32 cmd;
|
||||
@@ -227,7 +222,10 @@ struct brcmf_msgbuf {
|
||||
struct brcmf_commonring **commonrings;
|
||||
struct brcmf_commonring **flowrings;
|
||||
dma_addr_t *flowring_dma_handle;
|
||||
- u16 nrof_flowrings;
|
||||
+
|
||||
+ u16 max_flowrings;
|
||||
+ u16 max_submissionrings;
|
||||
+ u16 max_completionrings;
|
||||
|
||||
u16 rx_dataoffset;
|
||||
u32 max_rxbufpost;
|
||||
@@ -610,7 +608,7 @@ brcmf_msgbuf_flowring_create_worker(stru
|
||||
create->msg.request_id = 0;
|
||||
create->tid = brcmf_flowring_tid(msgbuf->flow, flowid);
|
||||
create->flow_ring_id = cpu_to_le16(flowid +
|
||||
- BRCMF_NROF_H2D_COMMON_MSGRINGS);
|
||||
+ BRCMF_H2D_MSGRING_FLOWRING_IDSTART);
|
||||
memcpy(create->sa, work->sa, ETH_ALEN);
|
||||
memcpy(create->da, work->da, ETH_ALEN);
|
||||
address = (u64)msgbuf->flowring_dma_handle[flowid];
|
||||
@@ -760,7 +758,7 @@ static void brcmf_msgbuf_txflow_worker(s
|
||||
u32 flowid;
|
||||
|
||||
msgbuf = container_of(worker, struct brcmf_msgbuf, txflow_work);
|
||||
- for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->nrof_flowrings) {
|
||||
+ for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->max_flowrings) {
|
||||
clear_bit(flowid, msgbuf->flow_map);
|
||||
brcmf_msgbuf_txflow(msgbuf, flowid);
|
||||
}
|
||||
@@ -866,7 +864,7 @@ brcmf_msgbuf_process_txstatus(struct brc
|
||||
tx_status = (struct msgbuf_tx_status *)buf;
|
||||
idx = le32_to_cpu(tx_status->msg.request_id);
|
||||
flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id);
|
||||
- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
|
||||
+ flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
|
||||
skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
|
||||
msgbuf->tx_pktids, idx);
|
||||
if (!skb)
|
||||
@@ -1174,7 +1172,7 @@ brcmf_msgbuf_process_flow_ring_create_re
|
||||
flowring_create_resp = (struct msgbuf_flowring_create_resp *)buf;
|
||||
|
||||
flowid = le16_to_cpu(flowring_create_resp->compl_hdr.flow_ring_id);
|
||||
- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
|
||||
+ flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
|
||||
status = le16_to_cpu(flowring_create_resp->compl_hdr.status);
|
||||
|
||||
if (status) {
|
||||
@@ -1202,7 +1200,7 @@ brcmf_msgbuf_process_flow_ring_delete_re
|
||||
flowring_delete_resp = (struct msgbuf_flowring_delete_resp *)buf;
|
||||
|
||||
flowid = le16_to_cpu(flowring_delete_resp->compl_hdr.flow_ring_id);
|
||||
- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
|
||||
+ flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
|
||||
status = le16_to_cpu(flowring_delete_resp->compl_hdr.status);
|
||||
|
||||
if (status) {
|
||||
@@ -1307,7 +1305,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct
|
||||
brcmf_msgbuf_process_rx(msgbuf, buf);
|
||||
|
||||
for_each_set_bit(flowid, msgbuf->txstatus_done_map,
|
||||
- msgbuf->nrof_flowrings) {
|
||||
+ msgbuf->max_flowrings) {
|
||||
clear_bit(flowid, msgbuf->txstatus_done_map);
|
||||
commonring = msgbuf->flowrings[flowid];
|
||||
qlen = brcmf_flowring_qlen(msgbuf->flow, flowid);
|
||||
@@ -1349,7 +1347,7 @@ void brcmf_msgbuf_delete_flowring(struct
|
||||
delete->msg.request_id = 0;
|
||||
|
||||
delete->flow_ring_id = cpu_to_le16(flowid +
|
||||
- BRCMF_NROF_H2D_COMMON_MSGRINGS);
|
||||
+ BRCMF_H2D_MSGRING_FLOWRING_IDSTART);
|
||||
delete->reason = 0;
|
||||
|
||||
brcmf_dbg(MSGBUF, "Send Flow Delete Req flow ID %d, ifindex %d\n",
|
||||
@@ -1427,10 +1425,10 @@ int brcmf_proto_msgbuf_attach(struct brc
|
||||
|
||||
if_msgbuf = drvr->bus_if->msgbuf;
|
||||
|
||||
- if (if_msgbuf->nrof_flowrings >= BRCMF_FLOWRING_HASHSIZE) {
|
||||
+ if (if_msgbuf->max_flowrings >= BRCMF_FLOWRING_HASHSIZE) {
|
||||
brcmf_err("driver not configured for this many flowrings %d\n",
|
||||
- if_msgbuf->nrof_flowrings);
|
||||
- if_msgbuf->nrof_flowrings = BRCMF_FLOWRING_HASHSIZE - 1;
|
||||
+ if_msgbuf->max_flowrings);
|
||||
+ if_msgbuf->max_flowrings = BRCMF_FLOWRING_HASHSIZE - 1;
|
||||
}
|
||||
|
||||
msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL);
|
||||
@@ -1443,7 +1441,7 @@ int brcmf_proto_msgbuf_attach(struct brc
|
||||
goto fail;
|
||||
}
|
||||
INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker);
|
||||
- count = BITS_TO_LONGS(if_msgbuf->nrof_flowrings);
|
||||
+ count = BITS_TO_LONGS(if_msgbuf->max_flowrings);
|
||||
count = count * sizeof(unsigned long);
|
||||
msgbuf->flow_map = kzalloc(count, GFP_KERNEL);
|
||||
if (!msgbuf->flow_map)
|
||||
@@ -1479,8 +1477,8 @@ int brcmf_proto_msgbuf_attach(struct brc
|
||||
msgbuf->commonrings =
|
||||
(struct brcmf_commonring **)if_msgbuf->commonrings;
|
||||
msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings;
|
||||
- msgbuf->nrof_flowrings = if_msgbuf->nrof_flowrings;
|
||||
- msgbuf->flowring_dma_handle = kzalloc(msgbuf->nrof_flowrings *
|
||||
+ msgbuf->max_flowrings = if_msgbuf->max_flowrings;
|
||||
+ msgbuf->flowring_dma_handle = kzalloc(msgbuf->max_flowrings *
|
||||
sizeof(*msgbuf->flowring_dma_handle), GFP_KERNEL);
|
||||
if (!msgbuf->flowring_dma_handle)
|
||||
goto fail;
|
||||
@@ -1501,7 +1499,7 @@ int brcmf_proto_msgbuf_attach(struct brc
|
||||
goto fail;
|
||||
|
||||
msgbuf->flow = brcmf_flowring_attach(drvr->bus_if->dev,
|
||||
- if_msgbuf->nrof_flowrings);
|
||||
+ if_msgbuf->max_flowrings);
|
||||
if (!msgbuf->flow)
|
||||
goto fail;
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
|
||||
@@ -31,6 +31,10 @@
|
||||
#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE 32
|
||||
#define BRCMF_H2D_TXFLOWRING_ITEMSIZE 48
|
||||
|
||||
+struct msgbuf_buf_addr {
|
||||
+ __le32 low_addr;
|
||||
+ __le32 high_addr;
|
||||
+};
|
||||
|
||||
int brcmf_proto_msgbuf_rx_trigger(struct device *dev);
|
||||
void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||||
@@ -135,7 +135,7 @@ static struct brcmf_firmware_mapping brc
|
||||
BRCMF_PCIE_MB_INT_D2H3_DB1)
|
||||
|
||||
#define BRCMF_PCIE_MIN_SHARED_VERSION 5
|
||||
-#define BRCMF_PCIE_MAX_SHARED_VERSION 5
|
||||
+#define BRCMF_PCIE_MAX_SHARED_VERSION 6
|
||||
#define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF
|
||||
#define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000
|
||||
#define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000
|
||||
@@ -166,17 +166,6 @@ static struct brcmf_firmware_mapping brc
|
||||
#define BRCMF_RING_MEM_SZ 16
|
||||
#define BRCMF_RING_STATE_SZ 8
|
||||
|
||||
-#define BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET 4
|
||||
-#define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET 8
|
||||
-#define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET 12
|
||||
-#define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET 16
|
||||
-#define BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET 20
|
||||
-#define BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET 28
|
||||
-#define BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET 36
|
||||
-#define BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET 44
|
||||
-#define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET 0
|
||||
-#define BRCMF_SHARED_RING_MAX_SUB_QUEUES 52
|
||||
-
|
||||
#define BRCMF_DEF_MAX_RXBUFPOST 255
|
||||
|
||||
#define BRCMF_CONSOLE_BUFADDR_OFFSET 8
|
||||
@@ -231,7 +220,9 @@ struct brcmf_pcie_shared_info {
|
||||
struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
|
||||
struct brcmf_pcie_ringbuf *flowrings;
|
||||
u16 max_rxbufpost;
|
||||
- u32 nrof_flowrings;
|
||||
+ u16 max_flowrings;
|
||||
+ u16 max_submissionrings;
|
||||
+ u16 max_completionrings;
|
||||
u32 rx_dataoffset;
|
||||
u32 htod_mb_data_addr;
|
||||
u32 dtoh_mb_data_addr;
|
||||
@@ -241,6 +232,7 @@ struct brcmf_pcie_shared_info {
|
||||
dma_addr_t scratch_dmahandle;
|
||||
void *ringupd;
|
||||
dma_addr_t ringupd_dmahandle;
|
||||
+ u8 version;
|
||||
};
|
||||
|
||||
struct brcmf_pcie_core_info {
|
||||
@@ -284,6 +276,36 @@ struct brcmf_pcie_ringbuf {
|
||||
u8 id;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * struct brcmf_pcie_dhi_ringinfo - dongle/host interface shared ring info
|
||||
+ *
|
||||
+ * @ringmem: dongle memory pointer to ring memory location
|
||||
+ * @h2d_w_idx_ptr: h2d ring write indices dongle memory pointers
|
||||
+ * @h2d_r_idx_ptr: h2d ring read indices dongle memory pointers
|
||||
+ * @d2h_w_idx_ptr: d2h ring write indices dongle memory pointers
|
||||
+ * @d2h_r_idx_ptr: d2h ring read indices dongle memory pointers
|
||||
+ * @h2d_w_idx_hostaddr: h2d ring write indices host memory pointers
|
||||
+ * @h2d_r_idx_hostaddr: h2d ring read indices host memory pointers
|
||||
+ * @d2h_w_idx_hostaddr: d2h ring write indices host memory pointers
|
||||
+ * @d2h_r_idx_hostaddr: d2h ring reaD indices host memory pointers
|
||||
+ * @max_flowrings: maximum number of tx flow rings supported.
|
||||
+ * @max_submissionrings: maximum number of submission rings(h2d) supported.
|
||||
+ * @max_completionrings: maximum number of completion rings(d2h) supported.
|
||||
+ */
|
||||
+struct brcmf_pcie_dhi_ringinfo {
|
||||
+ __le32 ringmem;
|
||||
+ __le32 h2d_w_idx_ptr;
|
||||
+ __le32 h2d_r_idx_ptr;
|
||||
+ __le32 d2h_w_idx_ptr;
|
||||
+ __le32 d2h_r_idx_ptr;
|
||||
+ struct msgbuf_buf_addr h2d_w_idx_hostaddr;
|
||||
+ struct msgbuf_buf_addr h2d_r_idx_hostaddr;
|
||||
+ struct msgbuf_buf_addr d2h_w_idx_hostaddr;
|
||||
+ struct msgbuf_buf_addr d2h_r_idx_hostaddr;
|
||||
+ __le16 max_flowrings;
|
||||
+ __le16 max_submissionrings;
|
||||
+ __le16 max_completionrings;
|
||||
+};
|
||||
|
||||
static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = {
|
||||
BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM,
|
||||
@@ -1054,26 +1076,35 @@ static int brcmf_pcie_init_ringbuffers(s
|
||||
{
|
||||
struct brcmf_pcie_ringbuf *ring;
|
||||
struct brcmf_pcie_ringbuf *rings;
|
||||
- u32 ring_addr;
|
||||
u32 d2h_w_idx_ptr;
|
||||
u32 d2h_r_idx_ptr;
|
||||
u32 h2d_w_idx_ptr;
|
||||
u32 h2d_r_idx_ptr;
|
||||
- u32 addr;
|
||||
u32 ring_mem_ptr;
|
||||
u32 i;
|
||||
u64 address;
|
||||
u32 bufsz;
|
||||
- u16 max_sub_queues;
|
||||
u8 idx_offset;
|
||||
-
|
||||
- ring_addr = devinfo->shared.ring_info_addr;
|
||||
- brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr);
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
|
||||
- max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
|
||||
+ struct brcmf_pcie_dhi_ringinfo ringinfo;
|
||||
+ u16 max_flowrings;
|
||||
+ u16 max_submissionrings;
|
||||
+ u16 max_completionrings;
|
||||
+
|
||||
+ memcpy_fromio(&ringinfo, devinfo->tcm + devinfo->shared.ring_info_addr,
|
||||
+ sizeof(ringinfo));
|
||||
+ if (devinfo->shared.version >= 6) {
|
||||
+ max_submissionrings = le16_to_cpu(ringinfo.max_submissionrings);
|
||||
+ max_flowrings = le16_to_cpu(ringinfo.max_flowrings);
|
||||
+ max_completionrings = le16_to_cpu(ringinfo.max_completionrings);
|
||||
+ } else {
|
||||
+ max_submissionrings = le16_to_cpu(ringinfo.max_flowrings);
|
||||
+ max_flowrings = max_submissionrings -
|
||||
+ BRCMF_NROF_H2D_COMMON_MSGRINGS;
|
||||
+ max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS;
|
||||
+ }
|
||||
|
||||
if (devinfo->dma_idx_sz != 0) {
|
||||
- bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) *
|
||||
+ bufsz = (max_submissionrings + max_completionrings) *
|
||||
devinfo->dma_idx_sz * 2;
|
||||
devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,
|
||||
&devinfo->idxbuf_dmahandle,
|
||||
@@ -1083,14 +1114,10 @@ static int brcmf_pcie_init_ringbuffers(s
|
||||
}
|
||||
|
||||
if (devinfo->dma_idx_sz == 0) {
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
|
||||
- d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
|
||||
- d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
|
||||
- h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
|
||||
- h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
+ d2h_w_idx_ptr = le32_to_cpu(ringinfo.d2h_w_idx_ptr);
|
||||
+ d2h_r_idx_ptr = le32_to_cpu(ringinfo.d2h_r_idx_ptr);
|
||||
+ h2d_w_idx_ptr = le32_to_cpu(ringinfo.h2d_w_idx_ptr);
|
||||
+ h2d_r_idx_ptr = le32_to_cpu(ringinfo.h2d_r_idx_ptr);
|
||||
idx_offset = sizeof(u32);
|
||||
devinfo->write_ptr = brcmf_pcie_write_tcm16;
|
||||
devinfo->read_ptr = brcmf_pcie_read_tcm16;
|
||||
@@ -1103,34 +1130,42 @@ static int brcmf_pcie_init_ringbuffers(s
|
||||
devinfo->read_ptr = brcmf_pcie_read_idx;
|
||||
|
||||
h2d_w_idx_ptr = 0;
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET;
|
||||
address = (u64)devinfo->idxbuf_dmahandle;
|
||||
- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
|
||||
- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
|
||||
-
|
||||
- h2d_r_idx_ptr = h2d_w_idx_ptr + max_sub_queues * idx_offset;
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET;
|
||||
- address += max_sub_queues * idx_offset;
|
||||
- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
|
||||
- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
|
||||
-
|
||||
- d2h_w_idx_ptr = h2d_r_idx_ptr + max_sub_queues * idx_offset;
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET;
|
||||
- address += max_sub_queues * idx_offset;
|
||||
- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
|
||||
- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
|
||||
+ ringinfo.h2d_w_idx_hostaddr.low_addr =
|
||||
+ cpu_to_le32(address & 0xffffffff);
|
||||
+ ringinfo.h2d_w_idx_hostaddr.high_addr =
|
||||
+ cpu_to_le32(address >> 32);
|
||||
+
|
||||
+ h2d_r_idx_ptr = h2d_w_idx_ptr +
|
||||
+ max_submissionrings * idx_offset;
|
||||
+ address += max_submissionrings * idx_offset;
|
||||
+ ringinfo.h2d_r_idx_hostaddr.low_addr =
|
||||
+ cpu_to_le32(address & 0xffffffff);
|
||||
+ ringinfo.h2d_r_idx_hostaddr.high_addr =
|
||||
+ cpu_to_le32(address >> 32);
|
||||
+
|
||||
+ d2h_w_idx_ptr = h2d_r_idx_ptr +
|
||||
+ max_submissionrings * idx_offset;
|
||||
+ address += max_submissionrings * idx_offset;
|
||||
+ ringinfo.d2h_w_idx_hostaddr.low_addr =
|
||||
+ cpu_to_le32(address & 0xffffffff);
|
||||
+ ringinfo.d2h_w_idx_hostaddr.high_addr =
|
||||
+ cpu_to_le32(address >> 32);
|
||||
|
||||
d2h_r_idx_ptr = d2h_w_idx_ptr +
|
||||
- BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET;
|
||||
- address += BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
|
||||
- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
|
||||
- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
|
||||
+ max_completionrings * idx_offset;
|
||||
+ address += max_completionrings * idx_offset;
|
||||
+ ringinfo.d2h_r_idx_hostaddr.low_addr =
|
||||
+ cpu_to_le32(address & 0xffffffff);
|
||||
+ ringinfo.d2h_r_idx_hostaddr.high_addr =
|
||||
+ cpu_to_le32(address >> 32);
|
||||
+
|
||||
+ memcpy_toio(devinfo->tcm + devinfo->shared.ring_info_addr,
|
||||
+ &ringinfo, sizeof(ringinfo));
|
||||
brcmf_dbg(PCIE, "Using host memory indices\n");
|
||||
}
|
||||
|
||||
- addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET;
|
||||
- ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
+ ring_mem_ptr = le32_to_cpu(ringinfo.ringmem);
|
||||
|
||||
for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) {
|
||||
ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
|
||||
@@ -1161,20 +1196,19 @@ static int brcmf_pcie_init_ringbuffers(s
|
||||
ring_mem_ptr += BRCMF_RING_MEM_SZ;
|
||||
}
|
||||
|
||||
- devinfo->shared.nrof_flowrings =
|
||||
- max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS;
|
||||
- rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring),
|
||||
- GFP_KERNEL);
|
||||
+ devinfo->shared.max_flowrings = max_flowrings;
|
||||
+ devinfo->shared.max_submissionrings = max_submissionrings;
|
||||
+ devinfo->shared.max_completionrings = max_completionrings;
|
||||
+ rings = kcalloc(max_flowrings, sizeof(*ring), GFP_KERNEL);
|
||||
if (!rings)
|
||||
goto fail;
|
||||
|
||||
- brcmf_dbg(PCIE, "Nr of flowrings is %d\n",
|
||||
- devinfo->shared.nrof_flowrings);
|
||||
+ brcmf_dbg(PCIE, "Nr of flowrings is %d\n", max_flowrings);
|
||||
|
||||
- for (i = 0; i < devinfo->shared.nrof_flowrings; i++) {
|
||||
+ for (i = 0; i < max_flowrings; i++) {
|
||||
ring = &rings[i];
|
||||
ring->devinfo = devinfo;
|
||||
- ring->id = i + BRCMF_NROF_COMMON_MSGRINGS;
|
||||
+ ring->id = i + BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
|
||||
brcmf_commonring_register_cb(&ring->commonring,
|
||||
brcmf_pcie_ring_mb_ring_bell,
|
||||
brcmf_pcie_ring_mb_update_rptr,
|
||||
@@ -1357,17 +1391,16 @@ brcmf_pcie_init_share_ram_info(struct br
|
||||
{
|
||||
struct brcmf_pcie_shared_info *shared;
|
||||
u32 addr;
|
||||
- u32 version;
|
||||
|
||||
shared = &devinfo->shared;
|
||||
shared->tcm_base_address = sharedram_addr;
|
||||
|
||||
shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr);
|
||||
- version = shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK;
|
||||
- brcmf_dbg(PCIE, "PCIe protocol version %d\n", version);
|
||||
- if ((version > BRCMF_PCIE_MAX_SHARED_VERSION) ||
|
||||
- (version < BRCMF_PCIE_MIN_SHARED_VERSION)) {
|
||||
- brcmf_err("Unsupported PCIE version %d\n", version);
|
||||
+ shared->version = (u8)(shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK);
|
||||
+ brcmf_dbg(PCIE, "PCIe protocol version %d\n", shared->version);
|
||||
+ if ((shared->version > BRCMF_PCIE_MAX_SHARED_VERSION) ||
|
||||
+ (shared->version < BRCMF_PCIE_MIN_SHARED_VERSION)) {
|
||||
+ brcmf_err("Unsupported PCIE version %d\n", shared->version);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1661,18 +1694,18 @@ static void brcmf_pcie_setup(struct devi
|
||||
bus->msgbuf->commonrings[i] =
|
||||
&devinfo->shared.commonrings[i]->commonring;
|
||||
|
||||
- flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*flowrings),
|
||||
+ flowrings = kcalloc(devinfo->shared.max_flowrings, sizeof(*flowrings),
|
||||
GFP_KERNEL);
|
||||
if (!flowrings)
|
||||
goto fail;
|
||||
|
||||
- for (i = 0; i < devinfo->shared.nrof_flowrings; i++)
|
||||
+ for (i = 0; i < devinfo->shared.max_flowrings; i++)
|
||||
flowrings[i] = &devinfo->shared.flowrings[i].commonring;
|
||||
bus->msgbuf->flowrings = flowrings;
|
||||
|
||||
bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset;
|
||||
bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost;
|
||||
- bus->msgbuf->nrof_flowrings = devinfo->shared.nrof_flowrings;
|
||||
+ bus->msgbuf->max_flowrings = devinfo->shared.max_flowrings;
|
||||
|
||||
init_waitqueue_head(&devinfo->mbdata_resp_wait);
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
From dc630dc5c753ccba97ce174f9c2894f802f9bd93 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:21 +0000
|
||||
Subject: [PATCH] brcmfmac: add support for 43341 chip
|
||||
|
||||
This chip was already supported, but seems a device came up giving
|
||||
a different chip identifier. So adding that effectively mapping to
|
||||
the same firmware file as for 43340 chip.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 1 +
|
||||
drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||||
@@ -621,6 +621,7 @@ static struct brcmf_firmware_mapping brc
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330),
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334),
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340),
|
||||
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340),
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
|
||||
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
|
||||
@@ -36,6 +36,7 @@
|
||||
#define BRCM_CC_4330_CHIP_ID 0x4330
|
||||
#define BRCM_CC_4334_CHIP_ID 0x4334
|
||||
#define BRCM_CC_43340_CHIP_ID 43340
|
||||
+#define BRCM_CC_43341_CHIP_ID 43341
|
||||
#define BRCM_CC_43362_CHIP_ID 43362
|
||||
#define BRCM_CC_4335_CHIP_ID 0x4335
|
||||
#define BRCM_CC_4339_CHIP_ID 0x4339
|
|
@ -1,319 +0,0 @@
|
|||
From ac55136f43d3336c7b40238b779c404008229929 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:22 +0000
|
||||
Subject: [PATCH] brcmfmac: move pno helper functions in separate source file
|
||||
|
||||
Introducing new source file for pno related functionality. Moving
|
||||
existing pno functions.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../wireless/broadcom/brcm80211/brcmfmac/Makefile | 3 +-
|
||||
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 93 ++-----------------
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 100 +++++++++++++++++++++
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 40 +++++++++
|
||||
4 files changed, 150 insertions(+), 86 deletions(-)
|
||||
create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
|
||||
@@ -35,7 +35,8 @@ brcmfmac-objs += \
|
||||
firmware.o \
|
||||
feature.o \
|
||||
btcoex.o \
|
||||
- vendor.o
|
||||
+ vendor.o \
|
||||
+ pno.o
|
||||
brcmfmac-$(CPTCFG_BRCMFMAC_PROTO_BCDC) += \
|
||||
bcdc.o
|
||||
brcmfmac-$(CPTCFG_BRCMFMAC_PROTO_MSGBUF) += \
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "fwil_types.h"
|
||||
#include "p2p.h"
|
||||
#include "btcoex.h"
|
||||
+#include "pno.h"
|
||||
#include "cfg80211.h"
|
||||
#include "feature.h"
|
||||
#include "fwil.h"
|
||||
@@ -41,16 +42,6 @@
|
||||
#include "common.h"
|
||||
|
||||
#define BRCMF_SCAN_IE_LEN_MAX 2048
|
||||
-#define BRCMF_PNO_VERSION 2
|
||||
-#define BRCMF_PNO_TIME 30
|
||||
-#define BRCMF_PNO_REPEAT 4
|
||||
-#define BRCMF_PNO_FREQ_EXPO_MAX 3
|
||||
-#define BRCMF_PNO_MAX_PFN_COUNT 16
|
||||
-#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
|
||||
-#define BRCMF_PNO_HIDDEN_BIT 2
|
||||
-#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
|
||||
-#define BRCMF_PNO_SCAN_COMPLETE 1
|
||||
-#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
||||
|
||||
#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
|
||||
#define WPA_OUI_TYPE 1
|
||||
@@ -3323,76 +3314,6 @@ out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int brcmf_dev_pno_clean(struct net_device *ndev)
|
||||
-{
|
||||
- int ret;
|
||||
-
|
||||
- /* Disable pfn */
|
||||
- ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0);
|
||||
- if (ret == 0) {
|
||||
- /* clear pfn */
|
||||
- ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear",
|
||||
- NULL, 0);
|
||||
- }
|
||||
- if (ret < 0)
|
||||
- brcmf_err("failed code %d\n", ret);
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int brcmf_dev_pno_config(struct brcmf_if *ifp,
|
||||
- struct cfg80211_sched_scan_request *request)
|
||||
-{
|
||||
- struct brcmf_pno_param_le pfn_param;
|
||||
- struct brcmf_pno_macaddr_le pfn_mac;
|
||||
- s32 err;
|
||||
- u8 *mac_mask;
|
||||
- int i;
|
||||
-
|
||||
- memset(&pfn_param, 0, sizeof(pfn_param));
|
||||
- pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
|
||||
-
|
||||
- /* set extra pno params */
|
||||
- pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
|
||||
- pfn_param.repeat = BRCMF_PNO_REPEAT;
|
||||
- pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
|
||||
-
|
||||
- /* set up pno scan fr */
|
||||
- pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
|
||||
-
|
||||
- err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
|
||||
- sizeof(pfn_param));
|
||||
- if (err) {
|
||||
- brcmf_err("pfn_set failed, err=%d\n", err);
|
||||
- return err;
|
||||
- }
|
||||
-
|
||||
- /* Find out if mac randomization should be turned on */
|
||||
- if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))
|
||||
- return 0;
|
||||
-
|
||||
- pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
|
||||
- pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
|
||||
-
|
||||
- memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN);
|
||||
- mac_mask = request->mac_addr_mask;
|
||||
- for (i = 0; i < ETH_ALEN; i++) {
|
||||
- pfn_mac.mac[i] &= mac_mask[i];
|
||||
- pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]);
|
||||
- }
|
||||
- /* Clear multi bit */
|
||||
- pfn_mac.mac[0] &= 0xFE;
|
||||
- /* Set locally administered */
|
||||
- pfn_mac.mac[0] |= 0x02;
|
||||
-
|
||||
- err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
|
||||
- sizeof(pfn_mac));
|
||||
- if (err)
|
||||
- brcmf_err("pfn_macaddr failed, err=%d\n", err);
|
||||
-
|
||||
- return err;
|
||||
-}
|
||||
-
|
||||
static int
|
||||
brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
|
||||
struct net_device *ndev,
|
||||
@@ -3436,15 +3357,16 @@ brcmf_cfg80211_sched_scan_start(struct w
|
||||
|
||||
if (request->n_match_sets > 0) {
|
||||
/* clean up everything */
|
||||
- ret = brcmf_dev_pno_clean(ndev);
|
||||
+ ret = brcmf_pno_clean(ifp);
|
||||
if (ret < 0) {
|
||||
brcmf_err("failed error=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* configure pno */
|
||||
- if (brcmf_dev_pno_config(ifp, request))
|
||||
- return -EINVAL;
|
||||
+ ret = brcmf_pno_config(ifp, request);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
/* configure each match set */
|
||||
for (i = 0; i < request->n_match_sets; i++) {
|
||||
@@ -3486,11 +3408,12 @@ static int brcmf_cfg80211_sched_scan_sto
|
||||
struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
+ struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
|
||||
brcmf_dbg(SCAN, "enter\n");
|
||||
- brcmf_dev_pno_clean(ndev);
|
||||
+ brcmf_pno_clean(ifp);
|
||||
if (cfg->sched_escan)
|
||||
- brcmf_notify_escan_complete(cfg, netdev_priv(ndev), true, true);
|
||||
+ brcmf_notify_escan_complete(cfg, ifp, true, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
@@ -0,0 +1,100 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2016 Broadcom
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and/or distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+#include <linux/netdevice.h>
|
||||
+#include <net/cfg80211.h>
|
||||
+
|
||||
+#include "core.h"
|
||||
+#include "debug.h"
|
||||
+#include "pno.h"
|
||||
+#include "fwil.h"
|
||||
+#include "fwil_types.h"
|
||||
+
|
||||
+#define BRCMF_PNO_VERSION 2
|
||||
+#define BRCMF_PNO_TIME 30
|
||||
+#define BRCMF_PNO_REPEAT 4
|
||||
+#define BRCMF_PNO_FREQ_EXPO_MAX 3
|
||||
+#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
|
||||
+#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
||||
+
|
||||
+int brcmf_pno_clean(struct brcmf_if *ifp)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Disable pfn */
|
||||
+ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0);
|
||||
+ if (ret == 0) {
|
||||
+ /* clear pfn */
|
||||
+ ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0);
|
||||
+ }
|
||||
+ if (ret < 0)
|
||||
+ brcmf_err("failed code %d\n", ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int brcmf_pno_config(struct brcmf_if *ifp,
|
||||
+ struct cfg80211_sched_scan_request *request)
|
||||
+{
|
||||
+ struct brcmf_pno_param_le pfn_param;
|
||||
+ struct brcmf_pno_macaddr_le pfn_mac;
|
||||
+ s32 err;
|
||||
+ u8 *mac_mask;
|
||||
+ int i;
|
||||
+
|
||||
+ memset(&pfn_param, 0, sizeof(pfn_param));
|
||||
+ pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
|
||||
+
|
||||
+ /* set extra pno params */
|
||||
+ pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
|
||||
+ pfn_param.repeat = BRCMF_PNO_REPEAT;
|
||||
+ pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
|
||||
+
|
||||
+ /* set up pno scan fr */
|
||||
+ pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
|
||||
+
|
||||
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
|
||||
+ sizeof(pfn_param));
|
||||
+ if (err) {
|
||||
+ brcmf_err("pfn_set failed, err=%d\n", err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /* Find out if mac randomization should be turned on */
|
||||
+ if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))
|
||||
+ return 0;
|
||||
+
|
||||
+ pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
|
||||
+ pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
|
||||
+
|
||||
+ memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN);
|
||||
+ mac_mask = request->mac_addr_mask;
|
||||
+ for (i = 0; i < ETH_ALEN; i++) {
|
||||
+ pfn_mac.mac[i] &= mac_mask[i];
|
||||
+ pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]);
|
||||
+ }
|
||||
+ /* Clear multi bit */
|
||||
+ pfn_mac.mac[0] &= 0xFE;
|
||||
+ /* Set locally administered */
|
||||
+ pfn_mac.mac[0] |= 0x02;
|
||||
+
|
||||
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
|
||||
+ sizeof(pfn_mac));
|
||||
+ if (err)
|
||||
+ brcmf_err("pfn_macaddr failed, err=%d\n", err);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
@@ -0,0 +1,40 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2016 Broadcom
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and/or distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+#ifndef _BRCMF_PNO_H
|
||||
+#define _BRCMF_PNO_H
|
||||
+
|
||||
+#define BRCMF_PNO_SCAN_COMPLETE 1
|
||||
+#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
|
||||
+#define BRCMF_PNO_HIDDEN_BIT 2
|
||||
+#define BRCMF_PNO_MAX_PFN_COUNT 16
|
||||
+
|
||||
+/**
|
||||
+ * brcmf_pno_clean - disable and clear pno in firmware.
|
||||
+ *
|
||||
+ * @ifp: interface object used.
|
||||
+ */
|
||||
+int brcmf_pno_clean(struct brcmf_if *ifp);
|
||||
+
|
||||
+/**
|
||||
+ * brcmf_pno_config - configure pno parameters.
|
||||
+ *
|
||||
+ * @ifp: interface object used.
|
||||
+ * @request: scheduled scan parameters.
|
||||
+ */
|
||||
+int brcmf_pno_config(struct brcmf_if *ifp,
|
||||
+ struct cfg80211_sched_scan_request *request);
|
||||
+
|
||||
+#endif /* _BRCMF_PNO_H */
|
|
@ -1,221 +0,0 @@
|
|||
From 3e2e86ab19c2a43953de30089c5411c580ddb5f7 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:23 +0000
|
||||
Subject: [PATCH] brcmfmac: fix handling ssids in .sched_scan_start() callback
|
||||
|
||||
The ssids list in the scheduled scan request were not properly taken
|
||||
into account when configuring in firmware. The hidden bit was set for
|
||||
any ssid resulting in active scanning for all. Only set it for ssids
|
||||
that are in the ssids list.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 103 ++++++++++-----------
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 18 ++++
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 12 ++-
|
||||
3 files changed, 76 insertions(+), 57 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -3314,19 +3314,37 @@ out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
+static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
|
||||
+ struct cfg80211_sched_scan_request *req)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ if (!ssid || !req->ssids || !req->n_ssids)
|
||||
+ return false;
|
||||
+
|
||||
+ for (i = 0; i < req->n_ssids; i++) {
|
||||
+ if (ssid->ssid_len == req->ssids[i].ssid_len) {
|
||||
+ if (!strncmp(ssid->ssid, req->ssids[i].ssid,
|
||||
+ ssid->ssid_len))
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
|
||||
struct net_device *ndev,
|
||||
- struct cfg80211_sched_scan_request *request)
|
||||
+ struct cfg80211_sched_scan_request *req)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
|
||||
- struct brcmf_pno_net_param_le pfn;
|
||||
+ struct cfg80211_ssid *ssid;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
|
||||
- request->n_match_sets, request->n_ssids);
|
||||
+ req->n_match_sets, req->n_ssids);
|
||||
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
|
||||
brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
|
||||
return -EAGAIN;
|
||||
@@ -3337,71 +3355,46 @@ brcmf_cfg80211_sched_scan_start(struct w
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
- if (!request->n_ssids || !request->n_match_sets) {
|
||||
- brcmf_dbg(SCAN, "Invalid sched scan req!! n_ssids:%d\n",
|
||||
- request->n_ssids);
|
||||
+ if (req->n_match_sets <= 0) {
|
||||
+ brcmf_dbg(SCAN, "invalid number of matchsets specified: %d\n",
|
||||
+ req->n_match_sets);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if (request->n_ssids > 0) {
|
||||
- for (i = 0; i < request->n_ssids; i++) {
|
||||
- /* Active scan req for ssids */
|
||||
- brcmf_dbg(SCAN, ">>> Active scan req for ssid (%s)\n",
|
||||
- request->ssids[i].ssid);
|
||||
-
|
||||
- /* match_set ssids is a supert set of n_ssid list,
|
||||
- * so we need not add these set separately.
|
||||
- */
|
||||
- }
|
||||
+ /* clean up everything */
|
||||
+ ret = brcmf_pno_clean(ifp);
|
||||
+ if (ret < 0) {
|
||||
+ brcmf_err("failed error=%d\n", ret);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
- if (request->n_match_sets > 0) {
|
||||
- /* clean up everything */
|
||||
- ret = brcmf_pno_clean(ifp);
|
||||
- if (ret < 0) {
|
||||
- brcmf_err("failed error=%d\n", ret);
|
||||
- return ret;
|
||||
+ /* configure pno */
|
||||
+ ret = brcmf_pno_config(ifp, req);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* configure each match set */
|
||||
+ for (i = 0; i < req->n_match_sets; i++) {
|
||||
+
|
||||
+ ssid = &req->match_sets[i].ssid;
|
||||
+
|
||||
+ if (!ssid->ssid_len) {
|
||||
+ brcmf_err("skip broadcast ssid\n");
|
||||
+ continue;
|
||||
}
|
||||
|
||||
- /* configure pno */
|
||||
- ret = brcmf_pno_config(ifp, request);
|
||||
+ ret = brcmf_pno_add_ssid(ifp, ssid,
|
||||
+ brcmf_is_ssid_active(ssid, req));
|
||||
if (ret < 0)
|
||||
- return ret;
|
||||
-
|
||||
- /* configure each match set */
|
||||
- for (i = 0; i < request->n_match_sets; i++) {
|
||||
- struct cfg80211_ssid *ssid;
|
||||
- u32 ssid_len;
|
||||
-
|
||||
- ssid = &request->match_sets[i].ssid;
|
||||
- ssid_len = ssid->ssid_len;
|
||||
-
|
||||
- if (!ssid_len) {
|
||||
- brcmf_err("skip broadcast ssid\n");
|
||||
- continue;
|
||||
- }
|
||||
- pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
|
||||
- pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
|
||||
- pfn.wsec = cpu_to_le32(0);
|
||||
- pfn.infra = cpu_to_le32(1);
|
||||
- pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
|
||||
- pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
|
||||
- memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
|
||||
- ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn,
|
||||
- sizeof(pfn));
|
||||
brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
|
||||
ret == 0 ? "set" : "failed", ssid->ssid);
|
||||
- }
|
||||
- /* Enable the PNO */
|
||||
- if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) {
|
||||
- brcmf_err("PNO enable failed!! ret=%d\n", ret);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
- } else {
|
||||
- return -EINVAL;
|
||||
}
|
||||
+ /* Enable the PNO */
|
||||
+ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
|
||||
+ if (ret < 0)
|
||||
+ brcmf_err("PNO enable failed!! ret=%d\n", ret);
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
@@ -28,6 +28,8 @@
|
||||
#define BRCMF_PNO_FREQ_EXPO_MAX 3
|
||||
#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
|
||||
#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
||||
+#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
|
||||
+#define BRCMF_PNO_HIDDEN_BIT 2
|
||||
|
||||
int brcmf_pno_clean(struct brcmf_if *ifp)
|
||||
{
|
||||
@@ -98,3 +100,19 @@ int brcmf_pno_config(struct brcmf_if *if
|
||||
return err;
|
||||
}
|
||||
|
||||
+int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
|
||||
+ bool active)
|
||||
+{
|
||||
+ struct brcmf_pno_net_param_le pfn;
|
||||
+
|
||||
+ pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
|
||||
+ pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
|
||||
+ pfn.wsec = cpu_to_le32(0);
|
||||
+ pfn.infra = cpu_to_le32(1);
|
||||
+ if (active)
|
||||
+ pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
|
||||
+ pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len);
|
||||
+ memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len);
|
||||
+ return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
|
||||
+}
|
||||
+
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
@@ -17,8 +17,6 @@
|
||||
#define _BRCMF_PNO_H
|
||||
|
||||
#define BRCMF_PNO_SCAN_COMPLETE 1
|
||||
-#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
|
||||
-#define BRCMF_PNO_HIDDEN_BIT 2
|
||||
#define BRCMF_PNO_MAX_PFN_COUNT 16
|
||||
|
||||
/**
|
||||
@@ -37,4 +35,14 @@ int brcmf_pno_clean(struct brcmf_if *ifp
|
||||
int brcmf_pno_config(struct brcmf_if *ifp,
|
||||
struct cfg80211_sched_scan_request *request);
|
||||
|
||||
+/**
|
||||
+ * brcmf_pno_add_ssid - add ssid for pno in firmware.
|
||||
+ *
|
||||
+ * @ifp: interface object used.
|
||||
+ * @ssid: ssid information.
|
||||
+ * @active: indicate this ssid needs to be actively probed.
|
||||
+ */
|
||||
+int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
|
||||
+ bool active);
|
||||
+
|
||||
#endif /* _BRCMF_PNO_H */
|
|
@ -1,58 +0,0 @@
|
|||
From ab5981c830339b945ddbedc314567a9e5f506d72 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:24 +0000
|
||||
Subject: [PATCH] brcmfmac: change prototype for brcmf_do_escan()
|
||||
|
||||
Reduce the number of parameters as the removed ones can be obtained
|
||||
through struct brcmf_if parameter.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -1080,9 +1080,9 @@ exit:
|
||||
}
|
||||
|
||||
static s32
|
||||
-brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
|
||||
- struct brcmf_if *ifp, struct cfg80211_scan_request *request)
|
||||
+brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request)
|
||||
{
|
||||
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
||||
s32 err;
|
||||
u32 passive_scan;
|
||||
struct brcmf_scan_results *results;
|
||||
@@ -1090,7 +1090,7 @@ brcmf_do_escan(struct brcmf_cfg80211_inf
|
||||
|
||||
brcmf_dbg(SCAN, "Enter\n");
|
||||
escan->ifp = ifp;
|
||||
- escan->wiphy = wiphy;
|
||||
+ escan->wiphy = cfg->wiphy;
|
||||
escan->escan_state = WL_ESCAN_STATE_SCANNING;
|
||||
passive_scan = cfg->active_scan ? 0 : 1;
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
|
||||
@@ -1170,7 +1170,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
|
||||
if (err)
|
||||
goto scan_out;
|
||||
|
||||
- err = brcmf_do_escan(cfg, wiphy, vif->ifp, request);
|
||||
+ err = brcmf_do_escan(vif->ifp, request);
|
||||
if (err)
|
||||
goto scan_out;
|
||||
} else {
|
||||
@@ -3289,7 +3289,7 @@ brcmf_notify_sched_scan_results(struct b
|
||||
|
||||
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||
cfg->escan_info.run = brcmf_run_escan;
|
||||
- err = brcmf_do_escan(cfg, wiphy, ifp, request);
|
||||
+ err = brcmf_do_escan(ifp, request);
|
||||
if (err) {
|
||||
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||
goto out_err;
|
|
@ -1,306 +0,0 @@
|
|||
From fa85b30a908455ff25def3a5f319aad272ef4862 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:25 +0000
|
||||
Subject: [PATCH] brcmfmac: make internal escan more generic
|
||||
|
||||
For scheduled scan we initiate an escan in firmware to obtain more
|
||||
info missing from the scheduled scan notification we get from firmware.
|
||||
For upcoming functionality this is also required so make it a bit
|
||||
more generic.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 187 ++++++++++++---------
|
||||
.../broadcom/brcm80211/brcmfmac/cfg80211.h | 4 +-
|
||||
2 files changed, 109 insertions(+), 82 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -757,12 +757,12 @@ s32 brcmf_notify_escan_complete(struct b
|
||||
brcmf_scan_config_mpc(ifp, 1);
|
||||
|
||||
/*
|
||||
- * e-scan can be initiated by scheduled scan
|
||||
+ * e-scan can be initiated internally
|
||||
* which takes precedence.
|
||||
*/
|
||||
- if (cfg->sched_escan) {
|
||||
+ if (cfg->internal_escan) {
|
||||
brcmf_dbg(SCAN, "scheduled scan completed\n");
|
||||
- cfg->sched_escan = false;
|
||||
+ cfg->internal_escan = false;
|
||||
if (!aborted)
|
||||
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
|
||||
} else if (scan_request) {
|
||||
@@ -3013,7 +3013,7 @@ void brcmf_abort_scanning(struct brcmf_c
|
||||
struct escan_info *escan = &cfg->escan_info;
|
||||
|
||||
set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
|
||||
- if (cfg->scan_request) {
|
||||
+ if (cfg->internal_escan || cfg->scan_request) {
|
||||
escan->escan_state = WL_ESCAN_STATE_IDLE;
|
||||
brcmf_notify_escan_complete(cfg, escan->ifp, true, true);
|
||||
}
|
||||
@@ -3036,7 +3036,7 @@ static void brcmf_escan_timeout(unsigned
|
||||
struct brcmf_cfg80211_info *cfg =
|
||||
(struct brcmf_cfg80211_info *)data;
|
||||
|
||||
- if (cfg->scan_request) {
|
||||
+ if (cfg->internal_escan || cfg->scan_request) {
|
||||
brcmf_err("timer expired\n");
|
||||
schedule_work(&cfg->escan_timeout_work);
|
||||
}
|
||||
@@ -3119,7 +3119,7 @@ brcmf_cfg80211_escan_handler(struct brcm
|
||||
if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le))
|
||||
goto exit;
|
||||
|
||||
- if (!cfg->scan_request) {
|
||||
+ if (!cfg->internal_escan && !cfg->scan_request) {
|
||||
brcmf_dbg(SCAN, "result without cfg80211 request\n");
|
||||
goto exit;
|
||||
}
|
||||
@@ -3165,7 +3165,7 @@ brcmf_cfg80211_escan_handler(struct brcm
|
||||
cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
|
||||
if (brcmf_p2p_scan_finding_common_channel(cfg, NULL))
|
||||
goto exit;
|
||||
- if (cfg->scan_request) {
|
||||
+ if (cfg->internal_escan || cfg->scan_request) {
|
||||
brcmf_inform_bss(cfg);
|
||||
aborted = status != BRCMF_E_STATUS_SUCCESS;
|
||||
brcmf_notify_escan_complete(cfg, ifp, aborted, false);
|
||||
@@ -3190,6 +3190,73 @@ static void brcmf_init_escan(struct brcm
|
||||
brcmf_cfg80211_escan_timeout_worker);
|
||||
}
|
||||
|
||||
+static struct cfg80211_scan_request *
|
||||
+brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) {
|
||||
+ struct cfg80211_scan_request *req;
|
||||
+ size_t req_size;
|
||||
+
|
||||
+ req_size = sizeof(*req) +
|
||||
+ n_netinfo * sizeof(req->channels[0]) +
|
||||
+ n_netinfo * sizeof(*req->ssids);
|
||||
+
|
||||
+ req = kzalloc(req_size, GFP_KERNEL);
|
||||
+ if (req) {
|
||||
+ req->wiphy = wiphy;
|
||||
+ req->ssids = (void *)(&req->channels[0]) +
|
||||
+ n_netinfo * sizeof(req->channels[0]);
|
||||
+ }
|
||||
+ return req;
|
||||
+}
|
||||
+
|
||||
+static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
|
||||
+ u8 *ssid, u8 ssid_len, u8 channel)
|
||||
+{
|
||||
+ struct ieee80211_channel *chan;
|
||||
+ enum nl80211_band band;
|
||||
+ int freq;
|
||||
+
|
||||
+ if (channel <= CH_MAX_2G_CHANNEL)
|
||||
+ band = NL80211_BAND_2GHZ;
|
||||
+ else
|
||||
+ band = NL80211_BAND_5GHZ;
|
||||
+
|
||||
+ freq = ieee80211_channel_to_frequency(channel, band);
|
||||
+ if (!freq)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ chan = ieee80211_get_channel(req->wiphy, freq);
|
||||
+ if (!chan)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ req->channels[req->n_channels++] = chan;
|
||||
+ memcpy(req->ssids[req->n_ssids].ssid, ssid, ssid_len);
|
||||
+ req->ssids[req->n_ssids++].ssid_len = ssid_len;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int brcmf_start_internal_escan(struct brcmf_if *ifp,
|
||||
+ struct cfg80211_scan_request *request)
|
||||
+{
|
||||
+ struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
||||
+ int err;
|
||||
+
|
||||
+ if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
|
||||
+ /* Abort any on-going scan */
|
||||
+ brcmf_abort_scanning(cfg);
|
||||
+ }
|
||||
+
|
||||
+ set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||
+ cfg->escan_info.run = brcmf_run_escan;
|
||||
+ err = brcmf_do_escan(ifp, request);
|
||||
+ if (err) {
|
||||
+ clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||
+ return err;
|
||||
+ }
|
||||
+ cfg->internal_escan = true;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* PFN result doesn't have all the info which are required by the supplicant
|
||||
* (For e.g IEs) Do a target Escan so that sched scan results are reported
|
||||
* via wl_inform_single_bss in the required format. Escan does require the
|
||||
@@ -3203,12 +3270,8 @@ brcmf_notify_sched_scan_results(struct b
|
||||
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
||||
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
|
||||
struct cfg80211_scan_request *request = NULL;
|
||||
- struct cfg80211_ssid *ssid = NULL;
|
||||
- struct ieee80211_channel *channel = NULL;
|
||||
struct wiphy *wiphy = cfg_to_wiphy(cfg);
|
||||
- int err = 0;
|
||||
- int channel_req = 0;
|
||||
- int band = 0;
|
||||
+ int i, err = 0;
|
||||
struct brcmf_pno_scanresults_le *pfn_result;
|
||||
u32 result_count;
|
||||
u32 status;
|
||||
@@ -3234,83 +3297,47 @@ brcmf_notify_sched_scan_results(struct b
|
||||
*/
|
||||
WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
|
||||
brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count);
|
||||
- if (result_count > 0) {
|
||||
- int i;
|
||||
-
|
||||
- request = kzalloc(sizeof(*request), GFP_KERNEL);
|
||||
- ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL);
|
||||
- channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL);
|
||||
- if (!request || !ssid || !channel) {
|
||||
- err = -ENOMEM;
|
||||
- goto out_err;
|
||||
- }
|
||||
+ if (!result_count) {
|
||||
+ brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
|
||||
+ goto out_err;
|
||||
+ }
|
||||
+ request = brcmf_alloc_internal_escan_request(wiphy,
|
||||
+ result_count);
|
||||
+ if (!request) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto out_err;
|
||||
+ }
|
||||
|
||||
- request->wiphy = wiphy;
|
||||
- data += sizeof(struct brcmf_pno_scanresults_le);
|
||||
- netinfo_start = (struct brcmf_pno_net_info_le *)data;
|
||||
-
|
||||
- for (i = 0; i < result_count; i++) {
|
||||
- netinfo = &netinfo_start[i];
|
||||
- if (!netinfo) {
|
||||
- brcmf_err("Invalid netinfo ptr. index: %d\n",
|
||||
- i);
|
||||
- err = -EINVAL;
|
||||
- goto out_err;
|
||||
- }
|
||||
+ data += sizeof(struct brcmf_pno_scanresults_le);
|
||||
+ netinfo_start = (struct brcmf_pno_net_info_le *)data;
|
||||
|
||||
- brcmf_dbg(SCAN, "SSID:%s Channel:%d\n",
|
||||
- netinfo->SSID, netinfo->channel);
|
||||
- memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len);
|
||||
- ssid[i].ssid_len = netinfo->SSID_len;
|
||||
- request->n_ssids++;
|
||||
-
|
||||
- channel_req = netinfo->channel;
|
||||
- if (channel_req <= CH_MAX_2G_CHANNEL)
|
||||
- band = NL80211_BAND_2GHZ;
|
||||
- else
|
||||
- band = NL80211_BAND_5GHZ;
|
||||
- channel[i].center_freq =
|
||||
- ieee80211_channel_to_frequency(channel_req,
|
||||
- band);
|
||||
- channel[i].band = band;
|
||||
- channel[i].flags |= IEEE80211_CHAN_NO_HT40;
|
||||
- request->channels[i] = &channel[i];
|
||||
- request->n_channels++;
|
||||
- }
|
||||
-
|
||||
- /* assign parsed ssid array */
|
||||
- if (request->n_ssids)
|
||||
- request->ssids = &ssid[0];
|
||||
-
|
||||
- if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
|
||||
- /* Abort any on-going scan */
|
||||
- brcmf_abort_scanning(cfg);
|
||||
+ for (i = 0; i < result_count; i++) {
|
||||
+ netinfo = &netinfo_start[i];
|
||||
+ if (!netinfo) {
|
||||
+ brcmf_err("Invalid netinfo ptr. index: %d\n",
|
||||
+ i);
|
||||
+ err = -EINVAL;
|
||||
+ goto out_err;
|
||||
}
|
||||
|
||||
- set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||
- cfg->escan_info.run = brcmf_run_escan;
|
||||
- err = brcmf_do_escan(ifp, request);
|
||||
- if (err) {
|
||||
- clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||
+ brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
|
||||
+ netinfo->SSID, netinfo->channel);
|
||||
+ err = brcmf_internal_escan_add_info(request,
|
||||
+ netinfo->SSID,
|
||||
+ netinfo->SSID_len,
|
||||
+ netinfo->channel);
|
||||
+ if (err)
|
||||
goto out_err;
|
||||
- }
|
||||
- cfg->sched_escan = true;
|
||||
- cfg->scan_request = request;
|
||||
- } else {
|
||||
- brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
|
||||
- goto out_err;
|
||||
}
|
||||
|
||||
- kfree(ssid);
|
||||
- kfree(channel);
|
||||
- kfree(request);
|
||||
- return 0;
|
||||
+ err = brcmf_start_internal_escan(ifp, request);
|
||||
+ if (!err)
|
||||
+ goto free_req;
|
||||
|
||||
out_err:
|
||||
- kfree(ssid);
|
||||
- kfree(channel);
|
||||
- kfree(request);
|
||||
cfg80211_sched_scan_stopped(wiphy);
|
||||
+free_req:
|
||||
+ kfree(request);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -3405,7 +3432,7 @@ static int brcmf_cfg80211_sched_scan_sto
|
||||
|
||||
brcmf_dbg(SCAN, "enter\n");
|
||||
brcmf_pno_clean(ifp);
|
||||
- if (cfg->sched_escan)
|
||||
+ if (cfg->internal_escan)
|
||||
brcmf_notify_escan_complete(cfg, ifp, true, true);
|
||||
return 0;
|
||||
}
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
|
||||
@@ -271,7 +271,7 @@ struct brcmf_cfg80211_wowl {
|
||||
* @pub: common driver information.
|
||||
* @channel: current channel.
|
||||
* @active_scan: current scan mode.
|
||||
- * @sched_escan: e-scan for scheduled scan support running.
|
||||
+ * @internal_escan: indicates internally initiated e-scan is running.
|
||||
* @ibss_starter: indicates this sta is ibss starter.
|
||||
* @pwr_save: indicate whether dongle to support power save mode.
|
||||
* @dongle_up: indicate whether dongle up or not.
|
||||
@@ -303,7 +303,7 @@ struct brcmf_cfg80211_info {
|
||||
struct brcmf_pub *pub;
|
||||
u32 channel;
|
||||
bool active_scan;
|
||||
- bool sched_escan;
|
||||
+ bool internal_escan;
|
||||
bool ibss_starter;
|
||||
bool pwr_save;
|
||||
bool dongle_up;
|
|
@ -1,176 +0,0 @@
|
|||
From fca6cb2f059e51dec3fcf3589a5abbbcce5b4043 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:26 +0000
|
||||
Subject: [PATCH] brcmfmac: split up brcmf_pno_config() function
|
||||
|
||||
The brcmf_pno_config() function handles two configurations in
|
||||
firmware. Split it and have caller sort out what is needed.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 11 +++-
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 60 ++++++++++++++++------
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 17 ++++--
|
||||
3 files changed, 68 insertions(+), 20 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "common.h"
|
||||
|
||||
#define BRCMF_SCAN_IE_LEN_MAX 2048
|
||||
+#define BRCMF_SCHED_SCAN_PERIOD 30
|
||||
|
||||
#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
|
||||
#define WPA_OUI_TYPE 1
|
||||
@@ -3396,10 +3397,18 @@ brcmf_cfg80211_sched_scan_start(struct w
|
||||
}
|
||||
|
||||
/* configure pno */
|
||||
- ret = brcmf_pno_config(ifp, req);
|
||||
+ ret = brcmf_pno_config(ifp, BRCMF_SCHED_SCAN_PERIOD, 0, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
+ /* configure random mac */
|
||||
+ if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
+ ret = brcmf_pno_set_random(ifp, req->mac_addr,
|
||||
+ req->mac_addr_mask);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
/* configure each match set */
|
||||
for (i = 0; i < req->n_match_sets; i++) {
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
@@ -23,10 +23,12 @@
|
||||
#include "fwil_types.h"
|
||||
|
||||
#define BRCMF_PNO_VERSION 2
|
||||
-#define BRCMF_PNO_TIME 30
|
||||
#define BRCMF_PNO_REPEAT 4
|
||||
#define BRCMF_PNO_FREQ_EXPO_MAX 3
|
||||
+#define BRCMF_PNO_IMMEDIATE_SCAN_BIT 3
|
||||
+#define BRCMF_PNO_ENABLE_BD_SCAN_BIT 5
|
||||
#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
|
||||
+#define BRCMF_PNO_REPORT_SEPARATELY_BIT 11
|
||||
#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
||||
#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
|
||||
#define BRCMF_PNO_HIDDEN_BIT 2
|
||||
@@ -47,42 +49,68 @@ int brcmf_pno_clean(struct brcmf_if *ifp
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int brcmf_pno_config(struct brcmf_if *ifp,
|
||||
- struct cfg80211_sched_scan_request *request)
|
||||
+int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
|
||||
+ u32 mscan, u32 bestn)
|
||||
{
|
||||
struct brcmf_pno_param_le pfn_param;
|
||||
- struct brcmf_pno_macaddr_le pfn_mac;
|
||||
+ u16 flags;
|
||||
+ u32 pfnmem;
|
||||
s32 err;
|
||||
- u8 *mac_mask;
|
||||
- int i;
|
||||
|
||||
memset(&pfn_param, 0, sizeof(pfn_param));
|
||||
pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
|
||||
|
||||
/* set extra pno params */
|
||||
- pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
|
||||
+ flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) |
|
||||
+ BIT(BRCMF_PNO_REPORT_SEPARATELY_BIT) |
|
||||
+ BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
|
||||
pfn_param.repeat = BRCMF_PNO_REPEAT;
|
||||
pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
|
||||
|
||||
/* set up pno scan fr */
|
||||
- pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
|
||||
+ pfn_param.scan_freq = cpu_to_le32(scan_freq);
|
||||
+
|
||||
+ if (mscan) {
|
||||
+ pfnmem = bestn;
|
||||
|
||||
+ /* set bestn in firmware */
|
||||
+ err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem);
|
||||
+ if (err < 0) {
|
||||
+ brcmf_err("failed to set pfnmem\n");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+ /* get max mscan which the firmware supports */
|
||||
+ err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem);
|
||||
+ if (err < 0) {
|
||||
+ brcmf_err("failed to get pfnmem\n");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+ mscan = min_t(u32, mscan, pfnmem);
|
||||
+ pfn_param.mscan = mscan;
|
||||
+ pfn_param.bestn = bestn;
|
||||
+ flags |= BIT(BRCMF_PNO_ENABLE_BD_SCAN_BIT);
|
||||
+ brcmf_dbg(INFO, "mscan=%d, bestn=%d\n", mscan, bestn);
|
||||
+ }
|
||||
+
|
||||
+ pfn_param.flags = cpu_to_le16(flags);
|
||||
err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
|
||||
sizeof(pfn_param));
|
||||
- if (err) {
|
||||
+ if (err)
|
||||
brcmf_err("pfn_set failed, err=%d\n", err);
|
||||
- return err;
|
||||
- }
|
||||
|
||||
- /* Find out if mac randomization should be turned on */
|
||||
- if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))
|
||||
- return 0;
|
||||
+exit:
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask)
|
||||
+{
|
||||
+ struct brcmf_pno_macaddr_le pfn_mac;
|
||||
+ int err, i;
|
||||
|
||||
pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
|
||||
pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
|
||||
|
||||
- memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN);
|
||||
- mac_mask = request->mac_addr_mask;
|
||||
+ memcpy(pfn_mac.mac, mac_addr, ETH_ALEN);
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
pfn_mac.mac[i] &= mac_mask[i];
|
||||
pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]);
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
@@ -30,10 +30,21 @@ int brcmf_pno_clean(struct brcmf_if *ifp
|
||||
* brcmf_pno_config - configure pno parameters.
|
||||
*
|
||||
* @ifp: interface object used.
|
||||
- * @request: scheduled scan parameters.
|
||||
+ * @scan_freq: scan frequency period in seconds.
|
||||
+ * @mscan: maximum number of scans stored in firmware.
|
||||
+ * @bestn: maximum number of APs per scan stored in firmware.
|
||||
*/
|
||||
-int brcmf_pno_config(struct brcmf_if *ifp,
|
||||
- struct cfg80211_sched_scan_request *request);
|
||||
+int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
|
||||
+ u32 mscan, u32 bestn);
|
||||
+
|
||||
+/**
|
||||
+ * brcmf_pno_set_random - setup randomisation mac address for pno.
|
||||
+ *
|
||||
+ * @ifp: interface object used.
|
||||
+ * @mac_addr: MAC address used with randomisation.
|
||||
+ * @mac_mask: MAC address mask used for randomisation.
|
||||
+ */
|
||||
+int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask);
|
||||
|
||||
/**
|
||||
* brcmf_pno_add_ssid - add ssid for pno in firmware.
|
|
@ -1,292 +0,0 @@
|
|||
From 3e48611d31dd333be01576902f2dc11adefc9a06 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:27 +0000
|
||||
Subject: [PATCH] brcmfmac: move scheduled scan activation to pno source file
|
||||
|
||||
Rework .sched_scan_start() callback moving actual configuration of
|
||||
the device in pno source file.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 65 +-----------
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 110 +++++++++++++++++----
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 29 +-----
|
||||
3 files changed, 94 insertions(+), 110 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -42,7 +42,6 @@
|
||||
#include "common.h"
|
||||
|
||||
#define BRCMF_SCAN_IE_LEN_MAX 2048
|
||||
-#define BRCMF_SCHED_SCAN_PERIOD 30
|
||||
|
||||
#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
|
||||
#define WPA_OUI_TYPE 1
|
||||
@@ -3342,24 +3341,6 @@ free_req:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
|
||||
- struct cfg80211_sched_scan_request *req)
|
||||
-{
|
||||
- int i;
|
||||
-
|
||||
- if (!ssid || !req->ssids || !req->n_ssids)
|
||||
- return false;
|
||||
-
|
||||
- for (i = 0; i < req->n_ssids; i++) {
|
||||
- if (ssid->ssid_len == req->ssids[i].ssid_len) {
|
||||
- if (!strncmp(ssid->ssid, req->ssids[i].ssid,
|
||||
- ssid->ssid_len))
|
||||
- return true;
|
||||
- }
|
||||
- }
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
static int
|
||||
brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
|
||||
struct net_device *ndev,
|
||||
@@ -3367,9 +3348,6 @@ brcmf_cfg80211_sched_scan_start(struct w
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
|
||||
- struct cfg80211_ssid *ssid;
|
||||
- int i;
|
||||
- int ret = 0;
|
||||
|
||||
brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
|
||||
req->n_match_sets, req->n_ssids);
|
||||
@@ -3389,48 +3367,7 @@ brcmf_cfg80211_sched_scan_start(struct w
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- /* clean up everything */
|
||||
- ret = brcmf_pno_clean(ifp);
|
||||
- if (ret < 0) {
|
||||
- brcmf_err("failed error=%d\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- /* configure pno */
|
||||
- ret = brcmf_pno_config(ifp, BRCMF_SCHED_SCAN_PERIOD, 0, 0);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
-
|
||||
- /* configure random mac */
|
||||
- if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
- ret = brcmf_pno_set_random(ifp, req->mac_addr,
|
||||
- req->mac_addr_mask);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- /* configure each match set */
|
||||
- for (i = 0; i < req->n_match_sets; i++) {
|
||||
-
|
||||
- ssid = &req->match_sets[i].ssid;
|
||||
-
|
||||
- if (!ssid->ssid_len) {
|
||||
- brcmf_err("skip broadcast ssid\n");
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- ret = brcmf_pno_add_ssid(ifp, ssid,
|
||||
- brcmf_is_ssid_active(ssid, req));
|
||||
- if (ret < 0)
|
||||
- brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
|
||||
- ret == 0 ? "set" : "failed", ssid->ssid);
|
||||
- }
|
||||
- /* Enable the PNO */
|
||||
- ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
|
||||
- if (ret < 0)
|
||||
- brcmf_err("PNO enable failed!! ret=%d\n", ret);
|
||||
-
|
||||
- return ret;
|
||||
+ return brcmf_pno_start_sched_scan(ifp, req);
|
||||
}
|
||||
|
||||
static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
@@ -32,25 +32,10 @@
|
||||
#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
||||
#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
|
||||
#define BRCMF_PNO_HIDDEN_BIT 2
|
||||
+#define BRCMF_PNO_SCHED_SCAN_PERIOD 30
|
||||
|
||||
-int brcmf_pno_clean(struct brcmf_if *ifp)
|
||||
-{
|
||||
- int ret;
|
||||
-
|
||||
- /* Disable pfn */
|
||||
- ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0);
|
||||
- if (ret == 0) {
|
||||
- /* clear pfn */
|
||||
- ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0);
|
||||
- }
|
||||
- if (ret < 0)
|
||||
- brcmf_err("failed code %d\n", ret);
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
|
||||
- u32 mscan, u32 bestn)
|
||||
+static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
|
||||
+ u32 mscan, u32 bestn)
|
||||
{
|
||||
struct brcmf_pno_param_le pfn_param;
|
||||
u16 flags;
|
||||
@@ -102,7 +87,8 @@ exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
-int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask)
|
||||
+static int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr,
|
||||
+ u8 *mac_mask)
|
||||
{
|
||||
struct brcmf_pno_macaddr_le pfn_mac;
|
||||
int err, i;
|
||||
@@ -128,8 +114,8 @@ int brcmf_pno_set_random(struct brcmf_if
|
||||
return err;
|
||||
}
|
||||
|
||||
-int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
|
||||
- bool active)
|
||||
+static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
|
||||
+ bool active)
|
||||
{
|
||||
struct brcmf_pno_net_param_le pfn;
|
||||
|
||||
@@ -144,3 +130,85 @@ int brcmf_pno_add_ssid(struct brcmf_if *
|
||||
return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
|
||||
}
|
||||
|
||||
+static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
|
||||
+ struct cfg80211_sched_scan_request *req)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ if (!ssid || !req->ssids || !req->n_ssids)
|
||||
+ return false;
|
||||
+
|
||||
+ for (i = 0; i < req->n_ssids; i++) {
|
||||
+ if (ssid->ssid_len == req->ssids[i].ssid_len) {
|
||||
+ if (!strncmp(ssid->ssid, req->ssids[i].ssid,
|
||||
+ ssid->ssid_len))
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+int brcmf_pno_clean(struct brcmf_if *ifp)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Disable pfn */
|
||||
+ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0);
|
||||
+ if (ret == 0) {
|
||||
+ /* clear pfn */
|
||||
+ ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0);
|
||||
+ }
|
||||
+ if (ret < 0)
|
||||
+ brcmf_err("failed code %d\n", ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
|
||||
+ struct cfg80211_sched_scan_request *req)
|
||||
+{
|
||||
+ struct cfg80211_ssid *ssid;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ /* clean up everything */
|
||||
+ ret = brcmf_pno_clean(ifp);
|
||||
+ if (ret < 0) {
|
||||
+ brcmf_err("failed error=%d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* configure pno */
|
||||
+ ret = brcmf_pno_config(ifp, BRCMF_PNO_SCHED_SCAN_PERIOD, 0, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* configure random mac */
|
||||
+ if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
+ ret = brcmf_pno_set_random(ifp, req->mac_addr,
|
||||
+ req->mac_addr_mask);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* configure each match set */
|
||||
+ for (i = 0; i < req->n_match_sets; i++) {
|
||||
+ ssid = &req->match_sets[i].ssid;
|
||||
+ if (!ssid->ssid_len) {
|
||||
+ brcmf_err("skip broadcast ssid\n");
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ret = brcmf_pno_add_ssid(ifp, ssid,
|
||||
+ brcmf_is_ssid_active(ssid, req));
|
||||
+ if (ret < 0)
|
||||
+ brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
|
||||
+ ret == 0 ? "set" : "failed", ssid->ssid);
|
||||
+ }
|
||||
+ /* Enable the PNO */
|
||||
+ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
|
||||
+ if (ret < 0)
|
||||
+ brcmf_err("PNO enable failed!! ret=%d\n", ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
@@ -27,33 +27,12 @@
|
||||
int brcmf_pno_clean(struct brcmf_if *ifp);
|
||||
|
||||
/**
|
||||
- * brcmf_pno_config - configure pno parameters.
|
||||
+ * brcmf_pno_start_sched_scan - initiate scheduled scan on device.
|
||||
*
|
||||
* @ifp: interface object used.
|
||||
- * @scan_freq: scan frequency period in seconds.
|
||||
- * @mscan: maximum number of scans stored in firmware.
|
||||
- * @bestn: maximum number of APs per scan stored in firmware.
|
||||
+ * @req: configuration parameters for scheduled scan.
|
||||
*/
|
||||
-int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
|
||||
- u32 mscan, u32 bestn);
|
||||
-
|
||||
-/**
|
||||
- * brcmf_pno_set_random - setup randomisation mac address for pno.
|
||||
- *
|
||||
- * @ifp: interface object used.
|
||||
- * @mac_addr: MAC address used with randomisation.
|
||||
- * @mac_mask: MAC address mask used for randomisation.
|
||||
- */
|
||||
-int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask);
|
||||
-
|
||||
-/**
|
||||
- * brcmf_pno_add_ssid - add ssid for pno in firmware.
|
||||
- *
|
||||
- * @ifp: interface object used.
|
||||
- * @ssid: ssid information.
|
||||
- * @active: indicate this ssid needs to be actively probed.
|
||||
- */
|
||||
-int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
|
||||
- bool active);
|
||||
+int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
|
||||
+ struct cfg80211_sched_scan_request *req);
|
||||
|
||||
#endif /* _BRCMF_PNO_H */
|
|
@ -1,111 +0,0 @@
|
|||
From 331e789443618ca9cc3ed48ada4e670225cca036 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:28 +0000
|
||||
Subject: [PATCH] brcmfmac: use provided channels for scheduled scan
|
||||
|
||||
User-space can provide list of channels in the schedule scan request.
|
||||
This was ignored so all channels supported and allowed by the device
|
||||
were used. This patch configures the device to use the channels as
|
||||
listed in the request.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 16 +++++++++++++
|
||||
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 26 +++++++++++++++++++++-
|
||||
2 files changed, 41 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
||||
@@ -131,6 +131,7 @@
|
||||
#define BRCMF_TXBF_MU_BFR_CAP BIT(1)
|
||||
|
||||
#define BRCMF_MAXPMKID 16 /* max # PMKID cache entries */
|
||||
+#define BRCMF_NUMCHANNELS 64
|
||||
|
||||
#define BRCMF_PFN_MACADDR_CFG_VER 1
|
||||
#define BRCMF_PFN_MAC_OUI_ONLY BIT(0)
|
||||
@@ -719,6 +720,21 @@ struct brcmf_pno_param_le {
|
||||
};
|
||||
|
||||
/**
|
||||
+ * struct brcmf_pno_config_le - PNO channel configuration.
|
||||
+ *
|
||||
+ * @reporttype: determines what is reported.
|
||||
+ * @channel_num: number of channels specified in @channel_list.
|
||||
+ * @channel_list: channels to use in PNO scan.
|
||||
+ * @flags: reserved.
|
||||
+ */
|
||||
+struct brcmf_pno_config_le {
|
||||
+ __le32 reporttype;
|
||||
+ __le32 channel_num;
|
||||
+ __le16 channel_list[BRCMF_NUMCHANNELS];
|
||||
+ __le32 flags;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
* struct brcmf_pno_net_param_le - scan parameters per preferred network.
|
||||
*
|
||||
* @ssid: ssid name and its length.
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
@@ -18,9 +18,10 @@
|
||||
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
-#include "pno.h"
|
||||
#include "fwil.h"
|
||||
#include "fwil_types.h"
|
||||
+#include "cfg80211.h"
|
||||
+#include "pno.h"
|
||||
|
||||
#define BRCMF_PNO_VERSION 2
|
||||
#define BRCMF_PNO_REPEAT 4
|
||||
@@ -34,6 +35,15 @@
|
||||
#define BRCMF_PNO_HIDDEN_BIT 2
|
||||
#define BRCMF_PNO_SCHED_SCAN_PERIOD 30
|
||||
|
||||
+static int brcmf_pno_channel_config(struct brcmf_if *ifp,
|
||||
+ struct brcmf_pno_config_le *cfg)
|
||||
+{
|
||||
+ cfg->reporttype = 0;
|
||||
+ cfg->flags = 0;
|
||||
+
|
||||
+ return brcmf_fil_iovar_data_set(ifp, "pfn_cfg", cfg, sizeof(*cfg));
|
||||
+}
|
||||
+
|
||||
static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
|
||||
u32 mscan, u32 bestn)
|
||||
{
|
||||
@@ -167,7 +177,10 @@ int brcmf_pno_clean(struct brcmf_if *ifp
|
||||
int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
|
||||
struct cfg80211_sched_scan_request *req)
|
||||
{
|
||||
+ struct brcmu_d11inf *d11inf;
|
||||
+ struct brcmf_pno_config_le pno_cfg;
|
||||
struct cfg80211_ssid *ssid;
|
||||
+ u16 chan;
|
||||
int i, ret;
|
||||
|
||||
/* clean up everything */
|
||||
@@ -190,6 +203,17 @@ int brcmf_pno_start_sched_scan(struct br
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ /* configure channels to use */
|
||||
+ d11inf = &ifp->drvr->config->d11inf;
|
||||
+ for (i = 0; i < req->n_channels; i++) {
|
||||
+ chan = req->channels[i]->hw_value;
|
||||
+ pno_cfg.channel_list[i] = cpu_to_le16(chan);
|
||||
+ }
|
||||
+ if (req->n_channels) {
|
||||
+ pno_cfg.channel_num = cpu_to_le32(req->n_channels);
|
||||
+ brcmf_pno_channel_config(ifp, &pno_cfg);
|
||||
+ }
|
||||
+
|
||||
/* configure each match set */
|
||||
for (i = 0; i < req->n_match_sets; i++) {
|
||||
ssid = &req->match_sets[i].ssid;
|
|
@ -1,34 +0,0 @@
|
|||
From dfe5b0d52d5880bd9d4b427e1a53c9e9e4c3c820 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:29 +0000
|
||||
Subject: [PATCH] brcmfmac: remove restriction from .sched_scan_start()
|
||||
callback
|
||||
|
||||
In the .sched_scan_start() callback a condition was checked whether a
|
||||
normal scan was ongoing. However, there is no need for this check as
|
||||
it is ok to start the scheduled scan irrespective whether or not a
|
||||
normal scan is ongoing.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -3351,10 +3351,7 @@ brcmf_cfg80211_sched_scan_start(struct w
|
||||
|
||||
brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
|
||||
req->n_match_sets, req->n_ssids);
|
||||
- if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
|
||||
- brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
|
||||
- return -EAGAIN;
|
||||
- }
|
||||
+
|
||||
if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
|
||||
brcmf_err("Scanning suppressed: status (%lu)\n",
|
||||
cfg->scan_status);
|
|
@ -1,67 +0,0 @@
|
|||
From c6989fd55ceb633d2f18c12ffae01b9123125c89 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:30 +0000
|
||||
Subject: [PATCH] brcmfmac: use requested scan interval in scheduled scan
|
||||
|
||||
User-space can specify the interval for the scheduled scan. This
|
||||
interval is found in scheduled scan plan. The driver supports only
|
||||
one plan, which is legacy behaviour.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 1 +
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 6 +++++-
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 6 ++++--
|
||||
3 files changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -6312,6 +6312,7 @@ static void brcmf_wiphy_pno_params(struc
|
||||
wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
|
||||
wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
|
||||
wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
|
||||
+ wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
|
||||
wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
@@ -63,6 +63,10 @@ static int brcmf_pno_config(struct brcmf
|
||||
pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
|
||||
|
||||
/* set up pno scan fr */
|
||||
+ if (scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) {
|
||||
+ brcmf_dbg(SCAN, "scan period too small, using minimum\n");
|
||||
+ scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD;
|
||||
+ }
|
||||
pfn_param.scan_freq = cpu_to_le32(scan_freq);
|
||||
|
||||
if (mscan) {
|
||||
@@ -191,7 +195,7 @@ int brcmf_pno_start_sched_scan(struct br
|
||||
}
|
||||
|
||||
/* configure pno */
|
||||
- ret = brcmf_pno_config(ifp, BRCMF_PNO_SCHED_SCAN_PERIOD, 0, 0);
|
||||
+ ret = brcmf_pno_config(ifp, req->scan_plans[0].interval, 0, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
||||
@@ -16,8 +16,10 @@
|
||||
#ifndef _BRCMF_PNO_H
|
||||
#define _BRCMF_PNO_H
|
||||
|
||||
-#define BRCMF_PNO_SCAN_COMPLETE 1
|
||||
-#define BRCMF_PNO_MAX_PFN_COUNT 16
|
||||
+#define BRCMF_PNO_SCAN_COMPLETE 1
|
||||
+#define BRCMF_PNO_MAX_PFN_COUNT 16
|
||||
+#define BRCMF_PNO_SCHED_SCAN_MIN_PERIOD 10
|
||||
+#define BRCMF_PNO_SCHED_SCAN_MAX_PERIOD 508
|
||||
|
||||
/**
|
||||
* brcmf_pno_clean - disable and clear pno in firmware.
|
|
@ -1,76 +0,0 @@
|
|||
From 53e3a80d80c80bf50ab64cf6c44fb0fa41aa22d8 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Wed, 23 Nov 2016 10:25:31 +0000
|
||||
Subject: [PATCH] brcmfmac: fix scheduled scan result handling for newer chips
|
||||
|
||||
The scan results for scheduled scan as retrieved from the device
|
||||
have changed. A field has been added which is not needed. However,
|
||||
the appended info is. Luckily they are versioned so check that to
|
||||
find out the location of the appended data.
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 24 +++++++++++++++++++++-
|
||||
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 7 +++++++
|
||||
2 files changed, 30 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -3257,6 +3257,28 @@ static int brcmf_start_internal_escan(st
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static struct brcmf_pno_net_info_le *
|
||||
+brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)
|
||||
+{
|
||||
+ struct brcmf_pno_scanresults_v2_le *pfn_v2;
|
||||
+ struct brcmf_pno_net_info_le *netinfo;
|
||||
+
|
||||
+ switch (pfn_v1->version) {
|
||||
+ default:
|
||||
+ WARN_ON(1);
|
||||
+ /* fall-thru */
|
||||
+ case cpu_to_le32(1):
|
||||
+ netinfo = (struct brcmf_pno_net_info_le *)(pfn_v1 + 1);
|
||||
+ break;
|
||||
+ case cpu_to_le32(2):
|
||||
+ pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1;
|
||||
+ netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return netinfo;
|
||||
+}
|
||||
+
|
||||
/* PFN result doesn't have all the info which are required by the supplicant
|
||||
* (For e.g IEs) Do a target Escan so that sched scan results are reported
|
||||
* via wl_inform_single_bss in the required format. Escan does require the
|
||||
@@ -3309,7 +3331,7 @@ brcmf_notify_sched_scan_results(struct b
|
||||
}
|
||||
|
||||
data += sizeof(struct brcmf_pno_scanresults_le);
|
||||
- netinfo_start = (struct brcmf_pno_net_info_le *)data;
|
||||
+ netinfo_start = brcmf_get_netinfo_array(pfn_result);
|
||||
|
||||
for (i = 0; i < result_count; i++) {
|
||||
netinfo = &netinfo_start[i];
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
|
||||
@@ -785,6 +785,13 @@ struct brcmf_pno_scanresults_le {
|
||||
__le32 count;
|
||||
};
|
||||
|
||||
+struct brcmf_pno_scanresults_v2_le {
|
||||
+ __le32 version;
|
||||
+ __le32 status;
|
||||
+ __le32 count;
|
||||
+ __le32 scan_ch_bucket;
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct brcmf_pno_macaddr_le - to configure PNO macaddr randomization.
|
||||
*
|
|
@ -1,47 +0,0 @@
|
|||
From cb853da3a368c40300a0e940f86be582037bb082 Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Fri, 9 Dec 2016 11:34:13 +0000
|
||||
Subject: [PATCH] brcmfmac: fix memory leak in brcmf_cfg80211_attach()
|
||||
|
||||
In brcmf_cfg80211_attach() there was one error path not properly
|
||||
handled as it leaked memory allocated in brcmf_btcoex_attach().
|
||||
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -6866,7 +6866,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
|
||||
|
||||
err = brcmf_p2p_attach(cfg, p2pdev_forced);
|
||||
if (err) {
|
||||
- brcmf_err("P2P initilisation failed (%d)\n", err);
|
||||
+ brcmf_err("P2P initialisation failed (%d)\n", err);
|
||||
goto wiphy_unreg_out;
|
||||
}
|
||||
err = brcmf_btcoex_attach(cfg);
|
||||
@@ -6891,7 +6891,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
|
||||
err = brcmf_fweh_activate_events(ifp);
|
||||
if (err) {
|
||||
brcmf_err("FWEH activation failed (%d)\n", err);
|
||||
- goto wiphy_unreg_out;
|
||||
+ goto detach;
|
||||
}
|
||||
|
||||
/* Fill in some of the advertised nl80211 supported features */
|
||||
@@ -6906,6 +6906,9 @@ struct brcmf_cfg80211_info *brcmf_cfg802
|
||||
|
||||
return cfg;
|
||||
|
||||
+detach:
|
||||
+ brcmf_btcoex_detach(cfg);
|
||||
+ brcmf_p2p_detach(&cfg->p2p);
|
||||
wiphy_unreg_out:
|
||||
wiphy_unregister(cfg->wiphy);
|
||||
priv_out:
|
|
@ -1,29 +0,0 @@
|
|||
From 2b66325d5ea7c2a39ac69ed83b6979afe480d81a Mon Sep 17 00:00:00 2001
|
||||
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||||
Date: Fri, 9 Dec 2016 11:34:14 +0000
|
||||
Subject: [PATCH] brcmfmac: fix uninitialized field in scheduled scan ssid
|
||||
configuration
|
||||
|
||||
The scheduled scan ssid configuration in firmware has a flags field that
|
||||
was not initialized resulting in unexpected behaviour.
|
||||
|
||||
Fixes: e3bdb7cc0300 ("brcmfmac: fix handling ssids in .sched_scan_start() callback")
|
||||
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||||
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
||||
@@ -137,6 +137,7 @@ static int brcmf_pno_add_ssid(struct brc
|
||||
pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
|
||||
pfn.wsec = cpu_to_le32(0);
|
||||
pfn.infra = cpu_to_le32(1);
|
||||
+ pfn.flags = 0;
|
||||
if (active)
|
||||
pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
|
||||
pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len);
|
|
@ -1,35 +0,0 @@
|
|||
From ad334bbb07b07e2873942571b0c9f3c34571bd47 Mon Sep 17 00:00:00 2001
|
||||
From: Colin Ian King <colin.king@canonical.com>
|
||||
Date: Fri, 23 Dec 2016 00:43:22 +0000
|
||||
Subject: [PATCH] brcmfmac: fix spelling mistakes on "Ivalid"
|
||||
|
||||
Trivial fixes to spelling mistake "Ivalid" to "Invalid" in
|
||||
brcmf_err error messages.
|
||||
|
||||
Signed-off-by: Colin Ian King <colin.king@canonical.com>
|
||||
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -3969,7 +3969,7 @@ brcmf_configure_wpaie(struct brcmf_if *i
|
||||
pval |= AES_ENABLED;
|
||||
break;
|
||||
default:
|
||||
- brcmf_err("Ivalid unicast security info\n");
|
||||
+ brcmf_err("Invalid unicast security info\n");
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
@@ -4013,7 +4013,7 @@ brcmf_configure_wpaie(struct brcmf_if *i
|
||||
wpa_auth |= WPA2_AUTH_1X_SHA256;
|
||||
break;
|
||||
default:
|
||||
- brcmf_err("Ivalid key mgmt info\n");
|
||||
+ brcmf_err("Invalid key mgmt info\n");
|
||||
}
|
||||
offset++;
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Wed, 4 Jan 2017 12:09:41 +0100
|
||||
Subject: [PATCH] brcmfmac: avoid writing channel out of allocated array
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Our code was assigning number of channels to the index variable by
|
||||
default. If firmware reported channel we didn't predict this would
|
||||
result in using that initial index value and writing out of array. This
|
||||
never happened so far (we got a complete list of supported channels) but
|
||||
it means possible memory corruption so we should handle it anyway.
|
||||
|
||||
This patch simply detects unexpected channel and ignores it.
|
||||
|
||||
As we don't try to create new entry now, it's also safe to drop hw_value
|
||||
and center_freq assignment. For known channels we have these set anyway.
|
||||
|
||||
I decided to fix this issue by assigning NULL or a target channel to the
|
||||
channel variable. This was one of possible ways, I prefefred this one as
|
||||
it also avoids using channel[index] over and over.
|
||||
|
||||
Fixes: 58de92d2f95e ("brcmfmac: use static superset of channels for wiphy bands")
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -5823,7 +5823,6 @@ static int brcmf_construct_chaninfo(stru
|
||||
u32 i, j;
|
||||
u32 total;
|
||||
u32 chaninfo;
|
||||
- u32 index;
|
||||
|
||||
pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
|
||||
|
||||
@@ -5871,33 +5870,36 @@ static int brcmf_construct_chaninfo(stru
|
||||
ch.bw == BRCMU_CHAN_BW_80)
|
||||
continue;
|
||||
|
||||
- channel = band->channels;
|
||||
- index = band->n_channels;
|
||||
+ channel = NULL;
|
||||
for (j = 0; j < band->n_channels; j++) {
|
||||
- if (channel[j].hw_value == ch.control_ch_num) {
|
||||
- index = j;
|
||||
+ if (band->channels[j].hw_value == ch.control_ch_num) {
|
||||
+ channel = &band->channels[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
- channel[index].center_freq =
|
||||
- ieee80211_channel_to_frequency(ch.control_ch_num,
|
||||
- band->band);
|
||||
- channel[index].hw_value = ch.control_ch_num;
|
||||
+ if (!channel) {
|
||||
+ /* It seems firmware supports some channel we never
|
||||
+ * considered. Something new in IEEE standard?
|
||||
+ */
|
||||
+ brcmf_err("Ignoring unexpected firmware channel %d\n",
|
||||
+ ch.control_ch_num);
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
/* assuming the chanspecs order is HT20,
|
||||
* HT40 upper, HT40 lower, and VHT80.
|
||||
*/
|
||||
if (ch.bw == BRCMU_CHAN_BW_80) {
|
||||
- channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ;
|
||||
+ channel->flags &= ~IEEE80211_CHAN_NO_80MHZ;
|
||||
} else if (ch.bw == BRCMU_CHAN_BW_40) {
|
||||
- brcmf_update_bw40_channel_flag(&channel[index], &ch);
|
||||
+ brcmf_update_bw40_channel_flag(channel, &ch);
|
||||
} else {
|
||||
/* enable the channel and disable other bandwidths
|
||||
* for now as mentioned order assure they are enabled
|
||||
* for subsequent chanspecs.
|
||||
*/
|
||||
- channel[index].flags = IEEE80211_CHAN_NO_HT40 |
|
||||
- IEEE80211_CHAN_NO_80MHZ;
|
||||
+ channel->flags = IEEE80211_CHAN_NO_HT40 |
|
||||
+ IEEE80211_CHAN_NO_80MHZ;
|
||||
ch.bw = BRCMU_CHAN_BW_20;
|
||||
cfg->d11inf.encchspec(&ch);
|
||||
chaninfo = ch.chspec;
|
||||
@@ -5905,11 +5907,11 @@ static int brcmf_construct_chaninfo(stru
|
||||
&chaninfo);
|
||||
if (!err) {
|
||||
if (chaninfo & WL_CHAN_RADAR)
|
||||
- channel[index].flags |=
|
||||
+ channel->flags |=
|
||||
(IEEE80211_CHAN_RADAR |
|
||||
IEEE80211_CHAN_NO_IR);
|
||||
if (chaninfo & WL_CHAN_PASSIVE)
|
||||
- channel[index].flags |=
|
||||
+ channel->flags |=
|
||||
IEEE80211_CHAN_NO_IR;
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Sat, 7 Jan 2017 21:36:04 +0100
|
||||
Subject: [PATCH] brcmfmac: don't preset all channels as disabled
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
During init we take care of regulatory stuff by disabling all
|
||||
unavailable channels (see brcmf_construct_chaninfo) so this predisabling
|
||||
them is not really required (and this patch won't change any behavior).
|
||||
It will on the other hand allow more detailed runtime control over
|
||||
channels which is the main reason for this change.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -138,7 +138,6 @@ static struct ieee80211_rate __wl_rates[
|
||||
.band = NL80211_BAND_2GHZ, \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_channel), \
|
||||
- .flags = IEEE80211_CHAN_DISABLED, \
|
||||
.max_antenna_gain = 0, \
|
||||
.max_power = 30, \
|
||||
}
|
||||
@@ -147,7 +146,6 @@ static struct ieee80211_rate __wl_rates[
|
||||
.band = NL80211_BAND_5GHZ, \
|
||||
.center_freq = 5000 + (5 * (_channel)), \
|
||||
.hw_value = (_channel), \
|
||||
- .flags = IEEE80211_CHAN_DISABLED, \
|
||||
.max_antenna_gain = 0, \
|
||||
.max_power = 30, \
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Sat, 7 Jan 2017 21:36:05 +0100
|
||||
Subject: [PATCH] brcmfmac: setup wiphy bands after registering it first
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
During bands setup we disable all channels that firmware doesn't support
|
||||
in the current regulatory setup. If we do this before wiphy_register
|
||||
it will result in copying set flags (including IEEE80211_CHAN_DISABLED)
|
||||
to the orig_flags which is supposed to be persistent. We don't want this
|
||||
as regulatory change may result in enabling some channels. We shouldn't
|
||||
mess with orig_flags then (by changing them or ignoring them) so it's
|
||||
better to just take care of their proper values.
|
||||
|
||||
This patch cleanups code a bit (by taking orig_flags more seriously) and
|
||||
allows further improvements like disabling really unavailable channels.
|
||||
We will need that e.g. if some frequencies should be disabled for good
|
||||
due to hardware setup (design).
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -6475,8 +6475,7 @@ static int brcmf_setup_wiphy(struct wiph
|
||||
wiphy->bands[NL80211_BAND_5GHZ] = band;
|
||||
}
|
||||
}
|
||||
- err = brcmf_setup_wiphybands(wiphy);
|
||||
- return err;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
|
||||
@@ -6841,6 +6840,12 @@ struct brcmf_cfg80211_info *brcmf_cfg802
|
||||
goto priv_out;
|
||||
}
|
||||
|
||||
+ err = brcmf_setup_wiphybands(wiphy);
|
||||
+ if (err) {
|
||||
+ brcmf_err("Setting wiphy bands failed (%d)\n", err);
|
||||
+ goto wiphy_unreg_out;
|
||||
+ }
|
||||
+
|
||||
/* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
|
||||
* setup 40MHz in 2GHz band and enable OBSS scanning.
|
||||
*/
|
|
@ -1,78 +0,0 @@
|
|||
From e457a8a01a19277e96830d3d95887e0e3c1e2f26 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Sat, 7 Jan 2017 23:43:45 +0100
|
||||
Subject: [PATCH] brcmfmac: make brcmf_of_probe more generic
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We may want to use Open Firmware for other devices than just SDIO ones.
|
||||
In future we may want to support more Broadcom properties so there is
|
||||
really no reason for such limitation.
|
||||
|
||||
Call brcmf_of_probe for all kind of devices & move extra conditions to
|
||||
the body of that funcion.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 8 +++-----
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c | 7 +++++--
|
||||
drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h | 6 ++++--
|
||||
3 files changed, 12 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
|
||||
@@ -299,11 +299,9 @@ struct brcmf_mp_device *brcmf_get_module
|
||||
}
|
||||
}
|
||||
}
|
||||
- if ((bus_type == BRCMF_BUSTYPE_SDIO) && (!found)) {
|
||||
- /* No platform data for this device. In case of SDIO try OF
|
||||
- * (Open Firwmare) Device Tree.
|
||||
- */
|
||||
- brcmf_of_probe(dev, &settings->bus.sdio);
|
||||
+ if (!found) {
|
||||
+ /* No platform data for this device, try OF (Open Firwmare) */
|
||||
+ brcmf_of_probe(dev, bus_type, settings);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
||||
@@ -23,14 +23,17 @@
|
||||
#include "common.h"
|
||||
#include "of.h"
|
||||
|
||||
-void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
|
||||
+void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
||||
+ struct brcmf_mp_device *settings)
|
||||
{
|
||||
+ struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio;
|
||||
struct device_node *np = dev->of_node;
|
||||
int irq;
|
||||
u32 irqf;
|
||||
u32 val;
|
||||
|
||||
- if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
|
||||
+ if (!np || bus_type != BRCMF_BUSTYPE_SDIO ||
|
||||
+ !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
|
||||
return;
|
||||
|
||||
if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
|
||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
|
||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
|
||||
@@ -14,9 +14,11 @@
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef CONFIG_OF
|
||||
-void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio);
|
||||
+void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
||||
+ struct brcmf_mp_device *settings);
|
||||
#else
|
||||
-static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
|
||||
+static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
||||
+ struct brcmf_mp_device *settings)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue