* Re: ROAM/CONNECT event with PORT_AUTHORIZED
From: Johannes Berg @ 2017-09-15 7:19 UTC (permalink / raw)
To: Denis Kenzior, Arend van Spriel, Jouni Malinen
Cc: Avraham Stern, linux-wireless
In-Reply-To: <94a01366-1af7-4728-59e4-847bfd8476e0@gmail.com>
On Thu, 2017-09-14 at 14:54 -0500, Denis Kenzior wrote:
> If you want roaming to keep oper state UP in all cases, then
> yes. Does this work on full mac cards as well?
I don't see why not.
> E.g. if I CMD_CONNECT to AP1, then pre-authenticate to AP2 and issue
> a CMD_CONNECT to AP2?
That's not something you can do with full-MAC cards?
And even mac80211 doesn't really support pre-authentication (unless you
mean over-the-DS)
johannes
^ permalink raw reply
* Re: ROAM/CONNECT event with PORT_AUTHORIZED
From: Johannes Berg @ 2017-09-15 7:20 UTC (permalink / raw)
To: Ben Greear, Denis Kenzior, Arend van Spriel, Arend van Spriel,
Jouni Malinen
Cc: Avraham Stern, linux-wireless
In-Reply-To: <c33e5aed-be5a-890d-cc50-b5ac87b40d9a@candelatech.com>
On Thu, 2017-09-14 at 13:47 -0700, Ben Greear wrote:
> Seems like we would need some way for the DHCP server and/or AP to
> proactively notify the station that they can skip DHCP, and default
> to not skipping.
I really disagree with that - every sane network should behave the
proper way, trying to push workarounds for stupid networks into all
layers of the stack seems like a really bad idea.
johannes
^ permalink raw reply
* Re: ROAM/CONNECT event with PORT_AUTHORIZED
From: Johannes Berg @ 2017-09-15 7:23 UTC (permalink / raw)
To: Ben Greear, Denis Kenzior, Arend van Spriel, Arend van Spriel,
Jouni Malinen
Cc: Avraham Stern, linux-wireless
In-Reply-To: <e7380aff-7e48-cfcb-b40d-530ac428a137@candelatech.com>
On Thu, 2017-09-14 at 15:57 -0700, Ben Greear wrote:
>
> What about two APs with ssid LEDE and open-auth, each serving DHCP,
> each connected to a switch that connects to a cable modem, etc.
Take a cluebat to the adminstrator?
It's really simple to disable DHCP on one of them, and if you properly
connect them to the same switch, everything works. I've done that in a
few places (not my own house because a single AP covers it well enough
for me, so ...).
> On initial connection to the network, the station does DHCP and gets
> a response, like normal.
> But, that response has a special message in it that says "you don't
> need to re-do dhcp if you roam here".
> User-space remembers this response for future roams...
>
> After that, then you skip DHCP on roam to this SSID/auth network, so
> you have zero extra network overhead when roaming.
That will be so much harder to configure.
johannes
^ permalink raw reply
* [PATCH] Revert "PCI: Avoid race while enabling upstream bridges"
From: Bjorn Helgaas @ 2017-09-15 7:23 UTC (permalink / raw)
To: linux-pci
Cc: Jens Axboe, Emmanuel Grumbach, linuxwifi, linux-wireless,
linux-kernel, Srinath Mannam, Johannes Berg, Luca Coelho
This reverts commit 40f11adc7cd9281227f0a6a627d966dd0a5f0cd9.
Jens found that iwlwifi firmware loading failed on a Lenovo X1 Carbon,
gen4:
iwlwifi 0000:04:00.0: Direct firmware load for iwlwifi-8000C-34.ucode failed with error -2
iwlwifi 0000:04:00.0: Direct firmware load for iwlwifi-8000C-33.ucode failed with error -2
iwlwifi 0000:04:00.0: Direct firmware load for iwlwifi-8000C-32.ucode failed with error -2
iwlwifi 0000:04:00.0: loaded firmware version 31.532993.0 op_mode iwlmvm
iwlwifi 0000:04:00.0: Detected Intel(R) Dual Band Wireless AC 8260, REV=0x208
...
iwlwifi 0000:04:00.0: Failed to load firmware chunk!
iwlwifi 0000:04:00.0: Could not load the [0] uCode section
iwlwifi 0000:04:00.0: Failed to start INIT ucode: -110
iwlwifi 0000:04:00.0: Failed to run INIT ucode: -110
He bisected it to 40f11adc7cd9 ("PCI: Avoid race while enabling upstream
bridges"). Revert that commit to fix the regression.
Link: http://lkml.kernel.org/r/4bcbcbc1-7c79-09f0-5071-bc2f53bf6574@kernel.dk
Fixes: 40f11adc7cd9 ("PCI: Avoid race while enabling upstream bridges")
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
CC: Srinath Mannam <srinath.mannam@broadcom.com>
CC: Jens Axboe <axboe@kernel.dk>
CC: Luca Coelho <luca@coelho.fi>
CC: Johannes Berg <johannes@sipsolutions.net>
CC: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
drivers/pci/pci.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b0002daa50f3..6078dfc11b11 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -52,7 +52,6 @@ static void pci_pme_list_scan(struct work_struct *work);
static LIST_HEAD(pci_pme_list);
static DEFINE_MUTEX(pci_pme_list_mutex);
static DECLARE_DELAYED_WORK(pci_pme_work, pci_pme_list_scan);
-static DEFINE_MUTEX(pci_bridge_mutex);
struct pci_pme_device {
struct list_head list;
@@ -1351,16 +1350,10 @@ static void pci_enable_bridge(struct pci_dev *dev)
if (bridge)
pci_enable_bridge(bridge);
- /*
- * Hold pci_bridge_mutex to prevent a race when enabling two
- * devices below the bridge simultaneously. The race may cause a
- * PCI_COMMAND_MEMORY update to be lost (see changelog).
- */
- mutex_lock(&pci_bridge_mutex);
if (pci_is_enabled(dev)) {
if (!dev->is_busmaster)
pci_set_master(dev);
- goto end;
+ return;
}
retval = pci_enable_device(dev);
@@ -1368,8 +1361,6 @@ static void pci_enable_bridge(struct pci_dev *dev)
dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n",
retval);
pci_set_master(dev);
-end:
- mutex_unlock(&pci_bridge_mutex);
}
static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
@@ -1394,7 +1385,7 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
return 0; /* already enabled */
bridge = pci_upstream_bridge(dev);
- if (bridge && !pci_is_enabled(bridge))
+ if (bridge)
pci_enable_bridge(bridge);
/* only skip sriov related */
^ permalink raw reply related
* Re: [RFC 2/4] mac80211_hwsim: add hwsim_tx_rate_flags to Netlink Attributes
From: Johannes Berg @ 2017-09-15 7:36 UTC (permalink / raw)
To: Benjamin Beichler, linux-wireless
In-Reply-To: <91d055d9-0974-1d18-02d0-fc5dc59b949c@uni-rostock.de>
On Mon, 2017-09-11 at 11:49 +0200, Benjamin Beichler wrote:
> I don't know what is the problem with the details. The only flag,
> which is a bit to verbose is MAC80211_HWSIM_TX_RC_DUP_DATA, which we
> may omit. All others describe directly terms used in the IEEE 802.11
> standard. Also the representation, that a rate is an MCS-index is
> quite good. If you take look here http://mcsindex.com/ , the bitrate
> would be not sufficient to get the exact coding and fec rate,
> therefore you would also need additional flags. You are right
> regarding legacy rates, which are in an encoded table. I tried to
> decouple internal and external API, but currently there is no big
> difference.
Yeah, I was just concerned that maybe this API was too tightly coupled
to mac80211, but I guess it should be fine.
> Nonetheless the whole hwsim API is highly specialized and only usable
> with the linux kernel. Of course the Userland API should be more or
> less stable, but the backward compatibility is not touched by this
> change. As I already said, this is nearly a fix for hwsim, since
> currently it's impossible to differentiate between legacy and MCS-
> rates, although they could appear in a single tx_rates array. I think
> currently minstrel does not mix HT and legacy rates for data frames,
> but AFAIK Management/Action frames are always sent with legacy rates,
> so there are mixed already.
Ok.
johannes
^ permalink raw reply
* What makes USB WiFi so difficult in Linux and may I help out?
From: Ernst Wegner @ 2017-09-15 8:48 UTC (permalink / raw)
To: linux-wireless
Dear list!
I recently suffer from attempts to use some USB WiFi sticks to connect
to a wireless network using Linux. I tried that with a number of
distros, but found that there seem to be kind of the same problems all
the way from Linux 2.6.x to 4.x. Most USB WiFi sticks don't work
reliably.
As I am a developer also (and very interested in these things) I would
be willing to help debugging drivers and possibly fix them. But I
don't really know where to start searching. So some hints would be
very welcome.
Currently I try to get this one here to work:
Bus 001 Device 006: ID 148f:5370 Ralink Technology, Corp. RT5370
Wireless Adapter
I am on Debian 9 with a pretty recent kernel:
Linux debian 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u3 (2017-08-06)
x86_64 GNU/Linux
I was able to get this stick to work kind of. Actually, it drops the
connection every couple of minutes, without any error messages in
dmesg or syslog, actually. But I was able to reach that state only
after applying some tweaks like disabling hardware encrypt, i.e.
options rt2800usb nohwcrypt=y
and
[device]
wifi.scan-rand-mac-address=no
So any pointers would be welcome.
I am not afraid to dig into the code of the driver and recompile.
I could also possibly add or enable some debugging code so I will get
some more debugging output to see what actually happens when I loose
the connection, i.e. if this is an external event, a special kind of
package, overload, ...
And finally: This isn't the only USB Wifi stick which has serious
problems with Linux. The Internet is full of this including drivers
for some sticks which don't work at all and don't go anywhere for
month. Obviously it's not the sticks to blame, as they all work fine
on Windows. So what's the underlying story here which I am missing?
Regards,
Torsten
^ permalink raw reply
* RE: [EXT] Re: [PATCH 2/2] mwifiex: print URB submit failure error after threshold attemtps
From: Ganapathi Bhat @ 2017-09-15 9:46 UTC (permalink / raw)
To: Brian Norris, Joe Perches
Cc: Cathy Luo, Xinming Hu, Zhiyuan Yang, James Cao, Mangesh Malusare,
linux-wireless@vger.kernel.org
In-Reply-To: <20170914215955.GA42289@google.com>
Hi Brian,
>
> Hi Ganapathi,
>
> On Thu, Sep 14, 2017 at 02:14:24PM +0000, Ganapathi Bhat wrote:
> > > On Thu, 2017-08-31 at 01:21 +0530, Ganapathi Bhat wrote:
> > > > Current driver prints dev_alloc_skb failures everytime while
> > > > submitting RX URBs. This failure might be frequent in some low
> > > > resource platforms. So, wait for a threshold failure count before
> > > > start priting the error. This change is a follow up for the
> > > > 'commit
> > > > 7b368e3d15c3
> > > > ("mwifiex: resubmit failed to submit RX URBs in main thread")'
> > >
> > > []
> > >
> > > > diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c
> > > > b/drivers/net/wireless/marvell/mwifiex/usb.c
> > > []
> > > > @@ -300,9 +300,16 @@ static int mwifiex_usb_submit_rx_urb(struct
> > > urb_context *ctx, int size)
> > > > if (card->rx_cmd_ep != ctx->ep) {
> > > > ctx->skb = dev_alloc_skb(size);
> > > > if (!ctx->skb) {
> > > > - mwifiex_dbg(adapter, ERROR,
> > > > - "%s: dev_alloc_skb failed\n",
> __func__);
> > > > + if (++card->rx_urb_failure_count >
> > > > + MWIFIEX_RX_URB_FAILURE_THRESHOLD) {
> > > > + mwifiex_dbg(adapter, ERROR,
> > > > + "%s: dev_alloc_skb failed,
> failure
> > > count = %u\n",
> > > > + __func__,
> > > > + card->rx_urb_failure_count);
> > > > + }
> > > > return -ENOMEM;
> > >
> > > Why not use a ratelimit?
> > Since this is for receive, the packets are from AP side and we cannot
> > lower the rate from AP. On some low performance systems this change
> > will be helpful.
>
> I think Joe was referring to things like printk_ratelimited() or
> dev_err_ratelimited(). Those automatically ratelimit prints for you,
> using a static counter. You'd just need to make a small warpper for
> mwifiex_dbg() using __ratelimit().
Got it. Yet it looks he meant the same. Thank you.
>
> Those sort of rate limits are significantly different than yours
> though.
> You were looking to avoid printing errors when there are only a few
> failures in a row, whereas the existing rate-limiting infrastructure
> looks to avoid printing errors if too many happen in a row. Those are
> different goals.
>
> Brian
Ok.
Hi Joe,
Let us know your comments on the above.
Thanks,
Ganapathi
^ permalink raw reply
* [RFC 0/4] cfg80211: in-kernel regulatory database
From: Johannes Berg @ 2017-09-15 10:18 UTC (permalink / raw)
To: linux-wireless
I've been sitting on these patches for pretty much 2 years, waiting
for the firmware loader to gain signature checking abilities. This
hasn't happened, and even the suggested code from AKASHI Takahiro
doesn't fulfill all requirements, notably having extra keys/keyring.
I'm not sure building the keys into the module really is the best
option, but then again, that's the same way it's done with crda.
Additionally, we've not been able to extend the regulatory database
format, and for even longer we've been wanting to do that, e.g. to
add spectral density power limits and DFS configuration. Since the
new database format is easily extensible (variable size on all of
the structures used, with only the minimum size being required), the
extensions can finally be done with this.
johannes
^ permalink raw reply
* [RFC 3/4] cfg80211: reg: remove support for built-in regdb
From: Johannes Berg @ 2017-09-15 10:18 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20170915101810.11435-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
Parsing and building C structures from a regdb is no longer needed
since the "firmware" file (regulatory.db) can be linked into the
kernel image to achieve the same effect.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
Documentation/networking/regulatory.txt | 22 +----
net/wireless/Kconfig | 24 +----
net/wireless/Makefile | 6 --
net/wireless/db.txt | 17 ----
net/wireless/genregdb.awk | 158 --------------------------------
net/wireless/reg.c | 38 --------
6 files changed, 3 insertions(+), 262 deletions(-)
delete mode 100644 net/wireless/db.txt
delete mode 100644 net/wireless/genregdb.awk
diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt
index 46c8d8b1cc66..381e5b23d61d 100644
--- a/Documentation/networking/regulatory.txt
+++ b/Documentation/networking/regulatory.txt
@@ -200,23 +200,5 @@ Then in some part of your code after your wiphy has been registered:
Statically compiled regulatory database
---------------------------------------
-In most situations the userland solution using CRDA as described
-above is the preferred solution. However in some cases a set of
-rules built into the kernel itself may be desirable. To account
-for this situation, a configuration option has been provided
-(i.e. CONFIG_CFG80211_INTERNAL_REGDB). With this option enabled,
-the wireless database information contained in net/wireless/db.txt is
-used to generate a data structure encoded in net/wireless/regdb.c.
-That option also enables code in net/wireless/reg.c which queries
-the data in regdb.c as an alternative to using CRDA.
-
-The file net/wireless/db.txt should be kept up-to-date with the db.txt
-file available in the git repository here:
-
- git://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git
-
-Again, most users in most situations should be using the CRDA package
-provided with their distribution, and in most other situations users
-should be building and using CRDA on their own rather than using
-this option. If you are not absolutely sure that you should be using
-CONFIG_CFG80211_INTERNAL_REGDB then _DO_NOT_USE_IT_.
+When a database should be fixed into the kernel, it can be provided as a
+firmware file at build time that is then linked into the kernel.
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 24eec5516649..f050030055c5 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -140,30 +140,8 @@ config CFG80211_DEBUGFS
If unsure, say N.
-config CFG80211_INTERNAL_REGDB
- bool "use statically compiled regulatory rules database" if EXPERT
- default n
- depends on CFG80211
- ---help---
- This option generates an internal data structure representing
- the wireless regulatory rules described in net/wireless/db.txt
- and includes code to query that database. This is an alternative
- to using CRDA for defining regulatory rules for the kernel.
-
- Using this option requires some parsing of the db.txt at build time,
- the parser will be upkept with the latest wireless-regdb updates but
- older wireless-regdb formats will be ignored. The parser may later
- be replaced to avoid issues with conflicts on versions of
- wireless-regdb.
-
- For details see:
-
- http://wireless.kernel.org/en/developers/Regulatory
-
- Most distributions have a CRDA package. So if unsure, say N.
-
config CFG80211_CRDA_SUPPORT
- bool "support CRDA" if CFG80211_INTERNAL_REGDB
+ bool "support CRDA" if EXPERT
default y
depends on CFG80211
help
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index d06e5015751a..5f20dac5d8c6 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -14,11 +14,5 @@ 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-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
-cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
CFLAGS_trace.o := -I$(src)
-
-$(obj)/regdb.c: $(src)/db.txt $(src)/genregdb.awk
- @$(AWK) -f $(srctree)/$(src)/genregdb.awk < $< > $@
-
-clean-files := regdb.c
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
deleted file mode 100644
index a2fc3a09ccdc..000000000000
--- a/net/wireless/db.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# This file is a placeholder to prevent accidental build breakage if someone
-# enables CONFIG_CFG80211_INTERNAL_REGDB. Almost no one actually needs to
-# enable that build option.
-#
-# You should be using CRDA instead. It is even better if you use the CRDA
-# package provided by your distribution, since they will probably keep it
-# up-to-date on your behalf.
-#
-# If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will
-# need to replace this file with one containing appropriately formatted
-# regulatory rules that cover the regulatory domains you will be using. Your
-# best option is to extract the db.txt file from the wireless-regdb git
-# repository:
-#
-# git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git
-#
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk
deleted file mode 100644
index baf2426b555a..000000000000
--- a/net/wireless/genregdb.awk
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/awk -f
-#
-# genregdb.awk -- generate regdb.c from db.txt
-#
-# Actually, it reads from stdin (presumed to be db.txt) and writes
-# to stdout (presumed to be regdb.c), but close enough...
-#
-# Copyright 2009 John W. Linville <linville@tuxdriver.com>
-#
-# 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.
-
-BEGIN {
- active = 0
- rules = 0;
- print "/*"
- print " * DO NOT EDIT -- file generated from data in db.txt"
- print " */"
- print ""
- print "#include <linux/nl80211.h>"
- print "#include <net/cfg80211.h>"
- print "#include \"regdb.h\""
- print ""
- regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
-}
-
-function parse_country_head() {
- country=$2
- sub(/:/, "", country)
- printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
- printf "\t.alpha2 = \"%s\",\n", country
- if ($NF ~ /DFS-ETSI/)
- printf "\t.dfs_region = NL80211_DFS_ETSI,\n"
- else if ($NF ~ /DFS-FCC/)
- printf "\t.dfs_region = NL80211_DFS_FCC,\n"
- else if ($NF ~ /DFS-JP/)
- printf "\t.dfs_region = NL80211_DFS_JP,\n"
- printf "\t.reg_rules = {\n"
- active = 1
- regdb = regdb "\t®dom_" country ",\n"
-}
-
-function parse_reg_rule()
-{
- flag_starts_at = 7
-
- start = $1
- sub(/\(/, "", start)
- end = $3
- bw = $5
- sub(/\),/, "", bw)
- gain = 0
- power = $6
- # power might be in mW...
- units = $7
- dfs_cac = 0
-
- sub(/\(/, "", power)
- sub(/\),/, "", power)
- sub(/\),/, "", units)
- sub(/\)/, "", units)
-
- if (units == "mW") {
- flag_starts_at = 8
- power = 10 * log(power)/log(10)
- if ($8 ~ /[[:digit:]]/) {
- flag_starts_at = 9
- dfs_cac = $8
- }
- } else {
- if ($7 ~ /[[:digit:]]/) {
- flag_starts_at = 8
- dfs_cac = $7
- }
- }
- sub(/\(/, "", dfs_cac)
- sub(/\),/, "", dfs_cac)
- flagstr = ""
- for (i=flag_starts_at; i<=NF; i++)
- flagstr = flagstr $i
- split(flagstr, flagarray, ",")
- flags = ""
- for (arg in flagarray) {
- if (flagarray[arg] == "NO-OFDM") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_OFDM | "
- } else if (flagarray[arg] == "NO-CCK") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_CCK | "
- } else if (flagarray[arg] == "NO-INDOOR") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_INDOOR | "
- } else if (flagarray[arg] == "NO-OUTDOOR") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_OUTDOOR | "
- } else if (flagarray[arg] == "DFS") {
- flags = flags "\n\t\t\tNL80211_RRF_DFS | "
- } else if (flagarray[arg] == "PTP-ONLY") {
- flags = flags "\n\t\t\tNL80211_RRF_PTP_ONLY | "
- } else if (flagarray[arg] == "PTMP-ONLY") {
- flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | "
- } else if (flagarray[arg] == "PASSIVE-SCAN") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
- } else if (flagarray[arg] == "NO-IBSS") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
- } else if (flagarray[arg] == "NO-IR") {
- flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
- } else if (flagarray[arg] == "AUTO-BW") {
- flags = flags "\n\t\t\tNL80211_RRF_AUTO_BW | "
- }
-
- }
- flags = flags "0"
- printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %.0f, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
- rules++
-}
-
-function print_tail_country()
-{
- active = 0
- printf "\t},\n"
- printf "\t.n_reg_rules = %d\n", rules
- printf "};\n\n"
- rules = 0;
-}
-
-/^[ \t]*#/ {
- # Ignore
-}
-
-!active && /^[ \t]*$/ {
- # Ignore
-}
-
-!active && /country/ {
- parse_country_head()
-}
-
-active && /^[ \t]*\(/ {
- parse_reg_rule()
-}
-
-active && /^[ \t]*$/ {
- print_tail_country()
-}
-
-END {
- if (active)
- print_tail_country()
- print regdb "};"
- print ""
- print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);"
-}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 8d366738c08a..5dd453bdad3a 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -494,38 +494,6 @@ static int reg_schedule_apply(const struct ieee80211_regdomain *regdom)
return 0;
}
-#ifdef CONFIG_CFG80211_INTERNAL_REGDB
-static int reg_query_builtin(const char *alpha2)
-{
- const struct ieee80211_regdomain *regdom = NULL;
- unsigned int i;
-
- for (i = 0; i < reg_regdb_size; i++) {
- if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
- regdom = reg_copy_regd(reg_regdb[i]);
- break;
- }
- }
- if (!regdom)
- return -ENODATA;
-
- return reg_schedule_apply(regdom);
-}
-
-/* Feel free to add any other sanity checks here */
-static void reg_regdb_size_check(void)
-{
- /* We should ideally BUILD_BUG_ON() but then random builds would fail */
- WARN_ONCE(!reg_regdb_size, "db.txt is empty, you should update it...");
-}
-#else
-static inline void reg_regdb_size_check(void) {}
-static inline int reg_query_builtin(const char *alpha2)
-{
- return -ENODATA;
-}
-#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
-
#ifdef CONFIG_CFG80211_CRDA_SUPPORT
/* Max number of consecutive attempts to communicate with CRDA */
#define REG_MAX_CRDA_TIMEOUTS 10
@@ -869,10 +837,6 @@ int reg_reload_regdb(void)
static bool reg_query_database(struct regulatory_request *request)
{
- /* query internal regulatory database (if it exists) */
- if (reg_query_builtin(request->alpha2) == 0)
- return true;
-
if (query_regdb_file(request->alpha2) == 0)
return true;
@@ -3549,8 +3513,6 @@ int __init regulatory_init(void)
spin_lock_init(®_pending_beacons_lock);
spin_lock_init(®_indoor_lock);
- reg_regdb_size_check();
-
rcu_assign_pointer(cfg80211_regdomain, cfg80211_world_regdom);
user_alpha2[0] = '9';
--
2.14.1
^ permalink raw reply related
* [RFC 1/4] cfg80211: support loading regulatory database as firmware file
From: Johannes Berg @ 2017-09-15 10:18 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20170915101810.11435-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
As the current regulatory database is only about 4k big, and already
difficult to extend, we decided that overall it would be better to
get rid of the complications with CRDA and load the database into the
kernel directly, but in a new format that is extensible.
The new file format can be extended since it carries a length field
on all the structs that need to be extensible.
In order to be able to request firmware when the module initializes,
move cfg80211 from subsys_initcall() to the later fs_initcall(); the
firmware loader is at the same level but linked earlier, so it can
be called from there. Otherwise, when both the firmware loader and
cfg80211 are built-in, the request will crash the kernel. We also
need to be before device_initcall() so that cfg80211 is available
for devices when they initialize.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
Documentation/networking/regulatory.txt | 8 +
net/wireless/Kconfig | 4 +-
net/wireless/core.c | 2 +-
net/wireless/reg.c | 265 +++++++++++++++++++++++++++++---
4 files changed, 255 insertions(+), 24 deletions(-)
diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt
index 7818b5fe448b..46c8d8b1cc66 100644
--- a/Documentation/networking/regulatory.txt
+++ b/Documentation/networking/regulatory.txt
@@ -19,6 +19,14 @@ core regulatory domain all wireless devices should adhere to.
How to get regulatory domains to the kernel
-------------------------------------------
+When the regulatory domain is first set up, the kernel will request a
+database file (regulatory.db) containing all the regulatory rules. It
+will then use that database when it needs to look up the rules for a
+given country.
+
+How to get regulatory domains to the kernel (old CRDA solution)
+---------------------------------------------------------------
+
Userspace gets a regulatory domain in the kernel by having
a userspace agent build it and send it via nl80211. Only
expected regulatory domains will be respected by the kernel.
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 6c606120abfe..24eec5516649 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -19,6 +19,7 @@ config WEXT_PRIV
config CFG80211
tristate "cfg80211 - wireless configuration API"
depends on RFKILL || !RFKILL
+ select FW_LOADER
---help---
cfg80211 is the Linux wireless LAN (802.11) configuration API.
Enable this if you have a wireless device.
@@ -167,7 +168,8 @@ config CFG80211_CRDA_SUPPORT
depends on CFG80211
help
You should enable this option unless you know for sure you have no
- need for it, for example when using internal regdb (above.)
+ need for it, for example when using internal regdb (above) or the
+ database loaded as a firmware file.
If unsure, say Y.
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 7b33e8c366bc..fdde0d98fde1 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1384,7 +1384,7 @@ static int __init cfg80211_init(void)
out_fail_pernet:
return err;
}
-subsys_initcall(cfg80211_init);
+fs_initcall(cfg80211_init);
static void __exit cfg80211_exit(void)
{
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 5fae296a6a58..7a1d6cda64f3 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -53,6 +53,7 @@
#include <linux/nl80211.h>
#include <linux/platform_device.h>
#include <linux/moduleparam.h>
+#include <linux/firmware.h>
#include <net/cfg80211.h>
#include "core.h"
#include "reg.h"
@@ -99,7 +100,7 @@ static struct regulatory_request core_request_world = {
static struct regulatory_request __rcu *last_request =
(void __force __rcu *)&core_request_world;
-/* To trigger userspace events */
+/* To trigger userspace events and load firmware */
static struct platform_device *reg_pdev;
/*
@@ -442,7 +443,6 @@ reg_copy_regd(const struct ieee80211_regdomain *src_regd)
return regd;
}
-#ifdef CONFIG_CFG80211_INTERNAL_REGDB
struct reg_regdb_apply_request {
struct list_head list;
const struct ieee80211_regdomain *regdom;
@@ -474,41 +474,44 @@ static void reg_regdb_apply(struct work_struct *work)
static DECLARE_WORK(reg_regdb_work, reg_regdb_apply);
-static int reg_query_builtin(const char *alpha2)
+static int reg_schedule_apply(const struct ieee80211_regdomain *regdom)
{
- const struct ieee80211_regdomain *regdom = NULL;
struct reg_regdb_apply_request *request;
- unsigned int i;
-
- for (i = 0; i < reg_regdb_size; i++) {
- if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
- regdom = reg_regdb[i];
- break;
- }
- }
-
- if (!regdom)
- return -ENODATA;
request = kzalloc(sizeof(struct reg_regdb_apply_request), GFP_KERNEL);
- if (!request)
- return -ENOMEM;
-
- request->regdom = reg_copy_regd(regdom);
- if (IS_ERR_OR_NULL(request->regdom)) {
- kfree(request);
+ if (!request) {
+ kfree(regdom);
return -ENOMEM;
}
+ request->regdom = regdom;
+
mutex_lock(®_regdb_apply_mutex);
list_add_tail(&request->list, ®_regdb_apply_list);
mutex_unlock(®_regdb_apply_mutex);
schedule_work(®_regdb_work);
-
return 0;
}
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+static int reg_query_builtin(const char *alpha2)
+{
+ const struct ieee80211_regdomain *regdom = NULL;
+ unsigned int i;
+
+ for (i = 0; i < reg_regdb_size; i++) {
+ if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
+ regdom = reg_copy_regd(reg_regdb[i]);
+ break;
+ }
+ }
+ if (!regdom)
+ return -ENODATA;
+
+ return reg_schedule_apply(regdom);
+}
+
/* Feel free to add any other sanity checks here */
static void reg_regdb_size_check(void)
{
@@ -598,12 +601,227 @@ static inline int call_crda(const char *alpha2)
}
#endif /* CONFIG_CFG80211_CRDA_SUPPORT */
+/* code to directly load a firmware database through request_firmware */
+static const struct firmware *regdb;
+static unsigned int fwregdb_attempts = 10;
+
+struct fwdb_country {
+ u8 alpha2[2];
+ __be16 coll_ptr;
+} __packed __aligned(4);
+
+struct fwdb_collection {
+ __be16 len;
+ __be16 n_rules;
+ u8 dfs_region;
+ u8 pad_reserved;
+ __be16 rules_ptr[];
+} __packed __aligned(4);
+
+struct fwdb_rule {
+ __be16 len;
+ __be16 flags;
+ __be32 start, end, max_bw;
+ __be32 cac_timeout;
+ __be16 max_ant_gain;
+ __be16 max_eirp;
+} __packed __aligned(4);
+
+#define FWDB_MAGIC 0x52474442
+#define FWDB_VERSION 20
+
+struct fwdb_header {
+ __be32 magic;
+ __be32 version;
+ struct fwdb_country country[];
+} __packed __aligned(4);
+
+static bool valid_rule(const struct firmware *db, u16 rule_ptr)
+{
+ struct fwdb_rule *rule = (void *)(db->data + (rule_ptr << 2));
+
+ if ((u8 *)rule + sizeof(rule->len) > db->data + db->size)
+ return false;
+
+ /* mandatory fields */
+ if (be16_to_cpu(rule->len) < offsetofend(struct fwdb_rule, max_eirp))
+ return false;
+
+ return true;
+}
+
+static bool valid_country(const struct firmware *db,
+ const struct fwdb_country *country)
+{
+ unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
+ struct fwdb_collection *coll = (void *)(db->data + ptr);
+ unsigned int i;
+
+ if ((u8 *)coll + sizeof(coll->len) > db->data + db->size)
+ return false;
+
+ if ((u8 *)coll + be16_to_cpu(coll->len) > db->data + db->size)
+ return false;
+
+ /* mandatory fields */
+ if (be16_to_cpu(coll->len) < offsetof(struct fwdb_collection,
+ rules_ptr))
+ return false;
+
+ if (be16_to_cpu(coll->len) < offsetof(struct fwdb_collection,
+ rules_ptr) +
+ be16_to_cpu(coll->n_rules) *
+ sizeof(coll->rules_ptr[0]))
+ return false;
+
+ for (i = 0; i < be16_to_cpu(coll->n_rules); i++) {
+ u16 rule_ptr = be16_to_cpu(coll->rules_ptr[i]);
+
+ if (!valid_rule(db, rule_ptr))
+ return false;
+ }
+
+ return true;
+}
+
+static bool valid_regdb(const struct firmware *db)
+{
+ const struct fwdb_header *hdr = (void *)db->data;
+ const struct fwdb_country *country;
+
+ if (db->size < sizeof(*hdr))
+ return false;
+
+ if (hdr->magic != cpu_to_be32(FWDB_MAGIC))
+ return false;
+
+ if (hdr->version != cpu_to_be32(FWDB_VERSION))
+ return false;
+
+ country = &hdr->country[0];
+ while ((u8 *)(country + 1) <= db->data + db->size) {
+ if (!country->coll_ptr)
+ break;
+ if (!valid_country(db, country))
+ return false;
+ country++;
+ }
+
+ return true;
+}
+
+static int regdb_query_country(const struct firmware *db,
+ const struct fwdb_country *country)
+{
+ unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
+ struct fwdb_collection *coll = (void *)(db->data + ptr);
+ struct ieee80211_regdomain *regdom;
+ unsigned int size_of_regd;
+ unsigned int i;
+
+ size_of_regd =
+ sizeof(struct ieee80211_regdomain) +
+ be16_to_cpu(coll->n_rules) * sizeof(struct ieee80211_reg_rule);
+
+ regdom = kzalloc(size_of_regd, GFP_KERNEL);
+ if (!regdom)
+ return -ENOMEM;
+
+ regdom->n_reg_rules = be16_to_cpu(coll->n_rules);
+ regdom->alpha2[0] = country->alpha2[0];
+ regdom->alpha2[1] = country->alpha2[1];
+ regdom->dfs_region = coll->dfs_region;
+
+ for (i = 0; i < regdom->n_reg_rules; i++) {
+ unsigned int rule_ptr = be16_to_cpu(coll->rules_ptr[i]) << 2;
+ struct fwdb_rule *rule = (void *)(db->data + rule_ptr);
+ struct ieee80211_reg_rule *rrule = ®dom->reg_rules[i];
+
+ rrule->freq_range.start_freq_khz = be32_to_cpu(rule->start);
+ rrule->freq_range.end_freq_khz = be32_to_cpu(rule->end);
+ rrule->freq_range.max_bandwidth_khz = be32_to_cpu(rule->max_bw);
+
+ rrule->power_rule.max_antenna_gain =
+ be16_to_cpu(rule->max_ant_gain);
+ rrule->power_rule.max_eirp = be16_to_cpu(rule->max_eirp);
+
+ rrule->flags = be16_to_cpu(rule->flags);
+ rrule->dfs_cac_ms = be32_to_cpu(rule->cac_timeout);
+ }
+
+ return reg_schedule_apply(regdom);
+}
+
+static int query_regdb(const char *alpha2)
+{
+ const struct fwdb_header *hdr;
+ const struct fwdb_country *country;
+
+ if (IS_ERR(regdb))
+ return PTR_ERR(regdb);
+
+ hdr = (void *)regdb->data;
+ country = &hdr->country[0];
+ while (country->coll_ptr) {
+ if (alpha2_equal(alpha2, country->alpha2))
+ return regdb_query_country(regdb, country);
+ country++;
+ }
+
+ return -ENODATA;
+}
+
+static void regdb_fw_cb(const struct firmware *fw, void *context)
+{
+ if (!fw) {
+ pr_info("failed to load regulatory.db\n");
+ if (fwregdb_attempts-- == 0)
+ regdb = ERR_PTR(-ENODATA);
+ goto restore;
+ }
+
+ if (!valid_regdb(fw)) {
+ pr_info("loaded regulatory.db is malformed\n");
+ release_firmware(fw);
+ regdb = ERR_PTR(-EINVAL);
+ goto restore;
+ }
+
+ regdb = fw;
+ if (query_regdb(context))
+ goto restore;
+ goto free;
+ restore:
+ rtnl_lock();
+ restore_regulatory_settings(true);
+ rtnl_unlock();
+ free:
+ kfree(context);
+}
+
+static int query_regdb_file(const char *alpha2)
+{
+ if (regdb)
+ return query_regdb(alpha2);
+
+ alpha2 = kmemdup(alpha2, 2, GFP_KERNEL);
+ if (!alpha2)
+ return -ENOMEM;
+
+ return request_firmware_nowait(THIS_MODULE, true, "regulatory.db",
+ ®_pdev->dev, GFP_KERNEL,
+ (void *)alpha2, regdb_fw_cb);
+}
+
static bool reg_query_database(struct regulatory_request *request)
{
/* query internal regulatory database (if it exists) */
if (reg_query_builtin(request->alpha2) == 0)
return true;
+ if (query_regdb_file(request->alpha2) == 0)
+ return true;
+
if (call_crda(request->alpha2) == 0)
return true;
@@ -3344,4 +3562,7 @@ void regulatory_exit(void)
list_del(®_request->list);
kfree(reg_request);
}
+
+ if (!IS_ERR_OR_NULL(regdb))
+ release_firmware(regdb);
}
--
2.14.1
^ permalink raw reply related
* [RFC 2/4] cfg80211: support reloading regulatory database
From: Johannes Berg @ 2017-09-15 10:18 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20170915101810.11435-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
If the regulatory database is loaded, and then updated, it may
be necessary to reload it. Add an nl80211 command to do this,
and RCU-ify the pointer to the regdb "firmware" to allow it to
be replaced at runtime.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/uapi/linux/nl80211.h | 4 +++
net/wireless/nl80211.c | 11 ++++++
net/wireless/reg.c | 84 ++++++++++++++++++++++++++++++++++++--------
net/wireless/reg.h | 6 ++++
4 files changed, 90 insertions(+), 15 deletions(-)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 51626b4175c0..926eb92cb4a8 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -983,6 +983,8 @@
* configured PMK for the authenticator address identified by
* &NL80211_ATTR_MAC.
*
+ * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1185,6 +1187,8 @@ enum nl80211_commands {
NL80211_CMD_SET_PMK,
NL80211_CMD_DEL_PMK,
+ NL80211_CMD_RELOAD_REGDB,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8ce85420ecb0..ee902ea13833 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5669,6 +5669,11 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
}
}
+static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
+{
+ return reg_reload_regdb();
+}
+
static int nl80211_get_mesh_config(struct sk_buff *skb,
struct genl_info *info)
{
@@ -12668,6 +12673,12 @@ static const struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
},
+ {
+ .cmd = NL80211_CMD_RELOAD_REGDB,
+ .doit = nl80211_reload_regdb,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
{
.cmd = NL80211_CMD_GET_MESH_CONFIG,
.doit = nl80211_get_mesh_config,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7a1d6cda64f3..8d366738c08a 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -602,7 +602,7 @@ static inline int call_crda(const char *alpha2)
#endif /* CONFIG_CFG80211_CRDA_SUPPORT */
/* code to directly load a firmware database through request_firmware */
-static const struct firmware *regdb;
+static const struct firmware __rcu *regdb;
static unsigned int fwregdb_attempts = 10;
struct fwdb_country {
@@ -756,47 +756,76 @@ static int query_regdb(const char *alpha2)
{
const struct fwdb_header *hdr;
const struct fwdb_country *country;
+ const struct firmware *db;
+ int err;
- if (IS_ERR(regdb))
- return PTR_ERR(regdb);
+ rcu_read_lock();
+ db = rcu_dereference(regdb);
- hdr = (void *)regdb->data;
+ if (IS_ERR(db)) {
+ err = PTR_ERR(db);
+ goto out;
+ }
+
+ hdr = (void *)db->data;
country = &hdr->country[0];
while (country->coll_ptr) {
- if (alpha2_equal(alpha2, country->alpha2))
- return regdb_query_country(regdb, country);
+ if (alpha2_equal(alpha2, country->alpha2)) {
+ err = regdb_query_country(db, country);
+ goto out;
+ }
country++;
}
- return -ENODATA;
+ err = -ENODATA;
+ out:
+ rcu_read_unlock();
+ return err;
}
static void regdb_fw_cb(const struct firmware *fw, void *context)
{
+ const struct firmware *db;
+
+ rtnl_lock();
+
+ db = rcu_dereference_protected(regdb, lockdep_rtnl_is_held());
+
+ if (WARN_ON(db)) {
+ release_firmware(fw);
+ goto out;
+ }
+
if (!fw) {
pr_info("failed to load regulatory.db\n");
if (fwregdb_attempts-- == 0)
- regdb = ERR_PTR(-ENODATA);
+ rcu_assign_pointer(regdb, ERR_PTR(-ENODATA));
goto restore;
}
if (!valid_regdb(fw)) {
pr_info("loaded regulatory.db is malformed\n");
release_firmware(fw);
- regdb = ERR_PTR(-EINVAL);
+ rcu_assign_pointer(regdb, ERR_PTR(-EINVAL));
goto restore;
}
- regdb = fw;
- if (query_regdb(context))
+ rcu_assign_pointer(regdb, fw);
+
+ if (context && query_regdb(context))
goto restore;
- goto free;
+ goto out;
+
restore:
- rtnl_lock();
restore_regulatory_settings(true);
+ out:
rtnl_unlock();
- free:
kfree(context);
+
+ if (!IS_ERR_OR_NULL(db)) {
+ synchronize_rcu();
+ release_firmware(db);
+ }
}
static int query_regdb_file(const char *alpha2)
@@ -813,6 +842,31 @@ static int query_regdb_file(const char *alpha2)
(void *)alpha2, regdb_fw_cb);
}
+int reg_reload_regdb(void)
+{
+ const struct firmware *db, *old;
+ int err;
+
+ err = request_firmware(&db, "regulatory.db", ®_pdev->dev);
+ if (err)
+ return err;
+
+ if (!valid_regdb(db))
+ return -ENODATA;
+
+ rtnl_lock();
+ old = rcu_dereference_protected(regdb, lockdep_rtnl_is_held());
+ rcu_assign_pointer(regdb, db);
+ rtnl_unlock();
+
+ if (!IS_ERR_OR_NULL(old)) {
+ synchronize_rcu();
+ release_firmware(old);
+ }
+
+ return 0;
+}
+
static bool reg_query_database(struct regulatory_request *request)
{
/* query internal regulatory database (if it exists) */
@@ -3564,5 +3618,5 @@ void regulatory_exit(void)
}
if (!IS_ERR_OR_NULL(regdb))
- release_firmware(regdb);
+ release_firmware(rcu_access_pointer(regdb));
}
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index ca7fedf2e7a1..9529c522611a 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -179,4 +179,10 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy,
* @wiphy2 - wiphy it's dfs_region to be checked against that of wiphy1
*/
bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2);
+
+/**
+ * reg_reload_regdb - reload the regulatory.db firmware file
+ */
+int reg_reload_regdb(void);
+
#endif /* __NET_WIRELESS_REG_H */
--
2.14.1
^ permalink raw reply related
* [RFC 4/4] cfg80211: implement regdb signature checking
From: Johannes Berg @ 2017-09-15 10:18 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20170915101810.11435-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
Currently CRDA implements the signature checking, and the previous
commits added the ability to load the whole regulatory database
into the kernel.
However, we really can't lose the signature checking, so implement
it in the kernel by loading a detached signature (regulatory.db.p7s)
and check it against built-in keys.
TODO
- add a Kconfig option to specify extra keys, rather than requiring
them to be dropped into the right directory
- should anything be able to modify the keyring? I guess not?
- add Seth's key, obviously
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/wireless/Kconfig | 10 ++++
net/wireless/Makefile | 10 ++++
net/wireless/certs/none.x509 | 0
net/wireless/reg.c | 109 +++++++++++++++++++++++++++++++++++++++++++
net/wireless/reg.h | 6 +++
5 files changed, 135 insertions(+)
create mode 100644 net/wireless/certs/none.x509
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index f050030055c5..8ac8fda93cfe 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -83,6 +83,16 @@ config CFG80211_CERTIFICATION_ONUS
you are a wireless researcher and are working in a controlled
and approved environment by your local regulatory agency.
+config CFG80211_REQUIRE_SIGNED_REGDB
+ bool "require regdb signature" if CFG80211_CERTIFICATION_ONUS
+ default y
+ select SYSTEM_DATA_VERIFICATION
+ help
+ Require that in addition to the "regulatory.db" file a
+ "regulatory.db.p7s" can be loaded with a valid PKCS#7
+ signature for the regulatory.db file made by one of the
+ keys in the certs/ directory.
+
config CFG80211_REG_CELLULAR_HINTS
bool "cfg80211 regulatory support for cellular base station hints"
depends on CFG80211_CERTIFICATION_ONUS
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 5f20dac5d8c6..20994876d42a 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -16,3 +16,13 @@ cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
CFLAGS_trace.o := -I$(src)
+
+cfg80211-$(CONFIG_CFG80211_REQUIRE_SIGNED_REGDB) += certs.o
+
+$(obj)/certs.c: $(wildcard $(srctree)/$(src)/certs/*.x509)
+ @echo " GEN $@"
+ @echo '#include "reg.h"' > $@
+ @echo 'const u8 regdb_certs[] = {' >> $@
+ @hexdump -v -e '1/1 "0x%.2x," "\n"' < $< >> $@
+ @echo '};' >> $@
+ @echo 'unsigned int regdb_certs_len = sizeof(regdb_certs);' >> $@
diff --git a/net/wireless/certs/none.x509 b/net/wireless/certs/none.x509
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 5dd453bdad3a..2a04118c500a 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -52,6 +52,7 @@
#include <linux/ctype.h>
#include <linux/nl80211.h>
#include <linux/platform_device.h>
+#include <linux/verification.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <net/cfg80211.h>
@@ -652,6 +653,105 @@ static bool valid_country(const struct firmware *db,
return true;
}
+#ifdef CONFIG_CFG80211_REQUIRE_SIGNED_REGDB
+static struct key *builtin_regdb_keys;
+
+static int load_builtin_regdb_keys(void)
+{
+ key_ref_t key;
+ const u8 *p, *end;
+ size_t plen;
+
+ builtin_regdb_keys =
+ keyring_alloc(".builtin_regdb_keys",
+ KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+ KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
+ KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
+ if (IS_ERR(builtin_regdb_keys))
+ return PTR_ERR(builtin_regdb_keys);
+
+ pr_notice("Loading compiled-in X.509 certificates\n");
+
+ p = regdb_certs;
+ end = p + regdb_certs_len;
+ while (p < end) {
+ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
+ * than 256 bytes in size.
+ */
+ if (end - p < 4)
+ goto dodgy_cert;
+ if (p[0] != 0x30 &&
+ p[1] != 0x82)
+ goto dodgy_cert;
+ plen = (p[2] << 8) | p[3];
+ plen += 4;
+ if (plen > end - p)
+ goto dodgy_cert;
+
+ key = key_create_or_update(make_key_ref(builtin_regdb_keys, 1),
+ "asymmetric",
+ NULL,
+ p,
+ plen,
+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+ KEY_USR_VIEW | KEY_USR_READ),
+ KEY_ALLOC_NOT_IN_QUOTA |
+ KEY_ALLOC_BUILT_IN |
+ KEY_ALLOC_BYPASS_RESTRICTION);
+ if (IS_ERR(key)) {
+ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
+ PTR_ERR(key));
+ } else {
+ pr_notice("Loaded X.509 cert '%s'\n",
+ key_ref_to_ptr(key)->description);
+ key_ref_put(key);
+ }
+ p += plen;
+ }
+
+ return 0;
+
+dodgy_cert:
+ pr_err("Problem parsing in-kernel X.509 certificate list\n");
+ return 0;
+}
+
+static bool regdb_has_valid_signature(const struct firmware *db)
+{
+ const struct firmware *sig;
+
+ if (request_firmware(&sig, "regulatory.db.p7s", ®_pdev->dev))
+ return false;
+
+ if (verify_pkcs7_signature(db->data, db->size, sig->data, sig->size,
+ builtin_regdb_keys,
+ VERIFYING_UNSPECIFIED_SIGNATURE, NULL, NULL))
+ return false;
+
+ return true;
+}
+
+static void free_regdb_keyring(void)
+{
+ key_put(builtin_regdb_keys);
+}
+#else
+static int load_builtin_regdb_keys(void)
+{
+ return 0;
+}
+
+static bool regdb_has_valid_signature(const struct firmware *db)
+{
+ return true;
+}
+
+static void free_regdb_keyring(void)
+{
+}
+#endif /* CONFIG_CFG80211_REQUIRE_SIGNED_REGDB */
+
static bool valid_regdb(const struct firmware *db)
{
const struct fwdb_header *hdr = (void *)db->data;
@@ -666,6 +766,9 @@ static bool valid_regdb(const struct firmware *db)
if (hdr->version != cpu_to_be32(FWDB_VERSION))
return false;
+ if (!regdb_has_valid_signature(db))
+ return false;
+
country = &hdr->country[0];
while ((u8 *)(country + 1) <= db->data + db->size) {
if (!country->coll_ptr)
@@ -3505,6 +3608,10 @@ int __init regulatory_init(void)
{
int err = 0;
+ err = load_builtin_regdb_keys();
+ if (err)
+ return err;
+
reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
if (IS_ERR(reg_pdev))
return PTR_ERR(reg_pdev);
@@ -3581,4 +3688,6 @@ void regulatory_exit(void)
if (!IS_ERR_OR_NULL(regdb))
release_firmware(rcu_access_pointer(regdb));
+
+ free_regdb_keyring();
}
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 9529c522611a..a520a8261d1a 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -1,5 +1,8 @@
#ifndef __NET_WIRELESS_REG_H
#define __NET_WIRELESS_REG_H
+
+#include <net/cfg80211.h>
+
/*
* Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
*
@@ -185,4 +188,7 @@ bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2);
*/
int reg_reload_regdb(void);
+extern const u8 regdb_certs[];
+extern unsigned int regdb_certs_len;
+
#endif /* __NET_WIRELESS_REG_H */
--
2.14.1
^ permalink raw reply related
* Re: [RFC 4/4] cfg80211: implement regdb signature checking
From: Johannes Berg @ 2017-09-15 10:20 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <20170915101810.11435-5-johannes@sipsolutions.net>
On Fri, 2017-09-15 at 12:18 +0200, Johannes Berg wrote:
>
> +config CFG80211_REQUIRE_SIGNED_REGDB
> + bool "require regdb signature" if
> CFG80211_CERTIFICATION_ONUS
> + default y
> + select SYSTEM_DATA_VERIFICATION
Note that this will not be easy to backport, however, the code only
needs relatively self-contained functionality, namely this:
> + builtin_regdb_keys =
> + keyring_alloc(".builtin_regdb_keys",
> + KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
> + ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
> + KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
> + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
> + key = key_create_or_update(make_key_ref(builtin_regdb_keys, 1),
> + "asymmetric",
> + NULL,
> + p,
> + plen,
> + ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
> + KEY_USR_VIEW | KEY_USR_READ),
> + KEY_ALLOC_NOT_IN_QUOTA |
> + KEY_ALLOC_BUILT_IN |
> + KEY_ALLOC_BYPASS_RESTRICTION);
> + if (verify_pkcs7_signature(db->data, db->size, sig->data, sig->size,
> + builtin_regdb_keys,
> + VERIFYING_UNSPECIFIED_SIGNATURE, NULL, NULL))
so I'm hoping it won't be too difficult, since we don't really need the
ability to manipulate keyrings etc.
johannes
^ permalink raw reply
* Re: What makes USB WiFi so difficult in Linux and may I help out?
From: Oleksij Rempel @ 2017-09-15 10:28 UTC (permalink / raw)
To: Ernst Wegner, linux-wireless
In-Reply-To: <CAF11ideB1ButOi1r8dmkbQZzSjmVrO247+pMOuxy60pO+BkuiA@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 2261 bytes --]
Hi,
it is not related to your HW, but may help:
https://github.com/qca/open-ath9k-htc-firmware/wiki/Troubleshooting-and-bug-reporting
https://github.com/qca/open-ath9k-htc-firmware/wiki/usb-related-issues
Am 15.09.2017 um 10:48 schrieb Ernst Wegner:
> Dear list!
>
> I recently suffer from attempts to use some USB WiFi sticks to connect
> to a wireless network using Linux. I tried that with a number of
> distros, but found that there seem to be kind of the same problems all
> the way from Linux 2.6.x to 4.x. Most USB WiFi sticks don't work
> reliably.
>
> As I am a developer also (and very interested in these things) I would
> be willing to help debugging drivers and possibly fix them. But I
> don't really know where to start searching. So some hints would be
> very welcome.
>
> Currently I try to get this one here to work:
>
> Bus 001 Device 006: ID 148f:5370 Ralink Technology, Corp. RT5370
> Wireless Adapter
>
> I am on Debian 9 with a pretty recent kernel:
>
> Linux debian 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u3 (2017-08-06)
> x86_64 GNU/Linux
>
> I was able to get this stick to work kind of. Actually, it drops the
> connection every couple of minutes, without any error messages in
> dmesg or syslog, actually. But I was able to reach that state only
> after applying some tweaks like disabling hardware encrypt, i.e.
>
> options rt2800usb nohwcrypt=y
>
> and
>
> [device]
> wifi.scan-rand-mac-address=no
>
> So any pointers would be welcome.
>
> I am not afraid to dig into the code of the driver and recompile.
>
> I could also possibly add or enable some debugging code so I will get
> some more debugging output to see what actually happens when I loose
> the connection, i.e. if this is an external event, a special kind of
> package, overload, ...
>
> And finally: This isn't the only USB Wifi stick which has serious
> problems with Linux. The Internet is full of this including drivers
> for some sticks which don't work at all and don't go anywhere for
> month. Obviously it's not the sticks to blame, as they all work fine
> on Windows. So what's the underlying story here which I am missing?
>
> Regards,
> Torsten
>
--
Regards,
Oleksij
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply
* [TDLS PATCH V1 0/5] Add TDLS feature for ath10k
From: yintang @ 2017-09-15 11:03 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless
In-Reply-To: <TDLS for ath10k>
From: Yingying Tang <yintang@qti.qualcomm.com>
This patchset is for Rome PCIE chip, it will not affect other hardware
Yingying Tang (5):
mac80211: Enable TDLS peer buffer STA feature
ath10k: Enable TDLS peer buffer STA feature
ath10k: Enable TDLS peer inactivity detection
ath10k: Avoid to set WEP key for TDLS peer
ath10k: Avoid to set WEP key for TDLS peer
drivers/net/wireless/ath/ath10k/mac.c | 9 ++++-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 55 +++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/wmi-tlv.h | 23 ++++++++++++
drivers/net/wireless/ath/ath10k/wmi.h | 1 +
include/net/cfg80211.h | 3 ++
net/mac80211/tdls.c | 5 ++-
6 files changed, 94 insertions(+), 2 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [TDLS PATCH V1 1/5] mac80211: Enable TDLS peer buffer STA feature
From: yintang @ 2017-09-15 11:03 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless
In-Reply-To: <1505473420-22932-1-git-send-email-yintang@qti.qualcomm.com>
From: Yingying Tang <yintang@qti.qualcomm.com>
Enable TDLS peer buffer STA feature.
Set extended capability bit to enable buffer STA when driver
support it.
Signed-off-by: Yingying Tang <yintang@qti.qualcomm.com>
---
include/net/cfg80211.h | 3 +++
net/mac80211/tdls.c | 5 ++++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f12fa52..edefc25 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3249,6 +3249,8 @@ struct cfg80211_ops {
* beaconing mode (AP, IBSS, Mesh, ...).
* @WIPHY_FLAG_HAS_STATIC_WEP: The device supports static WEP key installation
* before connection.
+ * @WIPHY_FLAG_SUPPORT_TDLS_BUFFER_ST: Device support buffer STA when TDLS is
+ * established.
*/
enum wiphy_flags {
/* use hole at 0 */
@@ -3275,6 +3277,7 @@ enum wiphy_flags {
WIPHY_FLAG_SUPPORTS_5_10_MHZ = BIT(22),
WIPHY_FLAG_HAS_CHANNEL_SWITCH = BIT(23),
WIPHY_FLAG_HAS_STATIC_WEP = BIT(24),
+ WIPHY_FLAG_SUPPORT_TDLS_BUFFER_STA = BIT(25),
};
/**
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 91093d4..f99e379 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -49,6 +49,8 @@ static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata,
!ifmgd->tdls_wider_bw_prohibited;
struct ieee80211_supported_band *sband = ieee80211_get_sband(sdata);
bool vht = sband && sband->vht_cap.vht_supported;
+ bool buffer_sta =
+ local->hw.wiphy->flags & WIPHY_FLAG_SUPPORT_TDLS_BUFFER_STA;
u8 *pos = skb_put(skb, 10);
*pos++ = WLAN_EID_EXT_CAPABILITY;
@@ -56,7 +58,8 @@ static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata,
*pos++ = 0x0;
*pos++ = 0x0;
*pos++ = 0x0;
- *pos++ = chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0;
+ *pos++ = (chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0) |
+ (buffer_sta ? WLAN_EXT_CAPA4_TDLS_BUFFER_STA : 0);
*pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
*pos++ = 0;
*pos++ = 0;
--
1.7.9.5
^ permalink raw reply related
* [TDLS PATCH V1 2/5] ath10k: Enable TDLS peer buffer STA feature
From: yintang @ 2017-09-15 11:03 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless
In-Reply-To: <1505473420-22932-1-git-send-email-yintang@qti.qualcomm.com>
From: Yingying Tang <yintang@qti.qualcomm.com>
Enable TDLS peer buffer STA feature.
QCA6174 firmware(version: WLAN.RM.4.4) support TDLS peer buffer STA,
it reports this capability through wmi service map in wmi service ready
event. Set related parameter in TDLS WMI command to enable this feature.
Signed-off-by: Yingying Tang <yintang@qti.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/mac.c | 3 +++
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 5683f1a..399f9ba 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -8204,6 +8204,9 @@ int ath10k_mac_register(struct ath10k *ar)
ieee80211_hw_set(ar->hw, TDLS_WIDER_BW);
}
+ if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
+ ar->hw->wiphy->flags |= WIPHY_FLAG_SUPPORT_TDLS_BUFFER_STA;
+
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
ar->hw->wiphy->max_remain_on_channel_duration = 5000;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 7616c1c..f60b46e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -2747,6 +2747,9 @@ static void *ath10k_wmi_tlv_put_wmm(void *ptr,
*/
u32 options = 0;
+ if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
+ options |= WMI_TLV_TDLS_BUFFER_STA_EN;
+
len = sizeof(*tlv) + sizeof(*cmd);
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
--
1.7.9.5
^ permalink raw reply related
* [TDLS PATCH V1 3/5] ath10k: Enable TDLS peer inactivity detection
From: yintang @ 2017-09-15 11:03 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless
In-Reply-To: <1505473420-22932-1-git-send-email-yintang@qti.qualcomm.com>
From: Yingying Tang <yintang@qti.qualcomm.com>
Enable TDLS peer inactivity detetion feature.
QCA6174 firmware(version: WLAN.RM.4.4) support TDLS link inactivity detecting.
Set related parameters in TDLS WMI command to enable this feature.
Signed-off-by: Yingying Tang <yintang@qti.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 52 +++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/wmi-tlv.h | 23 +++++++++++++
drivers/net/wireless/ath/ath10k/wmi.h | 1 +
3 files changed, 76 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index f60b46e..63bb2c4 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -412,6 +412,49 @@ static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
return 0;
}
+void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
+{
+ struct ieee80211_sta *station;
+ const struct wmi_tlv_tdls_peer_event *ev;
+ const void **tb;
+ struct ath10k_vif *arvif;
+
+ tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
+ if (IS_ERR(tb)) {
+ ath10k_warn(ar, "tdls peer failed to parse tlv");
+ return;
+ }
+ ev = tb[WMI_TLV_TAG_STRUCT_TDLS_PEER_EVENT];
+ if (!ev) {
+ kfree(tb);
+ ath10k_warn(ar, "tdls peer NULL event");
+ return;
+ }
+
+ switch (ev->peer_reason) {
+ case WMI_TDLS_TEARDOWN_REASON_TX:
+ case WMI_TDLS_TEARDOWN_REASON_RSSI:
+ case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
+ station = ieee80211_find_sta_by_ifaddr(ar->hw,
+ ev->peer_macaddr.addr,
+ NULL);
+ if (!station) {
+ ath10k_warn(ar, "did not find station from tdls peer event");
+ kfree(tb);
+ return;
+ }
+ arvif = ath10k_get_arvif(ar, ev->vdev_id);
+ ieee80211_tdls_oper_request(
+ arvif->vif, station->addr,
+ NL80211_TDLS_TEARDOWN,
+ WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
+ GFP_ATOMIC
+ );
+ break;
+ }
+ kfree(tb);
+}
+
/***********/
/* TLV ops */
/***********/
@@ -552,6 +595,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_TLV_TX_PAUSE_EVENTID:
ath10k_wmi_tlv_event_tx_pause(ar, skb);
break;
+ case WMI_TLV_TDLS_PEER_EVENTID:
+ ath10k_wmi_event_tdls_peer(ar, skb);
+ break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
break;
@@ -2750,6 +2796,12 @@ static void *ath10k_wmi_tlv_put_wmm(void *ptr,
if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
options |= WMI_TLV_TDLS_BUFFER_STA_EN;
+ /* WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL means firm will handle TDLS
+ * link inactivity detecting logic.
+ */
+ if (state == WMI_TDLS_ENABLE_ACTIVE)
+ state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
+
len = sizeof(*tlv) + sizeof(*cmd);
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index 22cf011..00d68c5 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -1641,6 +1641,29 @@ struct wmi_tlv_tx_pause_ev {
__le32 tid_map;
} __packed;
+struct wmi_tlv_tdls_peer_event {
+ struct wmi_mac_addr peer_macaddr;
+ __le32 peer_status;
+ __le32 peer_reason;
+ __le32 vdev_id;
+} __packed;
+
+enum wmi_tdls_peer_reason {
+ WMI_TDLS_TEARDOWN_REASON_TX,
+ WMI_TDLS_TEARDOWN_REASON_RSSI,
+ WMI_TDLS_TEARDOWN_REASON_SCAN,
+ WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE,
+ WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT,
+ WMI_TDLS_TEARDOWN_REASON_BAD_PTR,
+ WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE,
+ WMI_TDLS_ENTER_BUF_STA,
+ WMI_TDLS_EXIT_BUF_STA,
+ WMI_TDLS_ENTER_BT_BUSY_MODE,
+ WMI_TDLS_EXIT_BT_BUSY_MODE,
+ WMI_TDLS_SCAN_STARTED_EVENT,
+ WMI_TDLS_SCAN_COMPLETED_EVENT,
+};
+
void ath10k_wmi_tlv_attach(struct ath10k *ar);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 7a3606d..74a6c78 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6720,6 +6720,7 @@ enum wmi_tdls_state {
WMI_TDLS_DISABLE,
WMI_TDLS_ENABLE_PASSIVE,
WMI_TDLS_ENABLE_ACTIVE,
+ WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL,
};
enum wmi_tdls_peer_state {
--
1.7.9.5
^ permalink raw reply related
* [TDLS PATCH V1 4/5] ath10k: Avoid to set WEP key for TDLS peer
From: yintang @ 2017-09-15 11:03 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless
In-Reply-To: <1505473420-22932-1-git-send-email-yintang@qti.qualcomm.com>
From: Yingying Tang <yintang@qti.qualcomm.com>
TDLS peer do not need WEP key. Setting WEP key will lead
to TDLS setup failure. Add fix to avoid setting WEP key
for TDLS peer.
Signed-off-by: Yingying Tang <yintang@qti.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/mac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 399f9ba..f6702cb 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2966,7 +2966,7 @@ static int ath10k_station_assoc(struct ath10k *ar,
}
/* Plumb cached keys only for static WEP */
- if (arvif->def_wep_key_idx != -1) {
+ if ((arvif->def_wep_key_idx != -1) && (!sta->tdls)) {
ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
if (ret) {
ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n",
--
1.7.9.5
^ permalink raw reply related
* [TDLS PATCH V1 5/5] ath10k: Avoid to set WEP key for TDLS peer
From: yintang @ 2017-09-15 11:05 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless
In-Reply-To: <TDLS for ath10k>
From: Yingying Tang <yintang@qti.qualcomm.com>
TDLS peer do not need WEP key. Setting WEP key will lead
to TDLS setup failure. Add fix to avoid setting WEP key
for TDLS peer.
Signed-off-by: Yingying Tang <yintang@qti.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/mac.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index f6702cb..d2530f7 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -5841,6 +5841,10 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ath10k_warn(ar, "Peer %pM disappeared!\n", peer_addr);
spin_unlock_bh(&ar->data_lock);
+ if (sta && sta->tdls)
+ ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
+ WMI_PEER_AUTHORIZE, 1);
+
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
--
1.7.9.5
^ permalink raw reply related
* pull-request: iwlwifi 2017-09-15
From: Luca Coelho @ 2017-09-15 11:47 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, linuxwifi
[-- Attachment #1: Type: text/plain, Size: 2891 bytes --]
Hi Kalle,
Here is the first set of fixes for 4.14. More details in the tag
description.
I have sent this out before and kbuildbot didn't find any issues.
Please let me know if there are any issues.
Cheers,
Luca.
The following changes since commit 2eabc84d2f8e4f36d3719eeb6a330e10c46c8da7:
iwlwifi: mvm: only send LEDS_CMD when the FW supports it (2017-09-07 19:40:09 +0300)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes.git tags/iwlwifi-for-kalle-2017-09-15
for you to fetch changes up to 5f90472c00ddf1e64c2865f71cced297bd5f80a2:
iwlwifi: mvm: fix reorder buffer for 9000 devices (2017-09-08 11:52:51 +0300)
----------------------------------------------------------------
First set of fixes for 4.14
* A couple of bugzilla bugs related to multicast handling;
* Two fixes for WoWLAN bugs that were causing queue hangs and
re-initialization problems;
* Two fixes for potential uninitialized variable use reported by Dan
Carpenter in relation to a recently introduced patch;
* A fix for buffer reordering in the newly supported 9000 device
family;
* Fix a race when starting aggregation;
* Small fix for a recent patch to wake mac80211 queues;
* Send non-bufferable management frames in the generic queue so they
are not sent on queues that are under power-save;
----------------------------------------------------------------
Avraham Stern (2):
iwlwifi: mvm: send all non-bufferable frames on the probe queue
iwlwifi: mvm: wake the correct mac80211 queue
David Spinadel (1):
iwlwifi: mvm: Flush non STA TX queues
Luca Coelho (4):
iwlwifi: mvm: use IWL_HCMD_NOCOPY for MCAST_FILTER_CMD
iwlwifi: mvm: handle FIF_ALLMULTI when setting multicast addresses
iwlwifi: mvm: initialize status in iwl_mvm_add_int_sta_common()
iwlwifi: mvm: set status before calling iwl_mvm_send_cmd_status()
Matt Chen (1):
iwlwifi: mvm: fix wowlan resume failed to load INIT ucode
Naftali Goldstein (1):
iwlwifi: mvm: change state when queueing agg start work
Sara Sharon (1):
iwlwifi: mvm: fix reorder buffer for 9000 devices
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 3 ++-
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 7 ++++---
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 8 +++++---
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 2 ++
drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 10 +++++-----
9 files changed, 80 insertions(+), 17 deletions(-)
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH 0/2] qtnfmac: misc fixes intended for 4.14
From: Sergey Matyukevich @ 2017-09-15 11:52 UTC (permalink / raw)
To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil
Hello Kalle, Igor, and all
Here are two patches intended for 4.14. The first patch fixes tx path
regression. Lock should be held when queuing packets to h/w fifos in order to
properly handle configurations with two enabled interfaces or multiple enabled
mbss. The second patch fixes scan issues addressing a review comment
from K.Valo regarding pending active scans upon device removal.
Regards,
Sergey
Sergey Matyukevich (2):
qtnfmac: lock access to h/w in tx path
qtnfmac: abort scans on wireless interface changes
cfg80211.c | 9 ++++++---
cfg80211.h | 3 +++
core.c | 2 +-
event.c | 2 --
pearl/pcie.c | 9 ++++++++-
pearl/pcie_bus_priv.h | 2 ++
6 files changed, 20 insertions(+), 7 deletions(-)
^ permalink raw reply
* [PATCH 1/2] qtnfmac: lock access to h/w in tx path
From: Sergey Matyukevich @ 2017-09-15 11:52 UTC (permalink / raw)
To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Sergey Matyukevich
In-Reply-To: <20170915115300.12719-1-sergey.matyukevich.os@quantenna.com>
Fix tx path regression. Lock should be held when queuing packets
to h/w fifos in order to properly handle configurations with
multiple enabled interfaces.
Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
---
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c | 9 ++++++++-
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h | 2 ++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
index 502e72b7cdcc..69131965a298 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
@@ -661,14 +661,18 @@ static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
dma_addr_t txbd_paddr, skb_paddr;
struct qtnf_tx_bd *txbd;
+ unsigned long flags;
int len, i;
u32 info;
int ret = 0;
+ spin_lock_irqsave(&priv->tx0_lock, flags);
+
if (!qtnf_tx_queue_ready(priv)) {
if (skb->dev)
netif_stop_queue(skb->dev);
+ spin_unlock_irqrestore(&priv->tx0_lock, flags);
return NETDEV_TX_BUSY;
}
@@ -717,8 +721,10 @@ static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
dev_kfree_skb_any(skb);
}
- qtnf_pcie_data_tx_reclaim(priv);
priv->tx_done_count++;
+ spin_unlock_irqrestore(&priv->tx0_lock, flags);
+
+ qtnf_pcie_data_tx_reclaim(priv);
return NETDEV_TX_OK;
}
@@ -1247,6 +1253,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
strcpy(bus->fwname, QTN_PCI_PEARL_FW_NAME);
init_completion(&bus->request_firmware_complete);
mutex_init(&bus->bus_lock);
+ spin_lock_init(&pcie_priv->tx0_lock);
spin_lock_init(&pcie_priv->irq_lock);
spin_lock_init(&pcie_priv->tx_reclaim_lock);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h
index e76a23716ee0..86ac1ccedb52 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h
@@ -34,6 +34,8 @@ struct qtnf_pcie_bus_priv {
/* lock for tx reclaim operations */
spinlock_t tx_reclaim_lock;
+ /* lock for tx0 operations */
+ spinlock_t tx0_lock;
u8 msi_enabled;
int mps;
--
2.11.0
^ permalink raw reply related
* [PATCH 2/2] qtnfmac: abort scans on wireless interface changes
From: Sergey Matyukevich @ 2017-09-15 11:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Igor Mitsyanko, Avinash Patil, Sergey Matyukevich
In-Reply-To: <20170915115300.12719-1-sergey.matyukevich.os@quantenna.com>
Abort active scans when wireless interface configuration is changed.
The usecases include wireless interface mode change, interface down,
AP stop, virtual interface removal.
Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 9 ++++++---
drivers/net/wireless/quantenna/qtnfmac/cfg80211.h | 3 +++
drivers/net/wireless/quantenna/qtnfmac/core.c | 2 +-
drivers/net/wireless/quantenna/qtnfmac/event.c | 2 --
4 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 856fa6e8327e..a450bc6bc774 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -115,6 +115,8 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
vif = qtnf_netdev_get_priv(wdev->netdev);
+ qtnf_scan_done(vif->mac, true);
+
if (qtnf_cmd_send_del_intf(vif))
pr_err("VIF%u.%u: failed to delete VIF\n", vif->mac->macid,
vif->vifid);
@@ -335,6 +337,8 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev)
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
int ret;
+ qtnf_scan_done(vif->mac, true);
+
ret = qtnf_cmd_send_stop_ap(vif);
if (ret) {
pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
@@ -570,8 +574,6 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device *dev,
!qtnf_sta_list_lookup(&vif->sta_list, params->mac))
return 0;
- qtnf_scan_done(vif->mac, true);
-
ret = qtnf_cmd_send_del_sta(vif, params);
if (ret)
pr_err("VIF%u.%u: failed to delete STA %pM\n",
@@ -1134,8 +1136,9 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
}
vif->sta_state = QTNF_STA_DISCONNECTED;
- qtnf_scan_done(mac, true);
}
+
+ qtnf_scan_done(mac, true);
}
void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
index 6a4af52522b8..66db26613b1f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
@@ -34,6 +34,9 @@ static inline void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted)
.aborted = aborted,
};
+ if (timer_pending(&mac->scan_timeout))
+ del_timer_sync(&mac->scan_timeout);
+
mutex_lock(&mac->mac_lock);
if (mac->scan_req) {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
index 5e60180482d1..7f83bedc0b88 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -68,9 +68,9 @@ static int qtnf_netdev_open(struct net_device *ndev)
*/
static int qtnf_netdev_close(struct net_device *ndev)
{
- netif_carrier_off(ndev);
qtnf_virtual_intf_cleanup(ndev);
qtnf_netdev_updown(ndev, 0);
+ netif_carrier_off(ndev);
return 0;
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 0fc2814eafad..43d2e7fd6e02 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -345,8 +345,6 @@ qtnf_event_handle_scan_complete(struct qtnf_wmac *mac,
return -EINVAL;
}
- if (timer_pending(&mac->scan_timeout))
- del_timer_sync(&mac->scan_timeout);
qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED);
return 0;
--
2.11.0
^ permalink raw reply related
* [PATCH 00/10] iwlwifi: updates intended for v4.15 2017-09-15
From: Luca Coelho @ 2017-09-15 12:46 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Luca Coelho
From: Luca Coelho <luciano.coelho@intel.com>
Hi,
Here's my first set of patches intended for 4.15. Nothing major here,
these are the changes:
* Cleanups: - remove an unused value that we read from the NVM;
- remove link quality measurement code that was never used;
* One FW command API update;
* A fix and an addition for PCI devices for the A000 family;
* Tiny refactor of ref/unref code used by runtime-PM;
* Some debugging improvements;
* Implementation of a more flexible way to define command queue sizes;
As usual, I'm pushing this to a pending branch, for kbuild bot, and
will send a pull-request later.
Please review.
Cheers,
Luca.
Chaya Rachel Ivgi (1):
iwlwifi: remove redundant reading from NVM file
David Spinadel (1):
iwlwifi: mvm: Add new quota command API
Emmanuel Grumbach (2):
iwlwifi: mvm: remove support for Link Quality Measurements
iwlwifi: mvm: support firmware debug trigger on frame reorder timeout
Ilan Peer (1):
iwlwifi: Add few debug prints to the WRT dump flow
Liad Kaufman (1):
iwlwifi: mvm: add dbgfs entry for fw info
Luca Coelho (1):
iwlwifi: trans: move ref/unref code to the common part of the
transport
Oren Givon (2):
iwlwifi: fix wrong struct for a000 device
iwlwifi: add a new a000 device
Shahar S Matityahu (1):
iwlwifi: pcie: dynamic Tx command queue size
drivers/net/wireless/intel/iwlwifi/cfg/a000.c | 3 +-
.../net/wireless/intel/iwlwifi/fw/api/binding.h | 41 ++++++++-
.../net/wireless/intel/iwlwifi/fw/api/mac-cfg.h | 67 ---------------
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 15 ++++
drivers/net/wireless/intel/iwlwifi/fw/file.h | 3 +
drivers/net/wireless/intel/iwlwifi/iwl-config.h | 3 +
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 7 --
drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 16 ++++
drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 14 +---
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 16 ++--
.../net/wireless/intel/iwlwifi/mvm/debugfs-vif.c | 76 -----------------
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 32 ++++++++
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 38 +--------
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 45 +++++++---
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 -
drivers/net/wireless/intel/iwlwifi/mvm/quota.c | 59 +++++++------
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 5 ++
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 96 ++++++----------------
.../net/wireless/intel/iwlwifi/pcie/ctxt-info.c | 2 +-
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 3 +-
drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 3 +
drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 8 +-
drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 23 +++++-
24 files changed, 255 insertions(+), 323 deletions(-)
--
2.14.1
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox