* Re: [PATCH v2 01/13] wil6210: add sysfs file for FTM calibration
From: Lior David @ 2017-01-19 12:36 UTC (permalink / raw)
To: Valo, Kalle, qca_merez; +Cc: qca_liord, linux-wireless@vger.kernel.org, wil6210
In-Reply-To: <871svzp79p.fsf@kamboji.qca.qualcomm.com>
On 1/19/2017 2:24 PM, Valo, Kalle wrote:
> Maya Erez <qca_merez@qca.qualcomm.com> writes:
>
>> From: Lior David <qca_liord@qca.qualcomm.com>
>>
>> In fine timing measurements, the calculation is affected by
>> 2 parts: timing of packets over the air, which is platform
>> independent, and platform-specific delays, which are dependent
>> on things like antenna cable length and type.
>> Add a sysfs file which allows to get/set these platform specific
>> delays, separated into the TX and RX components.
>> There are 2 key scenarios where the file can be used:
>> 1. Calibration - start with some initial values (for example,
>> the default values at startup), make measurements at a known
>> distance, then iteratively change the values until the
>> measurement results match the known distance.
>> 2. Adjust the delays when platform starts up, based on known
>> values.
>>
>> Signed-off-by: Lior David <qca_liord@qca.qualcomm.com>
>> Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
>
> Can't this go via nl80211? sysfs is not really supposed to be used for
> something like this.
>
There is no nl80211 API for this (yet?).
Will it be ok to put this in debugfs? Normally this will be in the board
file (as part of RF configuration) but it will be useful to play
with these values for debugging/diagnostics.
Thanks,
Lior
^ permalink raw reply
* Re: [PATCH v2 01/13] wil6210: add sysfs file for FTM calibration
From: Valo, Kalle @ 2017-01-19 12:24 UTC (permalink / raw)
To: qca_merez; +Cc: qca_liord, linux-wireless@vger.kernel.org, wil6210
In-Reply-To: <1484226365-10433-2-git-send-email-qca_merez@qca.qualcomm.com>
Maya Erez <qca_merez@qca.qualcomm.com> writes:
> From: Lior David <qca_liord@qca.qualcomm.com>
>
> In fine timing measurements, the calculation is affected by
> 2 parts: timing of packets over the air, which is platform
> independent, and platform-specific delays, which are dependent
> on things like antenna cable length and type.
> Add a sysfs file which allows to get/set these platform specific
> delays, separated into the TX and RX components.
> There are 2 key scenarios where the file can be used:
> 1. Calibration - start with some initial values (for example,
> the default values at startup), make measurements at a known
> distance, then iteratively change the values until the
> measurement results match the known distance.
> 2. Adjust the delays when platform starts up, based on known
> values.
>
> Signed-off-by: Lior David <qca_liord@qca.qualcomm.com>
> Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
Can't this go via nl80211? sysfs is not really supposed to be used for
something like this.
--=20
Kalle Valo=
^ permalink raw reply
* Re: [PATCH] nl80211: fix validation of scheduled scan info for wowlan netdetect
From: Luca Coelho @ 2017-01-19 12:00 UTC (permalink / raw)
To: Arend van Spriel, Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1484820088-24448-1-git-send-email-arend.vanspriel@broadcom.com>
On Thu, 2017-01-19 at 10:01 +0000, Arend van Spriel wrote:
> For wowlan netdetect a separate limit is defined for the number of
> matchsets. Currently, this limit is ignored and the regular limit
> for scheduled scan matchsets, ie. struct wiphy::max_match_sets, is
> used for the net-detect case as well.
>
> Cc: Luciano Coelho <luciano.coelho@intel.com>
> Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> ---
What?! You don't have the same number of matchsets for both? :P
Looks good.
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
--
Luca.
^ permalink raw reply
* [PATCH] rtlwifi: rtl8192x: Enabling and disabling hardware interrupts after enabling local irq flags
From: Bharat Kumar Gogada @ 2017-01-19 10:14 UTC (permalink / raw)
To: Larry.Finger, chaoming_li, linux-wireless, linux-kernel
Cc: kvalo, netdev, rgummal, Bharat Kumar Gogada
-Realtek 8192CE chipset maintains local irq flags after enabling/disabling
hardware interrupts.
-Hardware interrupts are enabled before enabling the local irq
flags(these flags are being checked in interrupt handler),
leading to race condition on some RP, where the irq line between
bridge and GIC goes high at ASSERT_INTx and goes low only
at DEASSERT_INTx. In this kind of RP by the time ASSERT_INTx is seen
irq_enable flag is still set to false, resulting in continuous
interrupts seen by CPU as DEASSERT_INTx cannot be sent since
flag is still false and making CPU stall.
-Changing the sequence of setting these irq flags.
Signed-off-by: Bharat Kumar Gogada <bharatku@xilinx.com>
---
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
index a47be73..143766c4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
@@ -1306,9 +1306,9 @@ void rtl92ce_enable_interrupt(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ rtlpci->irq_enabled = true;
rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
- rtlpci->irq_enabled = true;
}
void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
@@ -1316,9 +1316,9 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ rtlpci->irq_enabled = false;
rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
- rtlpci->irq_enabled = false;
}
static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
--
2.1.1
^ permalink raw reply related
* [PATCH] nl80211: fix validation of scheduled scan info for wowlan netdetect
From: Arend van Spriel @ 2017-01-19 10:01 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Arend van Spriel, Luciano Coelho
For wowlan netdetect a separate limit is defined for the number of
matchsets. Currently, this limit is ignored and the regular limit
for scheduled scan matchsets, ie. struct wiphy::max_match_sets, is
used for the net-detect case as well.
Cc: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
---
net/wireless/nl80211.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b4e7bdd..df0675d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6852,7 +6852,7 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
static struct cfg80211_sched_scan_request *
nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
- struct nlattr **attrs)
+ struct nlattr **attrs, int max_match_sets)
{
struct cfg80211_sched_scan_request *request;
struct nlattr *attr;
@@ -6917,7 +6917,7 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
n_match_sets = 1;
- if (n_match_sets > wiphy->max_match_sets)
+ if (n_match_sets > max_match_sets)
return ERR_PTR(-EINVAL);
if (attrs[NL80211_ATTR_IE])
@@ -7217,7 +7217,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
return -EINPROGRESS;
sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
- info->attrs);
+ info->attrs,
+ rdev->wiphy.max_match_sets);
err = PTR_ERR_OR_ZERO(sched_scan_req);
if (err)
@@ -10030,7 +10031,8 @@ static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
if (err)
goto out;
- trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb);
+ trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
+ wowlan->max_nd_match_sets);
err = PTR_ERR_OR_ZERO(trig->nd_config);
if (err)
trig->nd_config = NULL;
--
1.9.1
^ permalink raw reply related
* Re: [PATCH net-next v4] bridge: multicast to unicast
From: Nikolay Aleksandrov @ 2017-01-19 9:53 UTC (permalink / raw)
To: Linus Lüssing, netdev
Cc: David S . Miller, Stephen Hemminger, Felix Fietkau, bridge,
linux-kernel, linux-wireless
In-Reply-To: <20170119024510.3284-1-linus.luessing@c0d3.blue>
On 19/01/17 03:45, Linus Lüssing wrote:
> From: Felix Fietkau <nbd@nbd.name>
>
> 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.
>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> [linus.luessing@c0d3.blue: various bug + style fixes, commit message]
> 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.
>
> Changes in v4:
> * readd "From: Felix Fietkau [...]" (missed it again in v3)
>
> Changes in v3:
> * fix an uninitialized variable bug introduced in br_multicast_flood()
> in v2, found by kbuild test bot
>
> Changes in v2:
> * netlink support (thanks Nik!)
> * fixed switching between multicast_to_unicast on/off
> -> even after toggling an already existing entry would
> stale in its mode and would never be replaced
> -> new extra check in br_port_group_equal)
> * reduced checks in br_multicast_flood() from two to one
> to address fast-path concerns (thanks Nik!)
> * rev-christmas tree ordering (thanks Nik!)
> * removed "net_bridge_port_group::unicast", using
> ::flags instead (thanks Nik!)
> * BR_MULTICAST_TO_UCAST -> BR_MULTICAST_TO_UNICAST
> (BR_MULTICAST_FLAST_LEAVE has the same length anyway)
> * simplified maybe_deliver_addr()
> (no return, no "prev" paramater -> was a NOP anyway)
> * added "From: Felix Fietkau [...]"
> * added "Signed-off-by: Felix Fietkau [...]"
> ---
> include/linux/if_bridge.h | 1 +
> include/uapi/linux/if_link.h | 1 +
> net/bridge/br_forward.c | 37 ++++++++++++++++-
> net/bridge/br_mdb.c | 2 +-
> net/bridge/br_multicast.c | 96 ++++++++++++++++++++++++++++++++------------
> net/bridge/br_netlink.c | 5 +++
> net/bridge/br_private.h | 8 ++--
> net/bridge/br_sysfs_if.c | 2 +
> 8 files changed, 121 insertions(+), 31 deletions(-)
>
Looks good to me,
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
^ permalink raw reply
* [PATCH] brcmfmac: drop duplicated core selection from brcmf_pcie_attach
From: Rafał Miłecki @ 2017-01-19 9:51 UTC (permalink / raw)
To: Kalle Valo
Cc: Arend van Spriel, Franky Lin, Hante Meuleman,
Pieter-Paul Giesberts, Franky Lin, linux-wireless,
brcm80211-dev-list.pdl, Rafał Miłecki, Hante Meuleman
From: Rafał Miłecki <rafal@milecki.pl>
It was left after reworking PCIe reset in commit 07fe2e38c7fd
("brcmfmac: Reset PCIE devices after recognition.").
Cc: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 19db8f2..6fae4cf 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -601,7 +601,6 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
{
u32 config;
- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
/* BAR1 window may not be sized properly */
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
--
2.10.1
^ permalink raw reply related
* Re: [3/3] rtlwifi: Enable debug mask to be set from sysfs
From: Kalle Valo @ 2017-01-19 8:57 UTC (permalink / raw)
To: Larry Finger; +Cc: linux-wireless, Ping-Ke Shih
In-Reply-To: <5aefd440-1b6f-1791-d85b-e71464c47620@lwfinger.net>
Larry Finger <Larry.Finger@lwfinger.net> writes:
> On 01/18/2017 08:49 AM, Kalle Valo wrote:
>> Larry Finger <Larry.Finger@lwfinger.net> wrote:
>>> The previous commit changes the debug system to use a mask to select
>>> which components are to be debugged. Now, we add the necessary code
>>> to change the mask from sysfs.
>>>
>>> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
>>> Cc: Ping-Ke Shih <pkshih@realtek.com>
>>
>> There's already a generic sysfs interface to change module parameters in
>> /sys/module/<driver>/parameters, drivers should not have a private interface for
>> that.
>
> Kalle,
>
> I was not aware of that part of sysfs. I will respin the patch as well
> as remove the old code that set the debug level.
Good, thanks. I dropped the whole series now and assume that you will
send v2.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v3] brcmfmac: fix incorrect event channel deduction
From: Kalle Valo @ 2017-01-19 8:48 UTC (permalink / raw)
To: Gavin Li
Cc: Arend Van Spriel, Franky Lin, Hante Meuleman, linux-wireless,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER, Stable,
Gavin Li, Rafał Miłecki
In-Reply-To: <CA+GxvY43AbKOVJFWAxHg1Gku=LD-dveHY8m6=zPPu9qR4+r=Fg@mail.gmail.com>
Gavin Li <gavinli@thegavinli.com> writes:
> I think calling this a performance regression is a bit understated; my
> download speed jumped from 1Mbit/s back up to 40MBit/s after applying
> the patch due to the sheer amount of packets being incorrectly
> processed.
>
> In addition, processing arbitrary data frames as firmware events might
> be a security vulnerability.
You should always mention valuable information like this in the commit
log, don't make us maintainers (and others) guessing the symptoms and
impact.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v3] brcmfmac: fix incorrect event channel deduction
From: Kalle Valo @ 2017-01-19 8:55 UTC (permalink / raw)
To: Gavin Li
Cc: Arend Van Spriel, Franky Lin, Gavin Li, Hante Meuleman,
Rafał Miłecki, Stable, linux-wireless,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
In-Reply-To: <CA+GxvY6ho89L-Ye7MrbtVM=i+Ck8YSH7JaSG1p=WzH5u_Be0_A@mail.gmail.com>
Gavin Li <gavinli@thegavinli.com> writes:
> Should I make a v4 patch with an updated log?
No need, I'll just copy your description of the bug to the commit log
before I commit it.
--
Kalle Valo
^ permalink raw reply
* [PATCH net-next v4] bridge: multicast to unicast
From: Linus Lüssing @ 2017-01-19 2:45 UTC (permalink / raw)
To: netdev
Cc: David S . Miller, Stephen Hemminger, Felix Fietkau,
Nikolay Aleksandrov, bridge, linux-kernel, linux-wireless,
Linus Lüssing
From: Felix Fietkau <nbd@nbd.name>
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.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
[linus.luessing@c0d3.blue: various bug + style fixes, commit message]
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.
Changes in v4:
* readd "From: Felix Fietkau [...]" (missed it again in v3)
Changes in v3:
* fix an uninitialized variable bug introduced in br_multicast_flood()
in v2, found by kbuild test bot
Changes in v2:
* netlink support (thanks Nik!)
* fixed switching between multicast_to_unicast on/off
-> even after toggling an already existing entry would
stale in its mode and would never be replaced
-> new extra check in br_port_group_equal)
* reduced checks in br_multicast_flood() from two to one
to address fast-path concerns (thanks Nik!)
* rev-christmas tree ordering (thanks Nik!)
* removed "net_bridge_port_group::unicast", using
::flags instead (thanks Nik!)
* BR_MULTICAST_TO_UCAST -> BR_MULTICAST_TO_UNICAST
(BR_MULTICAST_FLAST_LEAVE has the same length anyway)
* simplified maybe_deliver_addr()
(no return, no "prev" paramater -> was a NOP anyway)
* added "From: Felix Fietkau [...]"
* added "Signed-off-by: Felix Fietkau [...]"
---
include/linux/if_bridge.h | 1 +
include/uapi/linux/if_link.h | 1 +
net/bridge/br_forward.c | 37 ++++++++++++++++-
net/bridge/br_mdb.c | 2 +-
net/bridge/br_multicast.c | 96 ++++++++++++++++++++++++++++++++------------
net/bridge/br_netlink.c | 5 +++
net/bridge/br_private.h | 8 ++--
net/bridge/br_sysfs_if.c | 2 +
8 files changed, 121 insertions(+), 31 deletions(-)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index c6587c0..debc9d5 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_UNICAST BIT(12)
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6b13e59..4e59565 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -321,6 +321,7 @@ enum {
IFLA_BRPORT_MULTICAST_ROUTER,
IFLA_BRPORT_PAD,
IFLA_BRPORT_MCAST_FLOOD,
+ IFLA_BRPORT_MCAST_TO_UCAST,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 7cb41ae..a6c8a27 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -174,6 +174,29 @@ static struct net_bridge_port *maybe_deliver(
return p;
}
+static void maybe_deliver_addr(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;
+
+ /* Even with hairpin, no soliloquies - prevent breaking IPv6 DAD */
+ if (skb->dev == p->dev && ether_addr_equal(src, addr))
+ return;
+
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb) {
+ dev->stats.tx_dropped++;
+ return;
+ }
+
+ memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
+ __br_forward(p, skb, local_orig);
+}
+
/* 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)
@@ -241,10 +264,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;
+
+ if (p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) {
+ maybe_deliver_addr(lport, skb, p->eth_addr,
+ local_orig);
+ goto delivered;
+ }
+ } else {
+ port = rport;
+ }
prev = maybe_deliver(prev, port, skb, local_orig);
+delivered:
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..b127bb7 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,39 @@ 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_UNICAST) && src) {
+ memcpy(p->eth_addr, src, ETH_ALEN);
+ p->flags |= MDB_PG_FLAGS_MCAST_TO_UCAST;
+ }
+
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->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) !=
+ !(port->flags & BR_MULTICAST_TO_UNICAST))
+ return false;
+
+ if (!(p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST))
+ 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 +788,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 +813,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 +825,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 +844,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 +1113,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 +1154,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 +1176,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 +1228,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 +1548,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 +1573,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 +1604,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 +1655,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 +1671,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 +1694,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
@@ -1712,6 +1752,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const unsigned char *src;
struct igmphdr *ih;
int err;
@@ -1731,13 +1772,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 +1788,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;
}
@@ -1766,6 +1808,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const unsigned char *src;
struct mld_msg *mld;
int err;
@@ -1785,8 +1828,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 +1840,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_netlink.c b/net/bridge/br_netlink.c
index 71c7453..6c087cd 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -123,6 +123,7 @@ static inline size_t br_port_info_size(void)
+ nla_total_size(1) /* IFLA_BRPORT_GUARD */
+ nla_total_size(1) /* IFLA_BRPORT_PROTECT */
+ nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */
+ + nla_total_size(1) /* IFLA_BRPORT_MCAST_TO_UCAST */
+ nla_total_size(1) /* IFLA_BRPORT_LEARNING */
+ nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */
+ nla_total_size(1) /* IFLA_BRPORT_PROXYARP */
@@ -173,6 +174,8 @@ static int br_port_fill_attrs(struct sk_buff *skb,
!!(p->flags & BR_ROOT_BLOCK)) ||
nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE,
!!(p->flags & BR_MULTICAST_FAST_LEAVE)) ||
+ nla_put_u8(skb, IFLA_BRPORT_MCAST_TO_UCAST,
+ !!(p->flags & BR_MULTICAST_TO_UNICAST)) ||
nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) ||
nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
!!(p->flags & BR_FLOOD)) ||
@@ -586,6 +589,7 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
[IFLA_BRPORT_PROXYARP] = { .type = NLA_U8 },
[IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 },
[IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NLA_U8 },
+ [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 },
};
/* Change the state of the port and notify spanning tree */
@@ -636,6 +640,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
+ br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8ce621e..f7db79f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -166,8 +166,9 @@ struct net_bridge_fdb_entry
struct rcu_head rcu;
};
-#define MDB_PG_FLAGS_PERMANENT BIT(0)
-#define MDB_PG_FLAGS_OFFLOAD BIT(1)
+#define MDB_PG_FLAGS_PERMANENT BIT(0)
+#define MDB_PG_FLAGS_OFFLOAD BIT(1)
+#define MDB_PG_FLAGS_MCAST_TO_UCAST BIT(2)
struct net_bridge_port_group {
struct net_bridge_port *port;
@@ -177,6 +178,7 @@ struct net_bridge_port_group {
struct timer_list timer;
struct br_ip addr;
unsigned char flags;
+ unsigned char eth_addr[ETH_ALEN];
};
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..05e8946 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_UNICAST);
#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.1.4
^ permalink raw reply related
* RE: [PATCH v9] Add new mac80211 driver mwlwifi.
From: David Lin @ 2017-01-19 1:22 UTC (permalink / raw)
To: Johannes Berg, Kalle Valo
Cc: linux-wireless@vger.kernel.org, Chor Teck Law, James Lin,
Pete Hsieh
In-Reply-To: <1484126730.23671.5.camel@sipsolutions.net>
PiBKb2hhbm5lcyBCZXJnIFttYWlsdG86am9oYW5uZXNAc2lwc29sdXRpb25zLm5ldF0gd3JvdGU6
DQo+IE9uIFR1ZSwgMjAxNy0wMS0xMCBhdCAwMTozMiArMDAwMCwgRGF2aWQgTGluIHdyb3RlOg0K
PiANCj4gPiA+IFRoZSBvbmx5IHRoaW5nIHRoYXQgcmVhbGx5IHNlZW1zIHF1ZXN0aW9uYWJsZSB0
byBtZSBpcyB0aGUgd2hvbGUNCj4gPiA+IGJlYWNvbiBwYXJzaW5nIChhbmQgYXBwYXJlbnQgcmVi
dWlsZGluZyBpbiBmaXJtd2FyZT8pLiBJdCdzIHZlcnkgb2RkDQo+ID4gPiB0aGF0IHlvdSBjb3Vs
ZCBkbyB0aGF0LCB3aXRoIGEgc29mdG1hYyBkZXZpY2Ugd2hlcmUgYWxsIHRoZQ0KPiA+ID4gYXV0
aGVudGljYXRpb24gYW5kIGFzc29jaWF0aW9uIGlzIGhhbmRsZWQgYnkgaG9zdGFwZCBhbnl3YXks
IGFuZCB5b3UNCj4gPiA+IGNhbid0IHBvc3NpYmx5IHByZXRlbmQgdG8gaGFuZGxlIGV2ZXJ5dGhp
bmcgaG9zdGFwZCBtaWdodCB0aHJvdyBhdA0KPiA+ID4geW91IC0gdGhpcyB3aWxsIG1lYW4gdGhh
dCB5b3UnbGwgaGF2ZSBmZWF0dXJlcyBob3N0YXBkIGFuZCBldmVyeQ0KPiA+ID4gb3RoZXIgbWFj
ODAyMTEgc3VwcG9ydHMgdGhhdCB5b3Ugd2lsbCBzaWxlbnRseSBkcm9wIGFmYWljdCAtIHdoaWNo
DQo+ID4gPiBpcyByYXRoZXIgdW5leHBlY3RlZC4NCj4gPiA+DQo+ID4gPiBGaXJzdCwgeW91J3Jl
IHBhcnNpbmcgdGhlIGRhdGEgb2J0YWluZWQgZnJvbSBob3N0YXBkLCBpbg0KPiA+ID4gbXdsX2Z3
Y21kX3BhcnNlX2JlYWNvbigpLCBhbmQgdGhlbiB5b3Ugc2VuZCB0aGVtIGFsbCB0byB0aGUgZmly
bXdhcmUNCj4gPiA+IGluIG13bF9md2NtZF9zZXRfaWVzKCksIGJ1dCBvbmx5IHRoZSB0aGluZ3Mg
eW91IGFjdHVhbGx5IHVuZGVyc3Rvb2QuDQo+ID4gPiBOZXcgaGlnaGVyLWxldmVsIGZlYXR1cmVz
IHlvdSBkb24ndCB1bmRlcnN0YW5kLCBvciB2ZW5kb3IgYmVhY29uIElFcw0KPiA+ID4gdGhhdCBh
cmVuJ3QgV01NLCB3b3VsZCBiZSBjb21wbGV0ZWx5IGRyb3BwZWQuDQo+ID4gPg0KPiA+ID4gSSdt
IG5vdCB2ZXJ5IGhhcHB5IHdpdGggdGhhdCBiZWhhdmlvdXIuDQo+ID4gPg0KPiA+ID4gV2h5IGRv
ZXMgdGhlIGZpcm13YXJlIHJlcXVpcmUgdGhpcz8gV2h5IG5vdCBqdXN0IHBhY2sgYWxsIElFcyBp
bnRvDQo+ID4gPiB0aGUgcGNtZC0+aWVfbGlzdF9sZW5fcHJvcHJpZXRhcnksIGFuZCBsZWF2ZSBl
dmVyeXRoaW5nIGVsc2UgMD8gT3INCj4gPiA+IC0gaWYgcGVyaGFwcyBmaXJtd2FyZSBmb3Igc29t
ZSByZWFzb24gcmVxdWlyZXMgSFQvVkhUIHRvIGJlIHRyZWF0ZWQNCj4gPiA+IHNwZWNpYWxseSwg
b25seSBwYXJzZSBvdXQgdGhlIG9uZXMgdGhhdCBhcmUgcmVhbGx5IG5lZWRlZCBzcGVjaWFsbHkN
Cj4gPiA+IGFuZCBsZWF2ZSBldmVyeXRoaW5nIGVsc2UgaW4gdGhlIGllX2xpc3RfbGVuX3Byb3By
aWV0YXJ5Pw0KPiA+ID4NCj4gPiA+IEFsc28sIHRoaXMgaXMgZHJvcHBpbmcgYWxsIHRoZSBlbmNy
eXB0aW9uIHN0dWZmIC0gZXZlbiB0aG9zZSBhcmUNCj4gPiA+IGV4dGVuc2libGUgYnR3LCBhbmQg
aG9zdGFwZCBtaWdodCBkbyBzby4gSGF2aW5nIHRoZSBmaXJtd2FyZSByZWJ1aWxkDQo+ID4gPiB0
aG9zZSBvdXQgb2Ygb3V0LW9mLWJhbmQgaW5mb3JtYXRpb24gaXMgdmVyeSB1bmV4cGVjdGVkIGZv
ciBhDQo+ID4gPiBtYWM4MDIxMSBkcml2ZXIuDQo+ID4gPg0KPiA+DQo+ID4gVGhpcyBkcml2ZXIg
anVzdCBleHRyYWN0cyBuZWVkZWQgSUVzIHdoaWNoIGlzIHVzZWQgZm9yIHRoZSBob3N0DQo+ID4g
Y29tbWFuZCBvZiBmaXJtd2FyZS4gSSB0aGluayB3ZSB3aWxsIG5vdCBzdXBwb3J0IG90aGVyIHZl
bmRvciBJRXMuDQo+ID4gQW5kIGlmIG5lZWRlZCwgd2UgY2FuIGFkZCB0aGVtIHRvIHBjbWQtPmll
X2xpc3RfcHJvcHJpZXRhcnkuDQo+IA0KPiBTdXJlLCBJIHNlZSB0aGF0IHlvdSdyZSBkb2luZyB0
aGlzLiBJdCBzdGlsbCBtYWtlcyBubyBzZW5zZSB0aG91Z2gsIHNpbmNlIGFsbA0KPiBtYW5hZ2Vt
ZW50IGZyYW1lcyBhcmUgaGFuZGxlZCBieSBob3N0YXBkIGFueXdheS4gSXQgd291bGQgbWFrZSBz
b21lDQo+IHNlbnNlIGlmIHlvdSBhY3R1YWxseSB3ZXJlIGdvaW5nIHRvIGhhbmRsZSBhc3NvY2lh
dGlvbiBpbiB0aGUgZmlybXdhcmUsIGJ1dCBpdA0KPiBtYWtlcyBubyBzZW5zZSBoZXJlLCBhcyBm
YXIgYXMgSSBjYW4gdGVsbC4NCj4gDQo+IEknbSBub3Qgc3VyZSBob3cgaGFyZCBhIGxpbmUgSSBz
aG91bGQgZHJhdyBoZXJlLCBidXQgSSdsbCB3YXJuIHlvdSBub3cgdGhhdCBJDQo+IHdvbid0IHRh
a2UgdGhpcyBpbnRvIGNvbnNpZGVyYXRpb24gd2hlbiBhZGRpbmcgbmV3IGZlYXR1cmVzIHRvIG1h
YzgwMjExLCBhbmQNCj4gY2VydGFpbmx5IEpvdW5pIHdvbid0IHRha2UgaXQgaW50byBhY2NvdW50
IHdoZW4gYWRkaW5nIG5ldyBmZWF0dXJlcyB0byBob3N0YXBkLA0KPiBzbyB0aGF0IHN1Y2ggbmV3
IGZlYXR1cmVzIHdpbGwgdGhlbiBTSUxFTlRMWSBhbmQgVU5FWFBFQ1RFRExZIChkdWUgdG8NCj4g
bWFjODAyMTEpIG5vdCB3b3JrIHdpdGggeW91ciBkcml2ZXIuDQo+IA0KPiBJIHN0cm9uZ2x5IGFk
dmlzZSB5b3UgdG8gcmVjb25zaWRlciB0aGlzIGFuZCB0cnkgdG8gcGFzcyB0aHJvdWdoIGFsbCB0
aGUgSUVzIHNvDQo+IHRoYXQgbmV3bHkgYWRkZWQgZmVhdHVyZXMgdGhhdCBzaG91bGRuJ3QgcmVx
dWlyZSBmaXJtd2FyZSBpbnRlcmFjdGlvbiAoc2luY2UNCj4gaG9zdGFwZCBpcyBoYW5kbGluZyBh
bGwgdGhlIGFzc29jaWF0aW9uIGhhbmRzaGFrZSBhbmQgSUVzIHRvIGFkdmVydGlzZSB0aGUNCj4g
ZmVhdHVyZSkgd2lsbCBhdXRvbWF0aWNhbGx5IGFuZCBjbGVhbmx5IHdvcmsuDQo+IA0KPiBJZiB5
b3UgcmVhbGx5IGNhbid0IGRvIHRoYXQsIGZvciBzb21lIHJlYXNvbiwgdGhlbiBmb3IgbXkgYmVu
ZWZpdCBhcyB0aGUNCj4gbWFjODAyMTEgbWFpbnRhaW5lciBhbmQgZnV0dXJlIG1haW50YWluZXJz
IG9mIHlvdXIgZHJpdmVyLCBJJ2QgbGlrZSB0byBoYXZlDQo+IGRvY3VtZW50YXRpb24gaW4gdGhl
IGRyaXZlciBhcyB0byB3aHkgdGhlIGZpcm13YXJlIG5lZWRzIHRoZSBkcml2ZXIgdG8gc3BsaXQN
Cj4gdXAgYWxsIHRob3NlIElFcyBhbmQgd2hhdCBpdCBkb2VzIHdpdGggdGhlbS4gQWZ0ZXIgYWxs
LCBhIGNvbW1vbi1zZW5zZSBhbmFseXNpcw0KPiB3b3VsZCBzdWdnZXN0IHRoYXQgdGhlIGZpcm13
YXJlIGhhcyBubyBuZWVkIGZvciBpdCwgc2luY2UgYWxsIGNvbmZpZ3VyYXRpb24NCj4gc2hvdWxk
IGNvbWUgdGhyb3VnaCBvdGhlciBwbGFjZXMgYW5kIGFsbCBJRXMgYXJlIGp1c3QgZm9yIGdvaW5n
IG91dCBvbiB0aGUgYWlyLg0KPiANCg0KLSBUaGUgb2JqZWN0aXZlIGlzIHRvIHVzZSB0aGUgc2Ft
ZSBwcm9kdWN0aW9uIGZpcm13YXJlIGJpbmFyeSBmb3IgYm90aCB0aGUgb3BlbiBzb3VyY2UgYW5k
IHByb3ByaWV0YXJ5IGRyaXZlci4gU2FtZSBpbnRlcmZhY2UgaXMgY3VycmVudGx5IHVzZWQgYnkg
cHJvcHJpZXRhcnkgZHJpdmVyIGZvciBoaXN0b3JpY2FsbHkgcmVhc29uLCB3aGlsZSB0aGUgb3Bl
biBzb3VyY2UgSEFMIGlzIGFkYXB0aW5nIHRvIGl0IGZvciB0aGUgZXhpc3Rpbmcgc2hpcHBpbmcg
cHJvZHVjdC4NCi0gV2Ugd2lsbCBtYWtlIGNoYW5nZXMgYW5kIGNsZWFuIHRoaW5ncyB1cCBpbiBm
dXR1cmUuIEkgd2lsbCBzcGVuZCBlZmZvcnQgdG8gY29udGludWUgaXRzIG1haW50ZW5hbmNlIGFu
ZCBjbGVhbi11cC4NCg0KVGhhbmtzLA0KRGF2aWQNCg0KPiBqb2hhbm5lcw0K
^ permalink raw reply
* [PATCH net-next v3] bridge: multicast to unicast
From: Linus Lüssing @ 2017-01-19 0:23 UTC (permalink / raw)
To: netdev
Cc: David S . Miller, Stephen Hemminger, Felix Fietkau,
Nikolay Aleksandrov, bridge, linux-kernel, linux-wireless,
Linus Lüssing
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.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
[linus.luessing@c0d3.blue: various bug + style fixes, commit message]
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.
Changes in v3:
* fix an uninitialized variable bug introduced in br_multicast_flood()
in v2, found by kbuild test bot
Changes in v2:
* netlink support (thanks Nik!)
* fixed switching between multicast_to_unicast on/off
-> even after toggling an already existing entry would
stale in its mode and would never be replaced
-> new extra check in br_port_group_equal)
* reduced checks in br_multicast_flood() from two to one
to address fast-path concerns (thanks Nik!)
* rev-christmas tree ordering (thanks Nik!)
* removed "net_bridge_port_group::unicast", using
::flags instead (thanks Nik!)
* BR_MULTICAST_TO_UCAST -> BR_MULTICAST_TO_UNICAST
(BR_MULTICAST_FLAST_LEAVE has the same length anyway)
* simplified maybe_deliver_addr()
(no return, no "prev" paramater -> was a NOP anyway)
* added "From: Felix Fietkau [...]"
* added "Signed-off-by: Felix Fietkau [...]"
---
include/linux/if_bridge.h | 1 +
include/uapi/linux/if_link.h | 1 +
net/bridge/br_forward.c | 37 ++++++++++++++++-
net/bridge/br_mdb.c | 2 +-
net/bridge/br_multicast.c | 96 ++++++++++++++++++++++++++++++++------------
net/bridge/br_netlink.c | 5 +++
net/bridge/br_private.h | 8 ++--
net/bridge/br_sysfs_if.c | 2 +
8 files changed, 121 insertions(+), 31 deletions(-)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index c6587c0..debc9d5 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_UNICAST BIT(12)
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6b13e59..4e59565 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -321,6 +321,7 @@ enum {
IFLA_BRPORT_MULTICAST_ROUTER,
IFLA_BRPORT_PAD,
IFLA_BRPORT_MCAST_FLOOD,
+ IFLA_BRPORT_MCAST_TO_UCAST,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 7cb41ae..a6c8a27 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -174,6 +174,29 @@ static struct net_bridge_port *maybe_deliver(
return p;
}
+static void maybe_deliver_addr(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;
+
+ /* Even with hairpin, no soliloquies - prevent breaking IPv6 DAD */
+ if (skb->dev == p->dev && ether_addr_equal(src, addr))
+ return;
+
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb) {
+ dev->stats.tx_dropped++;
+ return;
+ }
+
+ memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
+ __br_forward(p, skb, local_orig);
+}
+
/* 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)
@@ -241,10 +264,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;
+
+ if (p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) {
+ maybe_deliver_addr(lport, skb, p->eth_addr,
+ local_orig);
+ goto delivered;
+ }
+ } else {
+ port = rport;
+ }
prev = maybe_deliver(prev, port, skb, local_orig);
+delivered:
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..b127bb7 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,39 @@ 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_UNICAST) && src) {
+ memcpy(p->eth_addr, src, ETH_ALEN);
+ p->flags |= MDB_PG_FLAGS_MCAST_TO_UCAST;
+ }
+
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->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) !=
+ !(port->flags & BR_MULTICAST_TO_UNICAST))
+ return false;
+
+ if (!(p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST))
+ 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 +788,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 +813,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 +825,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 +844,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 +1113,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 +1154,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 +1176,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 +1228,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 +1548,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 +1573,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 +1604,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 +1655,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 +1671,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 +1694,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
@@ -1712,6 +1752,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const unsigned char *src;
struct igmphdr *ih;
int err;
@@ -1731,13 +1772,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 +1788,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;
}
@@ -1766,6 +1808,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const unsigned char *src;
struct mld_msg *mld;
int err;
@@ -1785,8 +1828,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 +1840,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_netlink.c b/net/bridge/br_netlink.c
index 71c7453..6c087cd 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -123,6 +123,7 @@ static inline size_t br_port_info_size(void)
+ nla_total_size(1) /* IFLA_BRPORT_GUARD */
+ nla_total_size(1) /* IFLA_BRPORT_PROTECT */
+ nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */
+ + nla_total_size(1) /* IFLA_BRPORT_MCAST_TO_UCAST */
+ nla_total_size(1) /* IFLA_BRPORT_LEARNING */
+ nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */
+ nla_total_size(1) /* IFLA_BRPORT_PROXYARP */
@@ -173,6 +174,8 @@ static int br_port_fill_attrs(struct sk_buff *skb,
!!(p->flags & BR_ROOT_BLOCK)) ||
nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE,
!!(p->flags & BR_MULTICAST_FAST_LEAVE)) ||
+ nla_put_u8(skb, IFLA_BRPORT_MCAST_TO_UCAST,
+ !!(p->flags & BR_MULTICAST_TO_UNICAST)) ||
nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) ||
nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
!!(p->flags & BR_FLOOD)) ||
@@ -586,6 +589,7 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
[IFLA_BRPORT_PROXYARP] = { .type = NLA_U8 },
[IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 },
[IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NLA_U8 },
+ [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 },
};
/* Change the state of the port and notify spanning tree */
@@ -636,6 +640,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
+ br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8ce621e..f7db79f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -166,8 +166,9 @@ struct net_bridge_fdb_entry
struct rcu_head rcu;
};
-#define MDB_PG_FLAGS_PERMANENT BIT(0)
-#define MDB_PG_FLAGS_OFFLOAD BIT(1)
+#define MDB_PG_FLAGS_PERMANENT BIT(0)
+#define MDB_PG_FLAGS_OFFLOAD BIT(1)
+#define MDB_PG_FLAGS_MCAST_TO_UCAST BIT(2)
struct net_bridge_port_group {
struct net_bridge_port *port;
@@ -177,6 +178,7 @@ struct net_bridge_port_group {
struct timer_list timer;
struct br_ip addr;
unsigned char flags;
+ unsigned char eth_addr[ETH_ALEN];
};
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..05e8946 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_UNICAST);
#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.1.4
^ permalink raw reply related
* Re: [PATCH v3] brcmfmac: fix incorrect event channel deduction
From: Arend Van Spriel @ 2017-01-18 22:35 UTC (permalink / raw)
To: Gavin Li
Cc: Franky Lin, Hante Meuleman, linux-wireless,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER, Stable,
Gavin Li, Rafał Miłecki
In-Reply-To: <CA+GxvY43AbKOVJFWAxHg1Gku=LD-dveHY8m6=zPPu9qR4+r=Fg@mail.gmail.com>
On 18-1-2017 19:39, Gavin Li wrote:
> I think calling this a performance regression is a bit understated; my
> download speed jumped from 1Mbit/s back up to 40MBit/s after applying
> the patch due to the sheer amount of packets being incorrectly
> processed.
I was merely using your own words although admittedly I left out the
word "major".
> In addition, processing arbitrary data frames as firmware events might
> be a security vulnerability.
True. So I am not saying there is no need to backport it to stable
kernel. I meant there are no reported crashes related to this bug so
there is no need to push it through the current release cycle.
Regards,
Arend
> On Wed, Jan 18, 2017 at 4:38 AM, Arend Van Spriel
> <arend.vanspriel@broadcom.com> wrote:
>> On 18-1-2017 0:24, gavinli@thegavinli.com wrote:
>>> From: Gavin Li <git@thegavinli.com>
>>>
>>> brcmf_sdio_fromevntchan() was being called on the the data frame
>>> rather than the software header, causing some frames to be
>>> mischaracterized as on the event channel rather than the data channel.
>>>
>>> This fixes a major performance regression (due to dropped packets).
>>>
>>> Fixes: c56caa9db8ab ("brcmfmac: screening firmware event packet")
>>
>> Actually would prefer Franky to chime in as well as he made the change
>> and confirm correctness. It was introduced a couple of kernel versions
>> back and only a performance regression so seems ok to let this go in
>> 4.11 for now and backport as needed for stable later.
>>
>> Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
>>> Signed-off-by: Gavin Li <git@thegavinli.com>
>>> Cc: <stable@vger.kernel.org> [4.7+]
>>> ---
>>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>>> index dfb0658713d9..d2219885071f 100644
>>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>>> @@ -1661,7 +1661,7 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
>>> pfirst->len, pfirst->next,
>>> pfirst->prev);
>>> skb_unlink(pfirst, &bus->glom);
>>> - if (brcmf_sdio_fromevntchan(pfirst->data))
>>> + if (brcmf_sdio_fromevntchan(&dptr[SDPCM_HWHDR_LEN]))
>>> brcmf_rx_event(bus->sdiodev->dev, pfirst);
>>> else
>>> brcmf_rx_frame(bus->sdiodev->dev, pfirst,
>>>
^ permalink raw reply
* Re: [PATCH v3 1/2] devicetree: document new marvell-8xxx and pwrseq-sd8787 options
From: Rob Herring @ 2017-01-18 22:02 UTC (permalink / raw)
To: Matt Ranostay; +Cc: linux-wireless, linux-kernel, linux-mmc, devicetree, tony
In-Reply-To: <20170113052937.12538-2-matt@ranostay.consulting>
On Thu, Jan 12, 2017 at 09:29:36PM -0800, Matt Ranostay wrote:
Changelog?
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
> ---
> .../devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt | 14 ++++++++++++++
> .../devicetree/bindings/net/wireless/marvell-8xxx.txt | 7 ++++++-
> 2 files changed, 20 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt
>
> diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt
> new file mode 100644
> index 000000000000..1b658351629b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt
> @@ -0,0 +1,14 @@
> +* Marvell SD8787 power sequence provider
> +
> +Required properties:
> +- compatible: must be "mmc-pwrseq-sd8787".
> +- pwndn-gpio: contains a power down GPIO specifier.
powerdown-gpios
> +- reset-gpio: contains a reset GPIO specifier.
reset-gpios
And state the active state for both.
> +
> +Example:
> +
> + wifi_pwrseq: wifi_pwrseq {
> + compatible = "mmc-pwrseq-sd8787";
> + pwrdn-gpio = <&twl_gpio 0 GPIO_ACTIVE_LOW>;
> + reset-gpio = <&twl_gpio 1 GPIO_ACTIVE_LOW>;
> + }
> diff --git a/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt b/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt
> index 980b16df74c3..0854451ff91d 100644
> --- a/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt
> +++ b/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt
> @@ -1,4 +1,4 @@
> -Marvell 8897/8997 (sd8897/sd8997/pcie8997) SDIO/PCIE devices
> +Marvell 8787/8897/8997 (sd8787/sd8897/sd8997/pcie8997) SDIO/PCIE devices
> ------
>
> This node provides properties for controlling the Marvell SDIO/PCIE wireless device.
> @@ -8,6 +8,7 @@ connects the device to the system.
> Required properties:
>
> - compatible : should be one of the following:
> + * "marvell,sd8787"
> * "marvell,sd8897"
> * "marvell,sd8997"
> * "pci11ab,2b42"
> @@ -34,6 +35,9 @@ Optional properties:
> so that the wifi chip can wakeup host platform under certain condition.
> during system resume, the irq will be disabled to make sure
> unnecessary interrupt is not received.
> + - vmmc-supply: a phandle of a regulator, supplying VCC to the card
> + - mmc-pwrseq: phandle to the MMC power sequence node. See "mmc-pwrseq-*"
> + for documentation of MMC power sequence bindings.
>
> Example:
>
> @@ -46,6 +50,7 @@ so that firmware can wakeup host using this device side pin.
> &mmc3 {
> status = "okay";
> vmmc-supply = <&wlan_en_reg>;
> + mmc-pwrseq = <&wifi_pwrseq>;
> bus-width = <4>;
> cap-power-off-card;
> keep-power-in-suspend;
> --
> 2.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 1/2] devicetree: document vmmc-supply and mmc-pwrseq options
From: Rob Herring @ 2017-01-18 21:59 UTC (permalink / raw)
To: Matt Ranostay; +Cc: linux-wireless, linux-kernel, linux-mmc, devicetree, tony
In-Reply-To: <20170113052218.10534-2-matt@ranostay.consulting>
On Thu, Jan 12, 2017 at 09:22:17PM -0800, Matt Ranostay wrote:
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
> ---
> Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v3] brcmfmac: fix incorrect event channel deduction
From: Gavin Li @ 2017-01-18 18:39 UTC (permalink / raw)
To: Arend Van Spriel
Cc: Franky Lin, Hante Meuleman, linux-wireless,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER, Stable,
Gavin Li, Rafał Miłecki
In-Reply-To: <bab86bb5-7815-e5ea-053d-ed6b18af6677@broadcom.com>
I think calling this a performance regression is a bit understated; my
download speed jumped from 1Mbit/s back up to 40MBit/s after applying
the patch due to the sheer amount of packets being incorrectly
processed.
In addition, processing arbitrary data frames as firmware events might
be a security vulnerability.
On Wed, Jan 18, 2017 at 4:38 AM, Arend Van Spriel
<arend.vanspriel@broadcom.com> wrote:
> On 18-1-2017 0:24, gavinli@thegavinli.com wrote:
>> From: Gavin Li <git@thegavinli.com>
>>
>> brcmf_sdio_fromevntchan() was being called on the the data frame
>> rather than the software header, causing some frames to be
>> mischaracterized as on the event channel rather than the data channel.
>>
>> This fixes a major performance regression (due to dropped packets).
>>
>> Fixes: c56caa9db8ab ("brcmfmac: screening firmware event packet")
>
> Actually would prefer Franky to chime in as well as he made the change
> and confirm correctness. It was introduced a couple of kernel versions
> back and only a performance regression so seems ok to let this go in
> 4.11 for now and backport as needed for stable later.
>
> Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
>> Signed-off-by: Gavin Li <git@thegavinli.com>
>> Cc: <stable@vger.kernel.org> [4.7+]
>> ---
>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>> index dfb0658713d9..d2219885071f 100644
>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>> @@ -1661,7 +1661,7 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
>> pfirst->len, pfirst->next,
>> pfirst->prev);
>> skb_unlink(pfirst, &bus->glom);
>> - if (brcmf_sdio_fromevntchan(pfirst->data))
>> + if (brcmf_sdio_fromevntchan(&dptr[SDPCM_HWHDR_LEN]))
>> brcmf_rx_event(bus->sdiodev->dev, pfirst);
>> else
>> brcmf_rx_frame(bus->sdiodev->dev, pfirst,
>>
^ permalink raw reply
* Re: [3/3] rtlwifi: Enable debug mask to be set from sysfs
From: Larry Finger @ 2017-01-18 16:38 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless, Ping-Ke Shih
In-Reply-To: <20170118144936.91B3E6080C@smtp.codeaurora.org>
On 01/18/2017 08:49 AM, Kalle Valo wrote:
> Larry Finger <Larry.Finger@lwfinger.net> wrote:
>> The previous commit changes the debug system to use a mask to select
>> which components are to be debugged. Now, we add the necessary code
>> to change the mask from sysfs.
>>
>> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
>> Cc: Ping-Ke Shih <pkshih@realtek.com>
>
> There's already a generic sysfs interface to change module parameters in
> /sys/module/<driver>/parameters, drivers should not have a private interface for
> that.
Kalle,
I was not aware of that part of sysfs. I will respin the patch as well as remove
the old code that set the debug level.
Thanks,
Larry
^ permalink raw reply
* Re: [PATCH v2 08/14] rt2x00: rt2800mmio: add a workaround for spurious TX_FIFO_STATUS interrupts
From: Stanislaw Gruszka @ 2017-01-18 15:13 UTC (permalink / raw)
To: Daniel Golle
Cc: linux-wireless, Johannes Berg, roman, michel.stempin, c.mignanti,
evaxige, Kalle Valo, Felix Fietkau, John Crispin, Gabor Juhos
In-Reply-To: <20170118144446.GA22837@redhat.com>
On Wed, Jan 18, 2017 at 03:44:46PM +0100, Stanislaw Gruszka wrote:
> On Mon, Jan 16, 2017 at 04:05:47AM +0100, Daniel Golle wrote:
> > irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
> > {
> > struct rt2x00_dev *rt2x00dev = dev_instance;
> > u32 reg, mask;
> > + u32 txstatus = 0;
> >
> > - /* Read status and ACK all interrupts */
> > + /* Read status */
> > rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®);
> > +
> > + if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
> > + /* Due to unknown reason the hardware generates a
> > + * TX_FIFO_STATUS interrupt before the TX_STA_FIFO
> > + * register contain valid data. Read the TX status
> > + * here to see if we have to process the actual
> > + * request.
> > + */
> > + rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &txstatus);
> > + if (rt2800mmio_txstatus_is_spurious(rt2x00dev, txstatus)) {
> > + /* Remove the TX_FIFO_STATUS bit so it won't be
> > + * processed in this turn. The hardware will
> > + * generate another IRQ for us.
> > + */
> > + rt2x00_set_field32(®,
> > + INT_SOURCE_CSR_TX_FIFO_STATUS, 0);
> > + }
> > + }
> > +
> > + /* ACK interrupts */
> > rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
>
> I think spurious TX_STA_FIFO problem happen because we first ACK
> interrupt and then read in bulk all statuses from TX_STA_FIFO
> register, while hardware generate new interrupt (as previous
> was ACKed), then in new interrupt we have no more statues to
> read.
>
> This is inherently racy situation and first ACK interrupt and
> then read statuses is safer than reverse order which make risk we
> will have pending status and not get interrupt about that.
>
> Hence I think we should not apply this patch.
Actually patch is safe in regard that we first ACK interrupt
and then read all statuses TX_STA_FIFO. We only do not ACK
interrupt if we do not have valid status in TX_STA_FIFO .
However I don't really see point of the patch, we should get
next interrupt when new status will be places in TX_STA_FIFO
regardless we ACK this interrupt or don't and if we don't
ACK we possibly can get series of spurious interrupts.
Stanislaw
^ permalink raw reply
* Re: [PATCH v2 14/14] rt2x00: add support for RT5350 WiSoC
From: Stanislaw Gruszka @ 2017-01-18 14:47 UTC (permalink / raw)
To: Daniel Golle
Cc: linux-wireless, Johannes Berg, roman, michel.stempin, c.mignanti,
evaxige, Kalle Valo, Felix Fietkau, John Crispin, Gabor Juhos
In-Reply-To: <20170117014806.GE1912@makrotopia.org>
On Tue, Jan 17, 2017 at 02:48:07AM +0100, Daniel Golle wrote:
> On Mon, Jan 16, 2017 at 11:17:44AM +0100, Stanislaw Gruszka wrote:
> > On Mon, Jan 16, 2017 at 04:17:58AM +0100, Daniel Golle wrote:
> > > @@ -7131,6 +7236,12 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
> > > rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
> > > rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
> > > rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
> > > + } else if (rt2x00_rt(rt2x00dev, RT5350)) {
> > > + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 1);
> > > + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
> > > + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF3320);
>
> Good catch. This line was probably left over when trying to implement
> support for RT5350 based on adding codepaths to RF3320 which ended up
> messy... As EEPROM_NIC_CONF0_RF_TYPE aparently isn't used anywhere else
> in the code apart from setting rf type which is later on overwritten
> for RT5350 anyway. So no need to set it at all. I suggest to simply
> drop that line.
I'm not sure about that, but overwrite EEPROM_NIC_CONF0_RXPATH
and EEPROM_NIC_CONF0_TXPATH should not be needed as well. EEPROM
should contain proper values.
Stanislaw
^ permalink raw reply
* Re: [3/3] rtlwifi: Enable debug mask to be set from sysfs
From: Kalle Valo @ 2017-01-18 14:49 UTC (permalink / raw)
To: Larry Finger; +Cc: linux-wireless, Larry Finger, Ping-Ke Shih
In-Reply-To: <20170101010706.13234-4-Larry.Finger@lwfinger.net>
Larry Finger <Larry.Finger@lwfinger.net> wrote:
> The previous commit changes the debug system to use a mask to select
> which components are to be debugged. Now, we add the necessary code
> to change the mask from sysfs.
>
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> Cc: Ping-Ke Shih <pkshih@realtek.com>
There's already a generic sysfs interface to change module parameters in
/sys/module/<driver>/parameters, drivers should not have a private interface for
that.
--
https://patchwork.kernel.org/patch/9492849/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH v2 08/14] rt2x00: rt2800mmio: add a workaround for spurious TX_FIFO_STATUS interrupts
From: Stanislaw Gruszka @ 2017-01-18 14:44 UTC (permalink / raw)
To: Daniel Golle
Cc: linux-wireless, Johannes Berg, roman, michel.stempin, c.mignanti,
evaxige, Kalle Valo, Felix Fietkau, John Crispin, Gabor Juhos
In-Reply-To: <20170116030535.GA32238@makrotopia.org>
On Mon, Jan 16, 2017 at 04:05:47AM +0100, Daniel Golle wrote:
> irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
> {
> struct rt2x00_dev *rt2x00dev = dev_instance;
> u32 reg, mask;
> + u32 txstatus = 0;
>
> - /* Read status and ACK all interrupts */
> + /* Read status */
> rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®);
> +
> + if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
> + /* Due to unknown reason the hardware generates a
> + * TX_FIFO_STATUS interrupt before the TX_STA_FIFO
> + * register contain valid data. Read the TX status
> + * here to see if we have to process the actual
> + * request.
> + */
> + rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &txstatus);
> + if (rt2800mmio_txstatus_is_spurious(rt2x00dev, txstatus)) {
> + /* Remove the TX_FIFO_STATUS bit so it won't be
> + * processed in this turn. The hardware will
> + * generate another IRQ for us.
> + */
> + rt2x00_set_field32(®,
> + INT_SOURCE_CSR_TX_FIFO_STATUS, 0);
> + }
> + }
> +
> + /* ACK interrupts */
> rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
I think spurious TX_STA_FIFO problem happen because we first ACK
interrupt and then read in bulk all statuses from TX_STA_FIFO
register, while hardware generate new interrupt (as previous
was ACKed), then in new interrupt we have no more statues to
read.
This is inherently racy situation and first ACK interrupt and
then read statuses is safer than reverse order which make risk we
will have pending status and not get interrupt about that.
Hence I think we should not apply this patch.
Stanislaw
^ permalink raw reply
* Re: [PATCH v2 13/14] rt2x00: rt2800lib: add support for RT3352 with 20MHz crystal
From: Stanislaw Gruszka @ 2017-01-18 14:30 UTC (permalink / raw)
To: Daniel Golle
Cc: linux-wireless, Johannes Berg, roman, michel.stempin, c.mignanti,
evaxige, Kalle Valo, Felix Fietkau, John Crispin, Gabor Juhos
In-Reply-To: <20170116031541.GA32313@makrotopia.org>
On Mon, Jan 16, 2017 at 04:15:56AM +0100, Daniel Golle wrote:
> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
> Signed-off-by: Mathias Kresin <dev@kresin.me>
> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
> ---
> drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 50 +++++++++++++++++++++++++-
> drivers/net/wireless/ralink/rt2x00/rt2x00.h | 2 ++
> 2 files changed, 51 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> index 93c97eade334..cb1457595f05 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> @@ -36,6 +36,7 @@
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/slab.h>
> +#include <linux/clk.h>
>
> #include "rt2x00.h"
> #include "rt2800lib.h"
> @@ -7675,6 +7676,27 @@ static const struct rf_channel rf_vals_5592_xtal40[] = {
> {196, 83, 0, 12, 1},
> };
>
> +/*
> + * RF value list for rt3xxx with Xtal20MHz
> + * Supports: 2.4 GHz (all) (RF3322)
> + */
> +static const struct rf_channel rf_vals_xtal20mhz_3x[] = {
Please locate this values in alphabetical order (i.e. after _3x and
before _5592 ).
> struct hw_mode_spec *spec = &rt2x00dev->spec;
> @@ -7764,7 +7786,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> case RF5390:
> case RF5392:
> spec->num_channels = 14;
> - spec->channels = rf_vals_3x;
> + if (spec->clk_is_20mhz)
> + spec->channels = rf_vals_xtal20mhz_3x;
> + else
> + spec->channels = rf_vals_3x;
> break;
How does vendor drivers recognize xtal (I assume rf_vals_xtal20mhz_3x
values were taken from vendor driver) ? It should be possible to get
clock frequency from device register like is is done on RF5592, without
adding additional clock recognition code. But if such code is needed
I prefer that low level board/platform routines do it and place clock
frequency for rt2x00 in rt2x00dev->dev->platform_data.
Stanislaw
^ permalink raw reply
* Re: [1/1] net: wireless: marvell: fix improper return value
From: Kalle Valo @ 2017-01-18 14:43 UTC (permalink / raw)
To: Pan Bian
Cc: Andreas Kemnade, Johannes Berg, libertas-dev, linux-wireless,
netdev, linux-kernel, Pan Bian
In-Reply-To: <1480760857-4549-1-git-send-email-bianpan2016@163.com>
Pan Bian <bianpan2016@163.com> wrote:
> Function lbs_cmd_802_11_sleep_params() always return 0, even if the call
> to lbs_cmd_with_response() fails. In this case, the parameter @sp will
> keep uninitialized. Because the return value is 0, its caller (say
> lbs_sleepparams_read()) will not detect the error, and will copy the
> uninitialized stack memory to user sapce, resulting in stack information
> leak. To avoid the bug, this patch returns variable ret (which takes
> the return value of lbs_cmd_with_response()) instead of 0.
>
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=188451
>
> Signed-off-by: Pan Bian <bianpan2016@163.com>
The prefix should be "libertas:", I'll fix that.
--
https://patchwork.kernel.org/patch/9459597/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [1/5] ath10k: Remove unused 'buf_len' variable
From: Kalle Valo @ 2017-01-18 14:37 UTC (permalink / raw)
To: Kirtika Ruchandani
Cc: Kalle Valo, Arnd Bergmann, netdev, linux-wireless, Raja Mani,
Michal Kazior
In-Reply-To: <196e46eee00fd3ebb56da1373c36f3dff66f2ae1.1479974100.git.kirtika@chromium.org>
Kirtika Ruchandani <kirtika.ruchandani@gmail.com> wrote:
> Commit 32653cf19554 removed the call to 'skb_trim(skb, buf_len)'
> in ath10k_wmi_event_mgmt_rx(), leaving the buf_len variable set but
> unused. Compiling with W=1 gives the following warning, fix it.
> drivers/net/wireless/ath/ath10k/wmi.c: In function ‘ath10k_wmi_event_mgmt_rx’:
> drivers/net/wireless/ath/ath10k/wmi.c:2280:6: warning: variable ‘buf_len’ set but not used [-Wunused-but-set-variable]
>
> This is a harmless warning, and is only being fixed to reduce the
> noise with W=1 in the kernel.
>
> Fixes: 32653cf19554 ("ath10k: implement intermediate event args")
> Cc: Michal Kazior <michal.kazior@tieto.com>
> Cc: Kalle Valo <kvalo@qca.qualcomm.com>
> Signed-off-by: Kirtika Ruchandani <kirtika@chromium.org>
These patches seem to be corrupted:
Applying: ath10k: Remove unused 'buf_len' variable
fatal: corrupt patch at line 13
error: could not build fake ancestor
Patch failed at 0001 ath10k: Remove unused 'buf_len' variable
When resending please also cc ath10k list:
https://wireless.wiki.kernel.org/en/users/drivers/ath10k/sources#submitting_patches
4 patches set to Changes Requested.
9444973 [1/5] ath10k: Remove unused 'buf_len' variable
9444935 [2/5] ath10k: Remove unused 'num_vdev_stats' variable
9444971 [4/5] ath10k: Removed unused 'dev' in ath10k_ahb_clock_enable()
9444975 [5/5] ath10k: Removed unused 'dev' in ath10k_ahb_resource_init
--
https://patchwork.kernel.org/patch/9444973/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ 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