* Re: [PATCH V2 3/3] cfg80211: support ieee80211-freq-limit DT property
From: Rafał Miłecki @ 2017-01-02 14:09 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-wireless@vger.kernel.org, Martin Blumenstingl,
Felix Fietkau, Arend van Spriel, Arnd Bergmann,
devicetree@vger.kernel.org, Rafał Miłecki
In-Reply-To: <1483365844.21014.6.camel@sipsolutions.net>
On 2 January 2017 at 15:04, Johannes Berg <johannes@sipsolutions.net> wrote=
:
>> + prop =3D of_find_property(np, "ieee80211-freq-limit", &i);
>> + if (!prop)
>> + return 0;
>> +
>> + i =3D i / sizeof(u32);
>
> What if it's not even a multiple of sizeof(u32)? Shouldn't you check
> that, in case it's completely bogus?
>
>> + if (i % 2) {
>> + dev_err(dev, "ieee80211-freq-limit wrong value");
>
> say "wrong format" perhaps? we don't care (much) above the values.
>
>> + return -EPROTO;
>> + }
>> + wiphy->n_freq_limits =3D i / 2;
>
> I don't like this use of the 'i' variable - use something like
> 'len[gth]' instead?
>
>> + wiphy->freq_limits =3D kzalloc(wiphy->n_freq_limits *
>> sizeof(*wiphy->freq_limits),
>> + GFP_KERNEL);
>> + if (!wiphy->freq_limits) {
>> + err =3D -ENOMEM;
>> + goto out;
>> + }
>> +
>> + p =3D NULL;
>> + for (i =3D 0; i < wiphy->n_freq_limits; i++) {
>> + struct ieee80211_freq_range *limit =3D &wiphy-
>> >freq_limits[i];
>> +
>> + p =3D of_prop_next_u32(prop, p, &limit-
>> >start_freq_khz);
>> + if (!p) {
>> + err =3D -EINVAL;
>> + goto out;
>> + }
>> +
>> + p =3D of_prop_next_u32(prop, p, &limit->end_freq_khz);
>> + if (!p) {
>> + err =3D -EINVAL;
>> + goto out;
>> + }
>> + }
>
> You should also reject nonsense like empty ranges, or ranges with a
> higher beginning than end, etc. I think
>
>
> put
>
> return 0;
>
> here.
>
>> +out:
>> + if (err) {
>
> then you can make that a pure "error" label and remove the "if (err)"
> check.
>
>> +void wiphy_freq_limits_apply(struct wiphy *wiphy)
>
> I don't see any point in having this here rather than in reg.c, which
> is the only user.
>
>> + if (!wiphy_freq_limits_valid_chan(wiphy,
>> chan)) {
>> + pr_debug("Disabling freq %d MHz as
>> it's out of OF limits\n",
>> + chan->center_freq);
>> + chan->flags |=3D IEEE80211_CHAN_DISABLED;
>
> This seems wrong.
>
> The sband and channels can be static data and be shared across
> different wiphys for the same driver. If the driver has custom
> regulatory etc. then this can't work, but that's up to the driver. OF
> data is handled here though, so if OF data for one device disables a
> channel, this would also cause the channel to be disabled for another
> device, if the data is shared.
>
> To avoid this, you'd have to have drivers that never share it - but you
> can't really guarantee that at this level.
>
> In order to fix that, you probably need to memdup the sband/channel
> structs during wiphy registration. Then, if you set it up the right
> way, you can actually simply edit them according to the OF data
> directly there, so that *orig_flags* (rather than just flags) already
> gets the DISABLED bit - and that allows you to get rid of the reg.c
> hooks entirely since it'll look the same to reg.c independent of the
> driver or the OF stuff doing this.
>
>
> That can actually be inefficient though, since drivers may already have
> copied the channel data somewhere and then you copy it again since you
> can't know.
>
> Perhaps a better approach would be to not combine this with wiphy
> registration, but require drivers that may use this to call a new
> helper function *before* wiphy registration (and *after* calling
> set_wiphy_dev()), like e.g.
>
> ieee80211_read_of_data(wiphy);
>
> You can then also make this an inline when OF is not configured in
> (something which you haven't really taken into account now, you should
> have used dev_of_node() too instead of dev->of_node)
>
> Yes, this would mean that it doesn't automatically get applied to
> arbitrary drivers, but it seems unlikely that arbitrary drivers like
> realtek USB would suddenly get OF node entries ... so that's not
> necessarily a bad thing.
>
> In the documentation for this function you could then document that it
> will modify flags, and as such must not be called when the sband and
> channel data is shared, getting rid of the waste/complexity of the copy
> you otherwise have to make in cfg80211.
Thank you, I appreciate your review a lot, I'll work on this according
to your comments!
--=20
Rafa=C5=82
^ permalink raw reply
* Re: [PATCH V2 1/3] cfg80211: allow passing struct device in the wiphy_new call
From: Johannes Berg @ 2017-01-02 14:10 UTC (permalink / raw)
To: Rafał Miłecki
Cc: linux-wireless@vger.kernel.org, Martin Blumenstingl,
Felix Fietkau, Arend van Spriel, Arnd Bergmann,
devicetree@vger.kernel.org, Rafał Miłecki
In-Reply-To: <CACna6rzc2hk2xosd54eZVSUCtqgtT5E2vii24rgWBV96PR1W7A@mail.gmail.com>
> 2) mac80211 - it's a big one as it's used in SET_IEEE80211_DEV
>
> I was planning to work on mac80211 drivers later. This will require
> similar modification of ieee80211_alloc_hw.
Ah, ok, thanks for the explanation.
johannes
^ permalink raw reply
* Re: [PATCH] cfg80211: Random local address for Public Action frame exchange
From: IgorMitsyanko @ 2017-01-02 14:29 UTC (permalink / raw)
To: Johannes Berg, jouni; +Cc: linux-wireless, vamsin
In-Reply-To: <1483356523.4596.12.camel@sipsolutions.net>
On 01/02/2017 02:28 PM, Johannes Berg wrote:
> On Fri, 2016-12-30 at 22:55 +0300, IgorMitsyanko wrote:
>>> The driver needs to configure receive behavior to accept frames to
>>> the
>>> specified random address during the time the frame exchange is
>>> pending
>>> and such frames need to be acknowledged similarly to frames sent to
>>> the
>>> local permanent address when this random address functionality is
>>> not
>>> used.
>> A (probably) silly question: how wireless drivers are supposed to use
>> SA
>> in a frame? I think drivers are not concerned about source address,
>> they
>> simply pass whatever there is already set by userspace in
>> cfg80211_mgmt_tx_params::buf into air on Tx.
>> And on Rx, they filter frames based on receiver address/BSSID, pass
>> it
>> to upper layers and do not care what address is in DA (it is handled
>> by
>> upper layers).
> They do care about the DA in RX, since - as the commit message states -
> "such frames need to be acknowledged [...]"
Acknowledgment is done for transmitter<->receiver addresses,
not for source<->destination?
Patch talks about source address randomization, but I guess it actually
meant transmitter address (basically dynamic BSSID config?). Maybe naming
should be changed in the patch.
For NL80211_EXT_FEATURE_MGMT_TX_RANDOM_SA_CONNECTED case,
I wonder if HW can be configured to not filter-out multiple BSSIDs or
the idea
is that while random_sa frame is pending for ACK, HW will drop all
frames destined
for initially configured BSSID?
>
> johannes
>
^ permalink raw reply
* Re: [PATCH] cfg80211: Random local address for Public Action frame exchange
From: Johannes Berg @ 2017-01-02 14:33 UTC (permalink / raw)
To: IgorMitsyanko, jouni; +Cc: linux-wireless, vamsin
In-Reply-To: <c7eaea82-a5be-d047-c67a-ce9e58b4b65f@quantenna.com>
> Acknowledgment is done for transmitter<->receiver addresses,
> not for source<->destination?
Well, these are management frames, there either are no SA/DA or they're
identical to RA/TA, depending on how you want to look at it. Typically
it does get called SA/DA too then.
> Patch talks about source address randomization, but I guess it
> actually
> meant transmitter address (basically dynamic BSSID config?). Maybe
> naming should be changed in the patch.
Yes, I suppose TA might be a tad more accurate.
BSSID is another (unrelated) address.
> For NL80211_EXT_FEATURE_MGMT_TX_RANDOM_SA_CONNECTED case,
> I wonder if HW can be configured to not filter-out multiple BSSIDs
> or
> the idea
> is that while random_sa frame is pending for ACK, HW will drop all
> frames destined
> for initially configured BSSID?
Again, BSSID is unrelated (unless you're restricting yourself to the AP
STA case where BSSID == local MAC address).
And no, traffic would not be permitted to be dropped in this case, IMO
johannes
^ permalink raw reply
* pull-request: mac80211 2017-01-02
From: Johannes Berg @ 2017-01-02 14:39 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-wireless
Hi Dave,
Happy New Year :-)
Even though I was out for around two weeks, only a single fix came in,
I guess everyone else was also out. But if people were out, then they
won't be sending fixes soon again I suppose, and if they weren't out
they haven't sent more fixes, so I decided to send this one to you now.
Please pull and let me know if there's any problem.
Thanks,
johannes
The following changes since commit eb7903bb83cc1db31a9124d4cc8a1bddebe26e33:
Merge branch 'l2tp-socket-lookup-fixes' (2017-01-01 22:07:25 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git tags/mac80211-for-davem-2017-01-02
for you to fetch changes up to 35f432a03e41d3bf08c51ede917f94e2288fbe8c:
mac80211: initialize fast-xmit 'info' later (2017-01-02 11:28:25 +0100)
----------------------------------------------------------------
A single fix to avoid loading an skb->cb pointer too early.
----------------------------------------------------------------
Johannes Berg (1):
mac80211: initialize fast-xmit 'info' later
net/mac80211/tx.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
^ permalink raw reply
* Re: [PATCH 1/2] Documentation: devicetree: Add bindings info for rfkill-regulator
From: Johannes Berg @ 2017-01-02 14:57 UTC (permalink / raw)
To: Rob Herring, Paul Cercueil
Cc: David S . Miller, Mark Rutland, netdev, devicetree, linux-kernel,
linux-wireless, Maarten ter Huurne
In-Reply-To: <20161109182612.i4rnsdxulk5ghemz@rob-hp-laptop>
> My understanding is it is generally felt that using the regulator
> enable GPIO commonly found on WiFi chips for rfkill is an abuse of
> rfkill as it is more that just an RF disable. From a DT standpoint,
> this seems like creating a binding for what a Linux driver wants.
> Instead, I think this should be either a GPIO or GPIO regulator and
> the driver for the WiFi chip should decide whether or not to register
> that as an rfkill driver.
Sadly, there are two ways to use rfkill right now:
1) the more common, and correct, way of having rfkill be a control tied
to a specific wireless interface (wifi, BT, FM, GPS, NFC, ...), to both
report the hardware button state that might be tied to it, and to
control - centrally - the software state.
2) the platform way, which some ACPI based platforms do, which register
an rfkill instance, which often allows controlling in software the
hardware line that then toggles the hardware rfkill on the WiFi NIC.
It's not clear to me what this patch is trying to achieve. It seems a
bit like something else entirely, which would be using it to toggle the
power for a wifi device? I agree that doesn't seem appropriate, and
instead the driver could bind to the regulator and disable it when wifi
gets disabled (by rfkill or simply by taking all interfaces down.)
In fact, given that there are no in-tree users, I'm tempted to remove
the rfkill-regulator entirely. Thoughts?
johannes
^ permalink raw reply
* [PATCH] rfkill: remove rfkill-regulator
From: Johannes Berg @ 2017-01-02 15:01 UTC (permalink / raw)
To: linux-wireless
Cc: netdev, Guiming Zhuo, Antonio Ospite, Paul Cercueil, Rob Herring,
Maarten ter Huurne, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
There are no users of this ("vrfkill") in the tree, so it's just
dead code - remove it.
This also isn't really how rfkill is supposed to be used - it's
intended as a signalling mechanism to/from the device, which the
driver (and partially cfg80211) will handle - having a separate
rfkill instance for a regulator is confusing, the driver should
use the regulator instead to turn off the device when requested.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/linux/rfkill-regulator.h | 48 ------------
net/rfkill/Kconfig | 11 ---
net/rfkill/Makefile | 1 -
net/rfkill/rfkill-regulator.c | 154 ---------------------------------------
4 files changed, 214 deletions(-)
delete mode 100644 include/linux/rfkill-regulator.h
delete mode 100644 net/rfkill/rfkill-regulator.c
diff --git a/include/linux/rfkill-regulator.h b/include/linux/rfkill-regulator.h
deleted file mode 100644
index aca36bc83315..000000000000
--- a/include/linux/rfkill-regulator.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * rfkill-regulator.c - Regulator consumer driver for rfkill
- *
- * Copyright (C) 2009 Guiming Zhuo <gmzhuo@gmail.com>
- * Copyright (C) 2011 Antonio Ospite <ospite@studenti.unina.it>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#ifndef __LINUX_RFKILL_REGULATOR_H
-#define __LINUX_RFKILL_REGULATOR_H
-
-/*
- * Use "vrfkill" as supply id when declaring the regulator consumer:
- *
- * static struct regulator_consumer_supply pcap_regulator_V6_consumers [] = {
- * { .dev_name = "rfkill-regulator.0", .supply = "vrfkill" },
- * };
- *
- * If you have several regulator driven rfkill, you can append a numerical id to
- * .dev_name as done above, and use the same id when declaring the platform
- * device:
- *
- * static struct rfkill_regulator_platform_data ezx_rfkill_bt_data = {
- * .name = "ezx-bluetooth",
- * .type = RFKILL_TYPE_BLUETOOTH,
- * };
- *
- * static struct platform_device a910_rfkill = {
- * .name = "rfkill-regulator",
- * .id = 0,
- * .dev = {
- * .platform_data = &ezx_rfkill_bt_data,
- * },
- * };
- */
-
-#include <linux/rfkill.h>
-
-struct rfkill_regulator_platform_data {
- char *name; /* the name for the rfkill switch */
- enum rfkill_type type; /* the type as specified in rfkill.h */
-};
-
-#endif /* __LINUX_RFKILL_REGULATOR_H */
diff --git a/net/rfkill/Kconfig b/net/rfkill/Kconfig
index 868f1ad0415a..060600b03fad 100644
--- a/net/rfkill/Kconfig
+++ b/net/rfkill/Kconfig
@@ -23,17 +23,6 @@ config RFKILL_INPUT
depends on INPUT = y || RFKILL = INPUT
default y if !EXPERT
-config RFKILL_REGULATOR
- tristate "Generic rfkill regulator driver"
- depends on RFKILL || !RFKILL
- depends on REGULATOR
- help
- This options enable controlling radio transmitters connected to
- voltage regulator using the regulator framework.
-
- To compile this driver as a module, choose M here: the module will
- be called rfkill-regulator.
-
config RFKILL_GPIO
tristate "GPIO RFKILL driver"
depends on RFKILL
diff --git a/net/rfkill/Makefile b/net/rfkill/Makefile
index 311768783f4a..87a80aded0b3 100644
--- a/net/rfkill/Makefile
+++ b/net/rfkill/Makefile
@@ -5,5 +5,4 @@
rfkill-y += core.o
rfkill-$(CONFIG_RFKILL_INPUT) += input.o
obj-$(CONFIG_RFKILL) += rfkill.o
-obj-$(CONFIG_RFKILL_REGULATOR) += rfkill-regulator.o
obj-$(CONFIG_RFKILL_GPIO) += rfkill-gpio.o
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c
deleted file mode 100644
index 50cd26a48e87..000000000000
--- a/net/rfkill/rfkill-regulator.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * rfkill-regulator.c - Regulator consumer driver for rfkill
- *
- * Copyright (C) 2009 Guiming Zhuo <gmzhuo@gmail.com>
- * Copyright (C) 2011 Antonio Ospite <ospite@studenti.unina.it>
- *
- * Implementation inspired by leds-regulator driver.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/rfkill.h>
-#include <linux/rfkill-regulator.h>
-
-struct rfkill_regulator_data {
- struct rfkill *rf_kill;
- bool reg_enabled;
-
- struct regulator *vcc;
-};
-
-static int rfkill_regulator_set_block(void *data, bool blocked)
-{
- struct rfkill_regulator_data *rfkill_data = data;
- int ret = 0;
-
- pr_debug("%s: blocked: %d\n", __func__, blocked);
-
- if (blocked) {
- if (rfkill_data->reg_enabled) {
- regulator_disable(rfkill_data->vcc);
- rfkill_data->reg_enabled = false;
- }
- } else {
- if (!rfkill_data->reg_enabled) {
- ret = regulator_enable(rfkill_data->vcc);
- if (!ret)
- rfkill_data->reg_enabled = true;
- }
- }
-
- pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__,
- regulator_is_enabled(rfkill_data->vcc));
-
- return ret;
-}
-
-static struct rfkill_ops rfkill_regulator_ops = {
- .set_block = rfkill_regulator_set_block,
-};
-
-static int rfkill_regulator_probe(struct platform_device *pdev)
-{
- struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data;
- struct rfkill_regulator_data *rfkill_data;
- struct regulator *vcc;
- struct rfkill *rf_kill;
- int ret = 0;
-
- if (pdata == NULL) {
- dev_err(&pdev->dev, "no platform data\n");
- return -ENODEV;
- }
-
- if (pdata->name == NULL || pdata->type == 0) {
- dev_err(&pdev->dev, "invalid name or type in platform data\n");
- return -EINVAL;
- }
-
- vcc = regulator_get_exclusive(&pdev->dev, "vrfkill");
- if (IS_ERR(vcc)) {
- dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
- ret = PTR_ERR(vcc);
- goto out;
- }
-
- rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL);
- if (rfkill_data == NULL) {
- ret = -ENOMEM;
- goto err_data_alloc;
- }
-
- rf_kill = rfkill_alloc(pdata->name, &pdev->dev,
- pdata->type,
- &rfkill_regulator_ops, rfkill_data);
- if (rf_kill == NULL) {
- ret = -ENOMEM;
- goto err_rfkill_alloc;
- }
-
- if (regulator_is_enabled(vcc)) {
- dev_dbg(&pdev->dev, "Regulator already enabled\n");
- rfkill_data->reg_enabled = true;
- }
- rfkill_data->vcc = vcc;
- rfkill_data->rf_kill = rf_kill;
-
- ret = rfkill_register(rf_kill);
- if (ret) {
- dev_err(&pdev->dev, "Cannot register rfkill device\n");
- goto err_rfkill_register;
- }
-
- platform_set_drvdata(pdev, rfkill_data);
- dev_info(&pdev->dev, "%s initialized\n", pdata->name);
-
- return 0;
-
-err_rfkill_register:
- rfkill_destroy(rf_kill);
-err_rfkill_alloc:
- kfree(rfkill_data);
-err_data_alloc:
- regulator_put(vcc);
-out:
- return ret;
-}
-
-static int rfkill_regulator_remove(struct platform_device *pdev)
-{
- struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
- struct rfkill *rf_kill = rfkill_data->rf_kill;
-
- rfkill_unregister(rf_kill);
- rfkill_destroy(rf_kill);
- regulator_put(rfkill_data->vcc);
- kfree(rfkill_data);
-
- return 0;
-}
-
-static struct platform_driver rfkill_regulator_driver = {
- .probe = rfkill_regulator_probe,
- .remove = rfkill_regulator_remove,
- .driver = {
- .name = "rfkill-regulator",
- },
-};
-
-module_platform_driver(rfkill_regulator_driver);
-
-MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>");
-MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
-MODULE_DESCRIPTION("Regulator consumer driver for rfkill");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:rfkill-regulator");
--
2.9.3
^ permalink raw reply related
* Re: [PATCH] rfkill: remove rfkill-regulator
From: Johannes Berg @ 2017-01-02 15:03 UTC (permalink / raw)
To: linux-wireless
Cc: netdev, Guiming Zhuo, Antonio Ospite, Paul Cercueil, Rob Herring,
Maarten ter Huurne
In-Reply-To: <20170102150157.26745-1-johannes@sipsolutions.net>
On Mon, 2017-01-02 at 16:01 +0100, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> There are no users of this ("vrfkill") in the tree, so it's just
> dead code - remove it.
>
> This also isn't really how rfkill is supposed to be used - it's
> intended as a signalling mechanism to/from the device, which the
> driver (and partially cfg80211) will handle - having a separate
> rfkill instance for a regulator is confusing, the driver should
> use the regulator instead to turn off the device when requested.
OTOH, the rfkill-gpio is essentially the same thing, and it *does* get
used - by ACPI even, to control a GPS chip. And I'm not even sure that
there's a clear place to put this since there probably aren't any GPS
drivers?
johannes
^ permalink raw reply
* Re: [PATCH V2 3/3] cfg80211: support ieee80211-freq-limit DT property
From: Rafał Miłecki @ 2017-01-02 15:05 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-wireless@vger.kernel.org, Martin Blumenstingl,
Felix Fietkau, Arend van Spriel, Arnd Bergmann,
devicetree@vger.kernel.org, Rafał Miłecki
In-Reply-To: <1483365844.21014.6.camel@sipsolutions.net>
On 2 January 2017 at 15:04, Johannes Berg <johannes@sipsolutions.net> wrote=
:
> Perhaps a better approach would be to not combine this with wiphy
> registration, but require drivers that may use this to call a new
> helper function *before* wiphy registration (and *after* calling
> set_wiphy_dev()), like e.g.
>
> ieee80211_read_of_data(wiphy);
>
> (...)
>
> Yes, this would mean that it doesn't automatically get applied to
> arbitrary drivers, but it seems unlikely that arbitrary drivers like
> realtek USB would suddenly get OF node entries ... so that's not
> necessarily a bad thing.
>
> In the documentation for this function you could then document that it
> will modify flags, and as such must not be called when the sband and
> channel data is shared, getting rid of the waste/complexity of the copy
> you otherwise have to make in cfg80211.
I just think it may be better to stick to something like
ieee80211_read_of_freq_limits
or
wiphy_read_of_freq_limits
As you noted this function will be a bit specific because of modifying
(possibly shared) band channels. At some point we may want to add more
helpers for other OF properties which won't have extra requirements
for driver code. Some drivers may want to use them while not necessary
risking have shared band channels modified.
--=20
Rafa=C5=82
^ permalink raw reply
* Re: [PATCH V2 3/3] cfg80211: support ieee80211-freq-limit DT property
From: Johannes Berg @ 2017-01-02 15:10 UTC (permalink / raw)
To: Rafał Miłecki
Cc: linux-wireless@vger.kernel.org, Martin Blumenstingl,
Felix Fietkau, Arend van Spriel, Arnd Bergmann,
devicetree@vger.kernel.org, Rafał Miłecki
In-Reply-To: <CACna6rzvvkXBBHrDj4vVgcM0GmzTxM-Bh60nXYOkRH1-2WrWMQ@mail.gmail.com>
On Mon, 2017-01-02 at 16:05 +0100, Rafał Miłecki wrote:
> On 2 January 2017 at 15:04, Johannes Berg <johannes@sipsolutions.net>
> wrote:
> > Perhaps a better approach would be to not combine this with wiphy
> > registration, but require drivers that may use this to call a new
> > helper function *before* wiphy registration (and *after* calling
> > set_wiphy_dev()), like e.g.
> >
> > ieee80211_read_of_data(wiphy);
> >
> > (...)
> I just think it may be better to stick to something like
> ieee80211_read_of_freq_limits
> or
> wiphy_read_of_freq_limits
I have no objection to that.
> As you noted this function will be a bit specific because of
> modifying (possibly shared) band channels. At some point we may want
> to add more helpers for other OF properties which won't have extra
> requirements for driver code. Some drivers may want to use them while
> not necessary risking have shared band channels modified.
That makes sense, although at that time we might still wish to have a
common "read it all" with the combined requirements. But we can cross
that bridge when we get to it.
johannes
^ permalink raw reply
* [PATCH V3 1/2] dt-bindings: document common IEEE 802.11 frequency limit property
From: Rafał Miłecki @ 2017-01-02 16:32 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: Martin Blumenstingl, Felix Fietkau, Arend van Spriel,
Arnd Bergmann, devicetree, Rafał Miłecki
From: Rafał Miłecki <rafal@milecki.pl>
This new file should be used for properties that apply to all wireless
devices.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
V2: Switch to a single ieee80211-freq-limit property that allows specifying
*multiple* ranges. This resolves problem with more complex rules as pointed
by Felx.
Make description implementation agnostic as pointed by Arend.
Rename node to wifi as suggested by Martin.
V3: Use more real-life frequencies in the example.
---
.../devicetree/bindings/net/wireless/ieee80211.txt | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/wireless/ieee80211.txt
diff --git a/Documentation/devicetree/bindings/net/wireless/ieee80211.txt b/Documentation/devicetree/bindings/net/wireless/ieee80211.txt
new file mode 100644
index 0000000..0cd1219
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/wireless/ieee80211.txt
@@ -0,0 +1,18 @@
+Common IEEE 802.11 properties
+
+This provides documentation of common properties that are valid for all wireless
+devices.
+
+Optional properties:
+ - ieee80211-freq-limit : list of supported frequency ranges in KHz
+
+Example:
+
+pcie@0,0 {
+ reg = <0x0000 0 0 0 0>;
+ wifi@0,0 {
+ reg = <0x0000 0 0 0 0>;
+ ieee80211-freq-limit = <2402000 2482000>,
+ <5170000 5250000>;
+ };
+};
--
2.10.1
^ permalink raw reply related
* [PATCH V3 2/2] cfg80211: support ieee80211-freq-limit DT property
From: Rafał Miłecki @ 2017-01-02 16:32 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: Martin Blumenstingl, Felix Fietkau, Arend van Spriel,
Arnd Bergmann, devicetree, Rafał Miłecki
In-Reply-To: <20170102163209.2445-1-zajec5@gmail.com>
From: Rafał Miłecki <rafal@milecki.pl>
It allows specifying hardware limitations of supported channels. This
may be useful for specifying single band devices or devices that support
only some part of the whole band.
This can be useful for some tri-band routers that have separated radios
for lower and higher part of 5 GHz band.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
V2: Put main code in core.c as it isn't strictly part of regulatory - pointed
by Arend.
Update to support ieee80211-freq-limit (new property).
V3: Introduce separated wiphy_read_of_freq_limits function.
Add extra sanity checks for DT data.
Move code back to reg.c as suggested by Johannes.
---
include/net/cfg80211.h | 23 ++++++++++
net/wireless/core.c | 1 +
net/wireless/reg.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 142 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ca2ac1c..5002625 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3515,6 +3515,9 @@ struct wiphy_iftype_ext_capab {
* attribute indices defined in &enum nl80211_bss_select_attr.
*
* @cookie_counter: unique generic cookie counter, used to identify objects.
+ *
+ * @n_freq_limits: number of frequency limits
+ * @freq_limits: array of extra frequency limits
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -3646,6 +3649,9 @@ struct wiphy {
u64 cookie_counter;
+ unsigned int n_freq_limits;
+ struct ieee80211_freq_range *freq_limits;
+
char priv[0] __aligned(NETDEV_ALIGN);
};
@@ -4278,6 +4284,23 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
*/
/**
+ * 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 extermal power amplifier).
+ *
+ * This function reads info from DT and uses it to *modify* channels (disable
+ * unavailable ones) in a regulary code. It's usually a *bad* idea to use it in
+ * drivers with *shared* channel data as DT limitations are device specific.
+ *
+ * As this function access device node it has to be called after set_wiphy_dev.
+ */
+int wiphy_read_of_freq_limits(struct wiphy *wiphy);
+
+/**
* regulatory_hint - driver hint to the wireless core a regulatory domain
* @wiphy: the wireless device giving the hint (used only for reporting
* conflicts)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 158c59e..c1b5fc7 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -940,6 +940,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
void wiphy_free(struct wiphy *wiphy)
{
+ kfree(wiphy->freq_limits);
put_device(&wiphy->dev);
}
EXPORT_SYMBOL(wiphy_free);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 5dbac37..e00fd5b 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1158,6 +1158,120 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
return bw_flags;
}
+int wiphy_read_of_freq_limits(struct wiphy *wiphy)
+{
+ struct device *dev = wiphy_dev(wiphy);
+ struct device_node *np;
+ struct property *prop;
+ const __be32 *p;
+ int len, i, err;
+
+ if (wiphy->n_freq_limits)
+ return 0;
+
+ if (!dev)
+ return 0;
+ np = dev_of_node(dev);
+ if (!np)
+ return 0;
+
+ prop = of_find_property(np, "ieee80211-freq-limit", &len);
+ if (!prop)
+ return 0;
+
+ if (!len || len % sizeof(u32) || len / sizeof(u32) % 2) {
+ dev_err(dev, "ieee80211-freq-limit wrong format");
+ return -EPROTO;
+ }
+ wiphy->n_freq_limits = len / sizeof(u32) / 2;
+
+ wiphy->freq_limits = kzalloc(wiphy->n_freq_limits * sizeof(*wiphy->freq_limits),
+ GFP_KERNEL);
+ if (!wiphy->freq_limits) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ p = NULL;
+ for (i = 0; i < wiphy->n_freq_limits; i++) {
+ struct ieee80211_freq_range *limit = &wiphy->freq_limits[i];
+
+ p = of_prop_next_u32(prop, p, &limit->start_freq_khz);
+ if (!p) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ p = of_prop_next_u32(prop, p, &limit->end_freq_khz);
+ if (!p) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (!limit->start_freq_khz ||
+ !limit->end_freq_khz ||
+ limit->start_freq_khz >= limit->end_freq_khz) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ return 0;
+
+out:
+ dev_err(dev, "Failed to get limits: %d\n", err);
+ kfree(wiphy->freq_limits);
+ wiphy->n_freq_limits = 0;
+
+ return err;
+}
+EXPORT_SYMBOL(wiphy_read_of_freq_limits);
+
+static bool wiphy_freq_limits_valid_chan(struct wiphy *wiphy,
+ struct ieee80211_channel *chan)
+{
+ u32 bw = MHZ_TO_KHZ(20);
+ int i;
+
+ for (i = 0; i < wiphy->n_freq_limits; i++) {
+ struct ieee80211_freq_range *limit = &wiphy->freq_limits[i];
+
+ if (reg_does_bw_fit(limit, MHZ_TO_KHZ(chan->center_freq), bw))
+ return true;
+ }
+
+ return false;
+}
+
+static void wiphy_freq_limits_apply(struct wiphy *wiphy)
+{
+ enum nl80211_band band;
+ int i;
+
+ if (!wiphy->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, chan)) {
+ pr_debug("Disabling freq %d MHz as it's out of OF limits\n",
+ chan->center_freq);
+ chan->flags |= IEEE80211_CHAN_DISABLED;
+ }
+ }
+ }
+}
+
/*
* Note that right now we assume the desired channel bandwidth
* is always 20 MHz for each individual channel (HT40 uses 20 MHz
@@ -1693,6 +1807,8 @@ static void wiphy_update_regulatory(struct wiphy *wiphy,
for (band = 0; band < NUM_NL80211_BANDS; band++)
handle_band(wiphy, initiator, wiphy->bands[band]);
+ wiphy_freq_limits_apply(wiphy);
+
reg_process_beacons(wiphy);
reg_process_ht_flags(wiphy);
reg_call_notifier(wiphy, lr);
@@ -1800,6 +1916,8 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
bands_set++;
}
+ wiphy_freq_limits_apply(wiphy);
+
/*
* no point in calling this if it won't have any effect
* on your device's supported bands.
--
2.10.1
^ permalink raw reply related
* [PATCH V3 3/2] brcmfmac: use wiphy_read_of_freq_limits to get extra limits
From: Rafał Miłecki @ 2017-01-02 16:32 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: Martin Blumenstingl, Felix Fietkau, Arend van Spriel,
Arnd Bergmann, devicetree, Rafał Miłecki
In-Reply-To: <20170102163209.2445-1-zajec5@gmail.com>
From: Rafał Miłecki <rafal@milecki.pl>
There are some devices (e.g. Netgear R8000 home router) with one chipset
model used for different radios, some of them limited to subbands. NVRAM
entries don't contain any extra info on such limitations and firmware
reports full list of channels to us. We need to store extra limitation
info on DT to support such devices properly.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
This patch should probably go through wireless-driver-next, I'm sending
it just as a proof of concept. It was succesfully tested on SmartRG
SR400ac with BCM43602.
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index ccae3bb..dab4082 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -6825,6 +6825,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
goto priv_out;
brcmf_dbg(INFO, "Registering custom regulatory\n");
+ wiphy_read_of_freq_limits(wiphy);
wiphy->reg_notifier = brcmf_cfg80211_reg_notifier;
wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
--
2.10.1
^ permalink raw reply related
* Re: pull-request: mac80211 2017-01-02
From: David Miller @ 2017-01-02 17:28 UTC (permalink / raw)
To: johannes; +Cc: netdev, linux-wireless
In-Reply-To: <20170102143904.20851-1-johannes@sipsolutions.net>
From: Johannes Berg <johannes@sipsolutions.net>
Date: Mon, 2 Jan 2017 15:39:03 +0100
> Happy New Year :-)
Same to you :-)
> Even though I was out for around two weeks, only a single fix came in,
> I guess everyone else was also out. But if people were out, then they
> won't be sending fixes soon again I suppose, and if they weren't out
> they haven't sent more fixes, so I decided to send this one to you now.
>
> Please pull and let me know if there's any problem.
It certainly was a slow holiday break this year, kind of nice
actually...
Pulled, thanks Johannes.
^ permalink raw reply
* Re: [PATCH V3 2/2] cfg80211: support ieee80211-freq-limit DT property
From: Johannes Berg @ 2017-01-02 17:52 UTC (permalink / raw)
To: Rafał Miłecki, linux-wireless
Cc: Martin Blumenstingl, Felix Fietkau, Arend van Spriel,
Arnd Bergmann, devicetree, Rafał Miłecki
In-Reply-To: <20170102163209.2445-2-zajec5@gmail.com>
> +static void wiphy_freq_limits_apply(struct wiphy *wiphy)
[...]
> + if (!wiphy_freq_limits_valid_chan(wiphy,
> chan)) {
> + pr_debug("Disabling freq %d MHz as
> it's out of OF limits\n",
> + chan->center_freq);
> + chan->flags |=
> IEEE80211_CHAN_DISABLED;
I think you didn't address the problem in the best way now.
The problem with the channel sharing was the way you're applying the
limits - at runtime. This is now OK since the new function shouldn't be
called when the channel structs are shared, but hooking it all into the
regulatory code is now no longer needed.
What you can do now, when reading the OF data, is actually apply it to
the channel flags immediately. If done *before* wiphy_register(), these
flags will be preserved forever, so you no longer need any hooks in
regulatory code at all - you can just set the original channel flags
according to the OF data.
I think this greatly simplifies the flow, since you can also remove
wiphy->freq_limits (and n_freq_limits) completely, since now the only
effect of the function would be to modify the channel list, and later
regulatory updates would always preserve the flags.
johannes
^ permalink raw reply
* Re: Installing driver for Ubuntu 16.04 Intel(R) Wireless WiFi Link 4965AGN
From: info @ 2017-01-02 18:11 UTC (permalink / raw)
To: sedat.dilek; +Cc: linux-wireless, ilw
In-Reply-To: <CA+icZUXtJG18ejLynO1FB0BS5Guqr35-Bn0_Obht-VyGNO4tAg@mail.gmail.com>
Dear Madam Sedat,
Thank you for your answer.
I already consulted Ubuntu Community but it is not so nice for a
beginner like me. I tried several recomedations from them, but no way.
So, I thought, it is better to ask to the source.
Yes, I have the firmware you mention, but wifi doesn't work. The icon
appear in the top bar but it doesn't seem to be conected. It doesn't
seach conections even when wifi is activated. The ligh of wifi simbol in
the laptop lights some times but others it doesn't.
Any help is welcome and I won't forget ladies next time, sorry.
Thank you for your help and have a happy new year 2017 also.
Regards,
Leopoldo
El 02-01-2017 15:06, Sedat Dilek escribió:
> On Mon, Jan 2, 2017 at 2:11 PM, <info@leopoldosoria.com> wrote:
>> Dear Sirs,
>> Which of the below drivers should I install for my Lenovo 3000 V200?
>> I am runing Ubuntu 16.04
>>
>> Intel® Wireless WiFi Link 4965AGN
>> 2.6.24+ iwlwifi-4965-ucode-4.44.14.tgz
>> 2.6.24+ iwlwifi-4965-ucode-4.44.15.tgz
>> 2.6.24+ iwlwifi-4965-ucode-4.44.17.tgz
>> 2.6.24+ iwlwifi-4965-ucode-4.44.1.18.tgz
>> 2.6.24+ iwlwifi-4965-ucode-4.44.1.20.tgz
>> 2.6.24+ iwlwifi-4965-ucode-228.57.1.21.tgz
>> 2.6.28+ (?) iwlwifi-4965-ucode-228.57.2.21.tgz
>> 2.6.28+ (?) iwlwifi-4965-ucode-228.57.2.23.tgz
>> 2.6.28+ (?) iwlwifi-4965-ucode-228.61.2.24.tgz
>>
>> Ans how shoudl I proceed for intalling the right driver?
>>
>> Thank you
>>
>
> [ What about the Ladies, Sir :-)? ]
>
> Happy new 2017!
>
> You need the linux-firmware [1] package.
> Normally, Ubuntu/xenial should ship it.
>
> Check if you have...
>
> /lib/firmware/iwlwifi-4965-2.ucode
>
> ...file.
>
> Not sure why you are asking or what is not working.
> AFAICS, Ubuntu should have some nice wikis explaining a WLAN setup.
> A good strategy will always be to consult your distro's help before
> asking here.
>
> [3] as a gift.
>
> Regards,
> - Sedat -
>
> [1] http://packages.ubuntu.com/xenial/linux-firmware
> [2] http://packages.ubuntu.com/xenial/all/linux-firmware/filelist
> [3] http://www.catb.org/~esr/faqs/smart-questions.html
^ permalink raw reply
* Re: Installing driver for Ubuntu 16.04 Intel(R) Wireless WiFi Link 4965AGN
From: Sedat Dilek @ 2017-01-02 19:39 UTC (permalink / raw)
To: info; +Cc: linux-wireless
In-Reply-To: <6df84be9db053beae03eb31ece0ab2d7@mail.leopoldosoria.com>
On Mon, Jan 2, 2017 at 7:11 PM, <info@leopoldosoria.com> wrote:
> Dear Madam Sedat,
Hehe, my family name is indeed a female first name - Sedat is male.
> Thank you for your answer.
>
> I already consulted Ubuntu Community but it is not so nice for a beginner
> like me. I tried several recomedations from them, but no way. So, I
> thought, it is better to ask to the source.
>
> Yes, I have the firmware you mention, but wifi doesn't work. The icon app=
ear
> in the top bar but it doesn't seem to be conected. It doesn't seach
> conections even when wifi is activated. The ligh of wifi simbol in the
> laptop lights some times but others it doesn't.
>
It's difficult to answer without knowing anything about your hardware,
your WLAN infrastructure and your WLAN setup on Ubuntu/xenial.
It might be helpful if you attach your linux-config and dmesg output.
$ cp -v /boot/config-$(uname -r) /tmp
$ dmesg > /tmp/dmesg.txt
Attach those two files from /tmp directory and people can look at this.
- Sedat -
> Any help is welcome and I won't forget ladies next time, sorry.
>
> Thank you for your help and have a happy new year 2017 also.
>
> Regards,
> Leopoldo
>
>
>
>
> El 02-01-2017 15:06, Sedat Dilek escribi=C3=B3:
>>
>> On Mon, Jan 2, 2017 at 2:11 PM, <info@leopoldosoria.com> wrote:
>>>
>>> Dear Sirs,
>>> Which of the below drivers should I install for my Lenovo 3000 V200?
>>> I am runing Ubuntu 16.04
>>>
>>> Intel=C2=AE Wireless WiFi Link 4965AGN
>>> 2.6.24+ iwlwifi-4965-ucode-4.44.14.tgz
>>> 2.6.24+ iwlwifi-4965-ucode-4.44.15.tgz
>>> 2.6.24+ iwlwifi-4965-ucode-4.44.17.tgz
>>> 2.6.24+ iwlwifi-4965-ucode-4.44.1.18.tgz
>>> 2.6.24+ iwlwifi-4965-ucode-4.44.1.20.tgz
>>> 2.6.24+ iwlwifi-4965-ucode-228.57.1.21.tgz
>>> 2.6.28+ (?) iwlwifi-4965-ucode-228.57.2.21.tgz
>>> 2.6.28+ (?) iwlwifi-4965-ucode-228.57.2.23.tgz
>>> 2.6.28+ (?) iwlwifi-4965-ucode-228.61.2.24.tgz
>>>
>>> Ans how shoudl I proceed for intalling the right driver?
>>>
>>> Thank you
>>>
>>
>> [ What about the Ladies, Sir :-)? ]
>>
>> Happy new 2017!
>>
>> You need the linux-firmware [1] package.
>> Normally, Ubuntu/xenial should ship it.
>>
>> Check if you have...
>>
>> /lib/firmware/iwlwifi-4965-2.ucode
>>
>> ...file.
>>
>> Not sure why you are asking or what is not working.
>> AFAICS, Ubuntu should have some nice wikis explaining a WLAN setup.
>> A good strategy will always be to consult your distro's help before aski=
ng
>> here.
>>
>> [3] as a gift.
>>
>> Regards,
>> - Sedat -
>>
>> [1] http://packages.ubuntu.com/xenial/linux-firmware
>> [2] http://packages.ubuntu.com/xenial/all/linux-firmware/filelist
>> [3] http://www.catb.org/~esr/faqs/smart-questions.html
^ permalink raw reply
* [PATCH net-next] bridge: multicast to unicast
From: Linus Lüssing @ 2017-01-02 19:32 UTC (permalink / raw)
To: netdev
Cc: David S . Miller, Stephen Hemminger, bridge, linux-kernel,
linux-wireless, Linus Lüssing, Felix Fietkau
Implements an optional, per bridge port flag and feature to deliver
multicast packets to any host on the according port via unicast
individually. This is done by copying the packet per host and
changing the multicast destination MAC to a unicast one accordingly.
multicast-to-unicast works on top of the multicast snooping feature of
the bridge. Which means unicast copies are only delivered to hosts which
are interested in it and signalized this via IGMP/MLD reports
previously.
This feature is intended for interface types which have a more reliable
and/or efficient way to deliver unicast packets than broadcast ones
(e.g. wifi).
However, it should only be enabled on interfaces where no IGMPv2/MLDv1
report suppression takes place. This feature is disabled by default.
The initial patch and idea is from Felix Fietkau.
Cc: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
This feature is used and enabled by default in OpenWRT and LEDE for AP
interfaces for more than a year now to allow both a more robust multicast
delivery and multicast at higher rates (e.g. multicast streaming).
In OpenWRT/LEDE the IGMP/MLD report suppression issue is overcome by
the network daemon enabling AP isolation and by that separating all STAs.
Delivery of STA-to-STA IP mulitcast is made possible again by
enabling and utilizing the bridge hairpin mode, which considers the
incoming port as a potential outgoing port, too.
Hairpin-mode is performed after multicast snooping, therefore leading to
only deliver reports to STAs running a multicast router.
---
include/linux/if_bridge.h | 1 +
net/bridge/br_forward.c | 44 +++++++++++++++++++++--
net/bridge/br_mdb.c | 2 +-
net/bridge/br_multicast.c | 92 ++++++++++++++++++++++++++++++++++-------------
net/bridge/br_private.h | 4 ++-
net/bridge/br_sysfs_if.c | 2 ++
6 files changed, 115 insertions(+), 30 deletions(-)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index c6587c0..f1b0d78 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -46,6 +46,7 @@ struct br_ip_list {
#define BR_LEARNING_SYNC BIT(9)
#define BR_PROXYARP_WIFI BIT(10)
#define BR_MCAST_FLOOD BIT(11)
+#define BR_MULTICAST_TO_UCAST BIT(12)
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 7cb41ae..49d742d 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -174,6 +174,33 @@ static struct net_bridge_port *maybe_deliver(
return p;
}
+static struct net_bridge_port *maybe_deliver_addr(
+ struct net_bridge_port *prev, struct net_bridge_port *p,
+ struct sk_buff *skb, const unsigned char *addr,
+ bool local_orig)
+{
+ struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
+ const unsigned char *src = eth_hdr(skb)->h_source;
+
+ if (!should_deliver(p, skb))
+ return prev;
+
+ /* Even with hairpin, no soliloquies - prevent breaking IPv6 DAD */
+ if (skb->dev == p->dev && ether_addr_equal(src, addr))
+ return prev;
+
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb) {
+ dev->stats.tx_dropped++;
+ return prev;
+ }
+
+ memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
+ __br_forward(p, skb, local_orig);
+
+ return prev;
+}
+
/* called under rcu_read_lock */
void br_flood(struct net_bridge *br, struct sk_buff *skb,
enum br_pkt_type pkt_type, bool local_rcv, bool local_orig)
@@ -231,6 +258,7 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
struct net_bridge_port *prev = NULL;
struct net_bridge_port_group *p;
struct hlist_node *rp;
+ const unsigned char *addr;
rp = rcu_dereference(hlist_first_rcu(&br->router_list));
p = mdst ? rcu_dereference(mdst->ports) : NULL;
@@ -241,10 +269,20 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
NULL;
- port = (unsigned long)lport > (unsigned long)rport ?
- lport : rport;
+ if ((unsigned long)lport > (unsigned long)rport) {
+ port = lport;
+ addr = p->unicast ? p->eth_addr : NULL;
+ } else {
+ port = rport;
+ addr = NULL;
+ }
+
+ if (addr)
+ prev = maybe_deliver_addr(prev, port, skb, addr,
+ local_orig);
+ else
+ prev = maybe_deliver(prev, port, skb, local_orig);
- prev = maybe_deliver(prev, port, skb, local_orig);
if (IS_ERR(prev))
goto out;
if (prev == port)
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 7dbc80d..056e6ac 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -531,7 +531,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
break;
}
- p = br_multicast_new_port_group(port, group, *pp, state);
+ p = br_multicast_new_port_group(port, group, *pp, state, NULL);
if (unlikely(!p))
return -ENOMEM;
rcu_assign_pointer(*pp, p);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index b30e77e..470a2409 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -43,12 +43,14 @@ static void br_multicast_add_router(struct net_bridge *br,
static void br_ip4_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
__be32 group,
- __u16 vid);
+ __u16 vid,
+ const unsigned char *src);
+
#if IS_ENABLED(CONFIG_IPV6)
static void br_ip6_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
const struct in6_addr *group,
- __u16 vid);
+ __u16 vid, const unsigned char *src);
#endif
unsigned int br_mdb_rehash_seq;
@@ -711,7 +713,8 @@ struct net_bridge_port_group *br_multicast_new_port_group(
struct net_bridge_port *port,
struct br_ip *group,
struct net_bridge_port_group __rcu *next,
- unsigned char flags)
+ unsigned char flags,
+ const unsigned char *src)
{
struct net_bridge_port_group *p;
@@ -726,12 +729,35 @@ struct net_bridge_port_group *br_multicast_new_port_group(
hlist_add_head(&p->mglist, &port->mglist);
setup_timer(&p->timer, br_multicast_port_group_expired,
(unsigned long)p);
+
+ if ((port->flags & BR_MULTICAST_TO_UCAST) && src) {
+ memcpy(p->eth_addr, src, ETH_ALEN);
+ p->unicast = true;
+ }
+
return p;
}
+static bool br_port_group_equal(struct net_bridge_port_group *p,
+ struct net_bridge_port *port,
+ const unsigned char *src)
+{
+ if (p->port != port)
+ return false;
+
+ if (!p->unicast)
+ return true;
+
+ if (!src)
+ return false;
+
+ return ether_addr_equal(src, p->eth_addr);
+}
+
static int br_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
- struct br_ip *group)
+ struct br_ip *group,
+ const unsigned char *src)
{
struct net_bridge_port_group __rcu **pp;
struct net_bridge_port_group *p;
@@ -758,13 +784,13 @@ static int br_multicast_add_group(struct net_bridge *br,
for (pp = &mp->ports;
(p = mlock_dereference(*pp, br)) != NULL;
pp = &p->next) {
- if (p->port == port)
+ if (br_port_group_equal(p, port, src))
goto found;
if ((unsigned long)p->port < (unsigned long)port)
break;
}
- p = br_multicast_new_port_group(port, group, *pp, 0);
+ p = br_multicast_new_port_group(port, group, *pp, 0, src);
if (unlikely(!p))
goto err;
rcu_assign_pointer(*pp, p);
@@ -783,7 +809,8 @@ static int br_multicast_add_group(struct net_bridge *br,
static int br_ip4_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
__be32 group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
@@ -794,14 +821,15 @@ static int br_ip4_multicast_add_group(struct net_bridge *br,
br_group.proto = htons(ETH_P_IP);
br_group.vid = vid;
- return br_multicast_add_group(br, port, &br_group);
+ return br_multicast_add_group(br, port, &br_group, src);
}
#if IS_ENABLED(CONFIG_IPV6)
static int br_ip6_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
const struct in6_addr *group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
@@ -812,7 +840,7 @@ static int br_ip6_multicast_add_group(struct net_bridge *br,
br_group.proto = htons(ETH_P_IPV6);
br_group.vid = vid;
- return br_multicast_add_group(br, port, &br_group);
+ return br_multicast_add_group(br, port, &br_group, src);
}
#endif
@@ -1081,6 +1109,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
struct sk_buff *skb,
u16 vid)
{
+ const unsigned char *src;
struct igmpv3_report *ih;
struct igmpv3_grec *grec;
int i;
@@ -1121,12 +1150,14 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
continue;
}
+ src = eth_hdr(skb)->h_source;
if ((type == IGMPV3_CHANGE_TO_INCLUDE ||
type == IGMPV3_MODE_IS_INCLUDE) &&
ntohs(grec->grec_nsrcs) == 0) {
- br_ip4_multicast_leave_group(br, port, group, vid);
+ br_ip4_multicast_leave_group(br, port, group, vid, src);
} else {
- err = br_ip4_multicast_add_group(br, port, group, vid);
+ err = br_ip4_multicast_add_group(br, port, group, vid,
+ src);
if (err)
break;
}
@@ -1141,6 +1172,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
struct sk_buff *skb,
u16 vid)
{
+ const unsigned char *src = eth_hdr(skb)->h_source;
struct icmp6hdr *icmp6h;
struct mld2_grec *grec;
int i;
@@ -1192,10 +1224,11 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
grec->grec_type == MLD2_MODE_IS_INCLUDE) &&
ntohs(*nsrcs) == 0) {
br_ip6_multicast_leave_group(br, port, &grec->grec_mca,
- vid);
+ vid, src);
} else {
err = br_ip6_multicast_add_group(br, port,
- &grec->grec_mca, vid);
+ &grec->grec_mca, vid,
+ src);
if (err)
break;
}
@@ -1511,7 +1544,8 @@ br_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
struct br_ip *group,
struct bridge_mcast_other_query *other_query,
- struct bridge_mcast_own_query *own_query)
+ struct bridge_mcast_own_query *own_query,
+ const unsigned char *src)
{
struct net_bridge_mdb_htable *mdb;
struct net_bridge_mdb_entry *mp;
@@ -1535,7 +1569,7 @@ br_multicast_leave_group(struct net_bridge *br,
for (pp = &mp->ports;
(p = mlock_dereference(*pp, br)) != NULL;
pp = &p->next) {
- if (p->port != port)
+ if (!br_port_group_equal(p, port, src))
continue;
rcu_assign_pointer(*pp, p->next);
@@ -1566,7 +1600,7 @@ br_multicast_leave_group(struct net_bridge *br,
for (p = mlock_dereference(mp->ports, br);
p != NULL;
p = mlock_dereference(p->next, br)) {
- if (p->port != port)
+ if (!br_port_group_equal(p, port, src))
continue;
if (!hlist_unhashed(&p->mglist) &&
@@ -1617,7 +1651,8 @@ br_multicast_leave_group(struct net_bridge *br,
static void br_ip4_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
__be32 group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
struct bridge_mcast_own_query *own_query;
@@ -1632,14 +1667,15 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
br_group.vid = vid;
br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
- own_query);
+ own_query, src);
}
#if IS_ENABLED(CONFIG_IPV6)
static void br_ip6_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
const struct in6_addr *group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
struct bridge_mcast_own_query *own_query;
@@ -1654,7 +1690,7 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
br_group.vid = vid;
br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
- own_query);
+ own_query, src);
}
#endif
@@ -1711,6 +1747,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
struct sk_buff *skb,
u16 vid)
{
+ const unsigned char *src;
struct sk_buff *skb_trimmed = NULL;
struct igmphdr *ih;
int err;
@@ -1731,13 +1768,14 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
}
ih = igmp_hdr(skb);
+ src = eth_hdr(skb)->h_source;
BR_INPUT_SKB_CB(skb)->igmp = ih->type;
switch (ih->type) {
case IGMP_HOST_MEMBERSHIP_REPORT:
case IGMPV2_HOST_MEMBERSHIP_REPORT:
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
- err = br_ip4_multicast_add_group(br, port, ih->group, vid);
+ err = br_ip4_multicast_add_group(br, port, ih->group, vid, src);
break;
case IGMPV3_HOST_MEMBERSHIP_REPORT:
err = br_ip4_multicast_igmp3_report(br, port, skb_trimmed, vid);
@@ -1746,7 +1784,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
err = br_ip4_multicast_query(br, port, skb_trimmed, vid);
break;
case IGMP_HOST_LEAVE_MESSAGE:
- br_ip4_multicast_leave_group(br, port, ih->group, vid);
+ br_ip4_multicast_leave_group(br, port, ih->group, vid, src);
break;
}
@@ -1765,6 +1803,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
struct sk_buff *skb,
u16 vid)
{
+ const unsigned char *src;
struct sk_buff *skb_trimmed = NULL;
struct mld_msg *mld;
int err;
@@ -1785,8 +1824,10 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
switch (mld->mld_type) {
case ICMPV6_MGM_REPORT:
+ src = eth_hdr(skb)->h_source;
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
- err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid);
+ err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid,
+ src);
break;
case ICMPV6_MLD2_REPORT:
err = br_ip6_multicast_mld2_report(br, port, skb_trimmed, vid);
@@ -1795,7 +1836,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
err = br_ip6_multicast_query(br, port, skb_trimmed, vid);
break;
case ICMPV6_MGM_REDUCTION:
- br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid);
+ src = eth_hdr(skb)->h_source;
+ br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid, src);
break;
}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8ce621e..cc55100 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -177,6 +177,8 @@ struct net_bridge_port_group {
struct timer_list timer;
struct br_ip addr;
unsigned char flags;
+ unsigned char eth_addr[ETH_ALEN];
+ bool unicast;
};
struct net_bridge_mdb_entry
@@ -599,7 +601,7 @@ void br_multicast_free_pg(struct rcu_head *head);
struct net_bridge_port_group *
br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group,
struct net_bridge_port_group __rcu *next,
- unsigned char flags);
+ unsigned char flags, const unsigned char *src);
void br_mdb_init(void);
void br_mdb_uninit(void);
void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 8bd5696..1730278 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -188,6 +188,7 @@ static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
store_multicast_router);
BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
+BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UCAST);
#endif
static const struct brport_attribute *brport_attrs[] = {
@@ -214,6 +215,7 @@ static const struct brport_attribute *brport_attrs[] = {
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
&brport_attr_multicast_router,
&brport_attr_multicast_fast_leave,
+ &brport_attr_multicast_to_unicast,
#endif
&brport_attr_proxyarp,
&brport_attr_proxyarp_wifi,
--
2.10.2
^ permalink raw reply related
* Re: [PATCH V3 2/2] cfg80211: support ieee80211-freq-limit DT property
From: Arend van Spriel @ 2017-01-02 20:12 UTC (permalink / raw)
To: Johannes Berg, Rafał Miłecki, linux-wireless
Cc: Martin Blumenstingl, Felix Fietkau, Arend van Spriel,
Arnd Bergmann, devicetree, Rafał Miłecki
In-Reply-To: <1483379548.15591.1.camel@sipsolutions.net>
On 02-01-17 18:52, Johannes Berg wrote:
>> +static void wiphy_freq_limits_apply(struct wiphy *wiphy)
> [...]
>> + if (!wiphy_freq_limits_valid_chan(wiphy,
>> chan)) {
>> + pr_debug("Disabling freq %d MHz as
>> it's out of OF limits\n",
>> + chan->center_freq);
>> + chan->flags |=
>> IEEE80211_CHAN_DISABLED;
>
> I think you didn't address the problem in the best way now.
>
> The problem with the channel sharing was the way you're applying the
> limits - at runtime. This is now OK since the new function shouldn't be
> called when the channel structs are shared, but hooking it all into thes
> regulatory code is now no longer needed.
>
> What you can do now, when reading the OF data, is actually apply it to
> the channel flags immediately. If done *before* wiphy_register(), these
> flags will be preserved forever, so you no longer need any hooks in
> regulatory code at all - you can just set the original channel flags
> according to the OF data.
I suppose this then can also be done early in the wiphy_register()
function itself, right?
> I think this greatly simplifies the flow, since you can also remove
> wiphy->freq_limits (and n_freq_limits) completely, since now the only
> effect of the function would be to modify the channel list, and later
> regulatory updates would always preserve the flags.
So does it mean the function can go in core.c again :-p If it is likely
there will be other properties being added it might justify adding a new
source file, eg. of.c, and only compile it when CONFIG_OF is set. Just a
thought.
Regards,
Arend
^ permalink raw reply
* Re: pull-request: wireless-drivers-next 2017-01-02
From: David Miller @ 2017-01-02 20:46 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <8760lxk37o.fsf@kamboji.qca.qualcomm.com>
From: Kalle Valo <kvalo@codeaurora.org>
Date: Mon, 02 Jan 2017 15:20:59 +0200
> first pull request for 4.11. The tree is based on 4.9 but that shouldn't
> be a problem, at least my test pull to net-next worked ok. I'll fast
> forward my trees after you have pulled this.
>
> Please let me know if you have any problems.
Happy new year, pulled, thanks!
^ permalink raw reply
* Re: [PATCH V3 2/2] cfg80211: support ieee80211-freq-limit DT property
From: Rafał Miłecki @ 2017-01-02 22:12 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-wireless@vger.kernel.org, Martin Blumenstingl,
Felix Fietkau, Arend van Spriel, Arnd Bergmann,
devicetree@vger.kernel.org, Rafał Miłecki
In-Reply-To: <1483379548.15591.1.camel@sipsolutions.net>
On 2 January 2017 at 18:52, Johannes Berg <johannes@sipsolutions.net> wrote=
:
>> +static void wiphy_freq_limits_apply(struct wiphy *wiphy)
> [...]
>> + if (!wiphy_freq_limits_valid_chan(wiphy,
>> chan)) {
>> + pr_debug("Disabling freq %d MHz as
>> it's out of OF limits\n",
>> + chan->center_freq);
>> + chan->flags |=3D
>> IEEE80211_CHAN_DISABLED;
>
> I think you didn't address the problem in the best way now.
>
> The problem with the channel sharing was the way you're applying the
> limits - at runtime. This is now OK since the new function shouldn't be
> called when the channel structs are shared, but hooking it all into the
> regulatory code is now no longer needed.
>
> What you can do now, when reading the OF data, is actually apply it to
> the channel flags immediately. If done *before* wiphy_register(), these
> flags will be preserved forever, so you no longer need any hooks in
> regulatory code at all - you can just set the original channel flags
> according to the OF data.
>
> I think this greatly simplifies the flow, since you can also remove
> wiphy->freq_limits (and n_freq_limits) completely, since now the only
> effect of the function would be to modify the channel list, and later
> regulatory updates would always preserve the flags.
I need some extra help understanding this :(
When driver uses custom regulatory it registers initial channels at
init but it can also react to regdom changes using reg_notifier. Is
that correct?
So I'm looking at brcmf_cfg80211_reg_notifier which calls
brcmf_setup_wiphybands which calls brcmf_construct_chaninfo.
That last one reworks all channels on every call. It first marks all
existing channels as DISABLED then queries firmware for the list of
supported channels and updates wiphy channels one by one.
So if I understand this correctly, every regdom change can result in
rebuilding channels pretty much from the scratch. That's why I
believed I need to call wiphy_freq_limits_apply on runtime, not just
during the init.
Is there some flow in my understanding?
--=20
Rafa=C5=82
^ permalink raw reply
* Re: [PATCH V3 2/2] cfg80211: support ieee80211-freq-limit DT property
From: Rafał Miłecki @ 2017-01-02 22:16 UTC (permalink / raw)
To: Arend van Spriel
Cc: Johannes Berg, linux-wireless@vger.kernel.org,
Martin Blumenstingl, Felix Fietkau, Arend van Spriel,
Arnd Bergmann, devicetree@vger.kernel.org,
Rafał Miłecki
In-Reply-To: <e194b980-1048-8da6-624b-26f824ff655d@broadcom.com>
On 2 January 2017 at 21:12, Arend van Spriel
<arend.vanspriel@broadcom.com> wrote:
> On 02-01-17 18:52, Johannes Berg wrote:
>>> +static void wiphy_freq_limits_apply(struct wiphy *wiphy)
>> [...]
>>> + if (!wiphy_freq_limits_valid_chan(wiphy,
>>> chan)) {
>>> + pr_debug("Disabling freq %d MHz as
>>> it's out of OF limits\n",
>>> + chan->center_freq);
>>> + chan->flags |=3D
>>> IEEE80211_CHAN_DISABLED;
>>
>> I think you didn't address the problem in the best way now.
>>
>> The problem with the channel sharing was the way you're applying the
>> limits - at runtime. This is now OK since the new function shouldn't be
>> called when the channel structs are shared, but hooking it all into thes
>> regulatory code is now no longer needed.
>>
>> What you can do now, when reading the OF data, is actually apply it to
>> the channel flags immediately. If done *before* wiphy_register(), these
>> flags will be preserved forever, so you no longer need any hooks in
>> regulatory code at all - you can just set the original channel flags
>> according to the OF data.
>
> I suppose this then can also be done early in the wiphy_register()
> function itself, right?
When driver calls wiphy_apply_custom_regulatory I need to already have
limits read from the DT (at least in my current implementation, it may
change, but I need help understanding flow first). As
wiphy_apply_custom_regulatory has to be called before wiphy_register,
I can't read DT so late (in wiphy_register).
--=20
Rafa=C5=82
^ permalink raw reply
* Re: kernel 4.9 iwlwifi startup error
From: Andrew Donnellan @ 2017-01-03 2:42 UTC (permalink / raw)
To: Fabio Coatti, LKML, linux-wireless@vger.kernel.org
In-Reply-To: <2029482.jt8IarKZJs@calvin>
On 02/01/17 21:12, Fabio Coatti wrote:
> Hi all,
> I'm using kernel 4.9 and maybe half of the times I boot my laptop I get the
> error reported below, and the wifi does not work. I have to remove iwlwifi (like
> modprobe -r iwldvm iwlwifi) and insert it again to get things workig again.
> This seems a bit random, it does not happens all the times so it could be a
> timing issue or even a flaky hardware (unlikely, as I see only this issue with
> wifi, once it starts it works just fine)
> I'm pretty sure to have seen the same behaviour at some point in 4.8.X
> release, but right now I lost the related notes.
> Environment:
> Distro: gentoo
> gcc 5.4.0
> HW: Hewlett-Packard HP EliteBook Folio 9470m/18DF, BIOS 68IBD Ver. F.63
> 04/26/2016
> Intel(R) Core(TM) i5-3427U CPU @ 1.80GHz
> Network controller: Intel Corporation Centrino Advanced-N 6235 (rev 24)
>
> Of course if more info is needed, just drop me a note.
>
> I'm not subscribed to mailing lists, so please keep me in CC: for any
> information request.
>
> Many thanks.
I've so far seen this once on my laptop, a Samsung NP540U3C (don't have
it with me right now, so I'm not sure what the wifi chipset is), running
with a Debian 4.9 kernel.
--
Andrew Donnellan OzLabs, ADL Canberra
andrew.donnellan@au1.ibm.com IBM Australia Limited
^ permalink raw reply
* Re: [PATCH] mac80211: Fix invalid 'info' access in xmit-fast.
From: Ben Greear @ 2017-01-03 3:04 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
In-Reply-To: <1483352652.4596.0.camel@sipsolutions.net>
On 01/02/2017 02:24 AM, Johannes Berg wrote:
> On Fri, 2016-12-30 at 10:49 -0800, greearb@candelatech.com wrote:
>> From: Ben Greear <greearb@candelatech.com>
>>
>> ieee80211_xmit_fast assigns info from the passed-in
>> skb, but then later it also checks for skb_shared(skb),
>> and may create a new skb based on that check.
>>
>> But, the code did not re-assign 'info', so it pointed into
>> the old shared skb. This leads to all sorts of problems,
>> most obviously crashes since the new skb's info->hw_queue is not
>> properly initialized.
>>
>> Bug was seen by sending pktgen packets on a bridge that
>> had an AP network interface in it. hw-queue was out of
>> range, which made it crash like this:
>>
>> BUG: unable to handle kernel NULL pointer dereference
>> at (null)
>> IP: [<ffffffffa0ad4672>] ieee80211_tx_frags+0x232/0x4c0 [mac80211]
>> PGD 0
>> Oops: 0002 [#1] PREEMPT SMP
>> CPU: 0 PID: 1512 Comm: kpktgend_0 Tainted: G O 4.7.10+
>> #24
>> Hardware name: To be filled by O.E.M. To be filled by
>> O.E.M./ChiefRiver, BIOS 4.6.5 06/07/2013
>> task: ffff8802132f3a00 ti: ffff8800362ac000 task.ti: ffff8800362ac000
>> RIP: 0010:[<ffffffffa0ad4672>] [<ffffffffa0ad4672>]
>> ieee80211_tx_frags+0x232/0x4c0 [mac80211]
>> RSP: 0018:ffff8800362afa28 EFLAGS: 00010086
>> RAX: ffff8802130a22c0 RBX: ffff8802130a13a0 RCX: ffff880035ef2200
>> RDX: ffff880035ef2200 RSI: 0000000000000292 RDI: 0000000000000000
>> RBP: ffff8800362afa90 R08: 0000000000000000 R09: 0000000000000000
>> R10: 0000000000000088 R11: 0000000000000001 R12: ffff880035ef2200
>> R13: ffff880035dabb90 R14: ffff8800362afb18 R15: 0000000000000cc0
>> FS: 0000000000000000(0000) GS:ffff88021e200000(0000)
>> knlGS:0000000000000000
>> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> CR2: 0000000000000000 CR3: 0000000001e06000 CR4: 00000000001406f0
>> Stack:
>> 0000000000000292 ffff880035daa880 ffff8802130a0b20 ffff8800d4f01808
>> 00ff8800362afaa0 ffff8800362afb18 ffff8802130a13c0 ffff88021e20db68
>> ffff880035daa880 ffff8800362afb18 ffff880035ef2200 ffff88020f6ca300
>> Call Trace:
>> [<ffffffffa0ad9f63>] __ieee80211_subif_start_xmit+0xc13/0xc30
>> [mac80211]
>> [<ffffffff8113d2c5>] ? find_busiest_group+0x35/0x4a0
>> [<ffffffffa0ad9f8b>] ieee80211_subif_start_xmit+0xb/0x10 [mac80211]
>> [<ffffffff8177d40b>] dev_hard_start_xmit+0x9b/0x220
>> [<ffffffff817a3716>] sch_direct_xmit+0xd6/0x1a0
>> [<ffffffff8177da8e>] __dev_queue_xmit+0x3be/0x6c0
>> [<ffffffff81127f43>] ? finish_task_switch+0x73/0x1f0
>> [<ffffffff8177dd9d>] dev_queue_xmit+0xd/0x10
>> [<ffffffffa0b5fe85>] br_dev_queue_push_xmit+0x75/0x140 [bridge]
>> [<ffffffffa0b5ffc9>] br_forward_finish+0x29/0xa0 [bridge]
>> [<ffffffff8116db83>] ? del_timer_sync+0x43/0x50
>> [<ffffffffa0b600a2>] __br_deliver+0x62/0x130 [bridge]
>> [<ffffffff81175937>] ? __getnstimeofday64+0x37/0xd0
>> [<ffffffff811759d9>] ? getnstimeofday64+0x9/0x30
>> [<ffffffffa0b605b6>] br_deliver+0x56/0x60 [bridge]
>> [<ffffffffa0b5d472>] br_dev_xmit+0x1c2/0x250 [bridge]
>> [<ffffffffa137aa1c>] pktgen_thread_worker+0x174c/0x2471 [pktgen]
>> [<ffffffff8185087a>] ? __schedule+0x30a/0x7c0
>> [<ffffffff811446e0>] ? wake_atomic_t_function+0x60/0x60
>> [<ffffffffa13792d0>] ? pktgen_rem_all_ifs+0x80/0x80 [pktgen]
>> [<ffffffff81121c14>] kthread+0xc4/0xe0
>> [<ffffffff818551df>] ret_from_fork+0x1f/0x40
>> [<ffffffff81121b50>] ? kthread_worker_fn+0x180/0x180
>>
>> Fix this by re-assigning info after creating new one.
>>
>> Signed-off-by: Ben Greear <greearb@candelatech.com>
>> ---
>>
>> This patch is against 4.7.10+
>
> And thus didn't apply - I've replaced it with my own patch which I'll
> send out in a moment
Thanks for your patch... It is cleaner than what I originally wrote,
and I was out the door before I thought to re-write it as you did.
FYI, the same patch applies as far back as 4.4...I didn't look at anything older.
Ben
>
> johannes
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [PATCH V2 1/3] cfg80211: allow passing struct device in the wiphy_new call
From: kbuild test robot @ 2017-01-02 22:10 UTC (permalink / raw)
To: Rafał Miłecki
Cc: kbuild-all, Johannes Berg, linux-wireless, Martin Blumenstingl,
Felix Fietkau, Arend van Spriel, Arnd Bergmann, devicetree,
Rafał Miłecki
In-Reply-To: <20170102132747.3491-1-zajec5@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 5168 bytes --]
Hi Rafał,
[auto build test WARNING on mac80211-next/master]
[also build test WARNING on v4.10-rc2 next-20161224]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Rafa-Mi-ecki/cfg80211-allow-passing-struct-device-in-the-wiphy_new-call/20170103-014525
base: https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git master
reproduce: make htmldocs
All warnings (new ones prefixed by >>):
make[3]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
>> include/net/cfg80211.h:3734: warning: No description found for parameter 'dev'
include/net/cfg80211.h:3751: warning: No description found for parameter 'dev'
vim +/dev +3734 include/net/cfg80211.h
3718
3719 /**
3720 * wiphy_new_nm - create a new wiphy for use with cfg80211
3721 *
3722 * @ops: The configuration operations for this device
3723 * @sizeof_priv: The size of the private area to allocate
3724 * @requested_name: Request a particular name.
3725 * NULL is valid value, and means use the default phy%d naming.
3726 *
3727 * Create a new wiphy and associate the given operations with it.
3728 * @sizeof_priv bytes are allocated for private use.
3729 *
3730 * Return: A pointer to the new wiphy. This pointer must be
3731 * assigned to each netdev's ieee80211_ptr for proper operation.
3732 */
3733 struct wiphy *wiphy_new_nm(struct device *dev, const struct cfg80211_ops *ops,
> 3734 int sizeof_priv, const char *requested_name);
3735
3736 /**
3737 * wiphy_new - create a new wiphy for use with cfg80211
3738 *
3739 * @ops: The configuration operations for this device
3740 * @sizeof_priv: The size of the private area to allocate
3741 *
3742 * Create a new wiphy and associate the given operations with it.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 6421 bytes --]
^ 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