Netdev List
 help / color / mirror / Atom feed
* Re: bpf memory model. Was: [PATCH v4 bpf-next 1/9] bpf: introduce bpf_spin_lock
From: Alexei Starovoitov @ 2019-01-30  2:32 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Alexei Starovoitov, davem, daniel, jakub.kicinski, netdev,
	kernel-team, mingo, will.deacon, Paul McKenney, jannh
In-Reply-To: <20190129091654.GD28485@hirez.programming.kicks-ass.net>

On Tue, Jan 29, 2019 at 10:16:54AM +0100, Peter Zijlstra wrote:
> On Mon, Jan 28, 2019 at 01:56:24PM -0800, Alexei Starovoitov wrote:
> > On Mon, Jan 28, 2019 at 10:24:08AM +0100, Peter Zijlstra wrote:
> 
> > > Ah, but the loop won't be in the BPF program itself. The BPF program
> > > would only have had the BPF_SPIN_LOCK instruction, the JIT them emits
> > > code similar to queued_spin_lock()/queued_spin_unlock() (or calls to
> > > out-of-line versions of them).
> > 
> > As I said we considered exactly that and such approach has a lot of downsides
> > comparing with the helper approach.
> > Pretty much every time new feature is added we're evaluating whether it
> > should be new instruction or new helper. 99% of the time we go with new helper.
> 
> Ah; it seems I'm confused on helper vs instruction. As in, I've no idea
> what a helper is.

bpf helper is a normal kernel function that can be called from bpf program.
In assembler it's a direct function call.

> > > There isn't anything that mandates the JIT uses the exact same locking
> > > routines the interpreter does, is there?
> > 
> > sure. This bpf_spin_lock() helper can be optimized whichever way the kernel wants.
> > Like bpf_map_lookup_elem() call is _inlined_ by the verifier for certain map types.
> > JITs don't even need to do anything. It looks like function call from bpf prog
> > point of view, but in JITed code it is a sequence of native instructions.
> > 
> > Say tomorrow we find out that bpf_prog->bpf_spin_lock()->queued_spin_lock()
> > takes too much time then we can inline fast path of queued_spin_lock
> > directly into bpf prog and save function call cost.
> 
> OK, so then the JIT can optimize helpers. Would it not make sense to
> have the simple test-and-set spinlock in the generic code and have the
> JITs use arch_spinlock_t where appropriate?

I think that pretty much the same as what I have with qspinlock.
Instead of taking a risk how JIT writers implement bpf_spin_lock optimization
I'm using qspinlock on architectures that are known to support it.
So instead of starting with dumb test-and-set there will be faster
qspinlock from the start on x86, arm64 and few others archs.
Those are the archs we care about the most anyway. Other archs can take
time to optimize it (if optimizations are necessary at all).
In general hacking JITs is much harder and more error prone than
changing core and adding helpers. Hence we avoid touching JITs
as much as possible.
Like map_lookup inlining optimization we do only when JIT is on.
And we do it purely in the generic core. See array_map_gen_lookup().
We generate bpf instructions only to feed them into JITs so they
can replace them with native asm. That is much easier to implement
correctly than if we were doing inlining in every JIT independently.


^ permalink raw reply

* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
From: Callum Sinclair @ 2019-01-30  2:25 UTC (permalink / raw)
  To: davem, kuznet, yoshfuji, nikolay, netdev, linux-kernel; +Cc: Callum Sinclair
In-Reply-To: <20190130022509.25303-1-callum.sinclair@alliedtelesis.co.nz>

Currently the only way to clear the mfc cache was to delete the entries
one by one using the MRT_DEL_MFC socket option or to destroy and
recreate the socket.

Create a new socket option which will clear the multicast forwarding
cache on the socket without destroying the socket.

Signed-off-by: Callum Sinclair <callum.sinclair@alliedtelesis.co.nz>
---
 include/uapi/linux/mroute.h  |  3 ++-
 include/uapi/linux/mroute6.h |  3 ++-
 net/ipv4/ipmr.c              | 41 +++++++++++++++++++++-----------
 net/ipv6/ip6mr.c             | 45 +++++++++++++++++++++++-------------
 4 files changed, 60 insertions(+), 32 deletions(-)

diff --git a/include/uapi/linux/mroute.h b/include/uapi/linux/mroute.h
index 5d37a9ccce63..8a0beb885cd9 100644
--- a/include/uapi/linux/mroute.h
+++ b/include/uapi/linux/mroute.h
@@ -28,7 +28,8 @@
 #define MRT_TABLE	(MRT_BASE+9)	/* Specify mroute table ID		*/
 #define MRT_ADD_MFC_PROXY	(MRT_BASE+10)	/* Add a (*,*|G) mfc entry	*/
 #define MRT_DEL_MFC_PROXY	(MRT_BASE+11)	/* Del a (*,*|G) mfc entry	*/
-#define MRT_MAX		(MRT_BASE+11)
+#define MRT_DEL_MFC_ALL		(MRT_BASE+12)	/* Del all multicast entries	*/
+#define MRT_MAX		(MRT_BASE+12)
 
 #define SIOCGETVIFCNT	SIOCPROTOPRIVATE	/* IP protocol privates */
 #define SIOCGETSGCNT	(SIOCPROTOPRIVATE+1)
diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h
index 9999cc006390..7def70cdf571 100644
--- a/include/uapi/linux/mroute6.h
+++ b/include/uapi/linux/mroute6.h
@@ -31,7 +31,8 @@
 #define MRT6_TABLE	(MRT6_BASE+9)	/* Specify mroute table ID		*/
 #define MRT6_ADD_MFC_PROXY	(MRT6_BASE+10)	/* Add a (*,*|G) mfc entry	*/
 #define MRT6_DEL_MFC_PROXY	(MRT6_BASE+11)	/* Del a (*,*|G) mfc entry	*/
-#define MRT6_MAX	(MRT6_BASE+11)
+#define MRT6_DEL_MFC_ALL	(MRT6_BASE+12)	/* Del all multicast entries	*/
+#define MRT6_MAX	(MRT6_BASE+12)
 
 #define SIOCGETMIFCNT_IN6	SIOCPROTOPRIVATE	/* IP protocol privates */
 #define SIOCGETSGCNT_IN6	(SIOCPROTOPRIVATE+1)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ddbf8c9a1abb..bbbce5ec8a0c 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1298,22 +1298,10 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
 	return 0;
 }
 
-/* Close the multicast socket, and clear the vif tables etc */
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+/* Clear the vif tables */
+static void mroute_clean_cache(struct mr_table *mrt, bool all)
 {
-	struct net *net = read_pnet(&mrt->net);
 	struct mr_mfc *c, *tmp;
-	struct mfc_cache *cache;
-	LIST_HEAD(list);
-	int i;
-
-	/* Shut down all active vif entries */
-	for (i = 0; i < mrt->maxvif; i++) {
-		if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
-			continue;
-		vif_delete(mrt, i, 0, &list);
-	}
-	unregister_netdevice_many(&list);
 
 	/* Wipe the cache */
 	list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
@@ -1340,6 +1328,24 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
 	}
 }
 
+/* Close the multicast socket, and clear the vif tables etc */
+static void mroute_clean_tables(struct mr_table *mrt, bool all)
+{
+	struct net *net = read_pnet(&mrt->net);
+	LIST_HEAD(list);
+	int i;
+
+	/* Shut down all active vif entries */
+	for (i = 0; i < mrt->maxvif; i++) {
+		if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+			continue;
+		vif_delete(mrt, i, 0, &list);
+	}
+	unregister_netdevice_many(&list);
+
+	mroute_clean_cache (mrt, all);
+}
+
 /* called from ip_ra_control(), before an RCU grace period,
  * we dont need to call synchronize_rcu() here
  */
@@ -1482,6 +1488,13 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
 					   sk == rtnl_dereference(mrt->mroute_sk),
 					   parent);
 		break;
+	case MRT_DEL_MFC_ALL:
+		rtnl_lock();
+		ipmr_for_each_table(mrt, net) {
+			mroute_clean_cache(mrt, true);
+		}
+		rtnl_unlock();
+		break;
 	/* Control PIM assert. */
 	case MRT_ASSERT:
 		if (optlen != sizeof(val)) {
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 30337b38274b..64631f85dcf4 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1492,25 +1492,11 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
 	return 0;
 }
 
-/*
- *	Close the multicast socket, and clear the vif tables etc
- */
-
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+/* Clear the vif tables */
+static void mroute_clean_cache(struct mr_table *mrt, bool all)
 {
 	struct mr_mfc *c, *tmp;
-	LIST_HEAD(list);
-	int i;
-
-	/* Shut down all active vif entries */
-	for (i = 0; i < mrt->maxvif; i++) {
-		if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
-			continue;
-		mif6_delete(mrt, i, 0, &list);
-	}
-	unregister_netdevice_many(&list);
 
-	/* Wipe the cache */
 	list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
 		if (!all && (c->mfc_flags & MFC_STATIC))
 			continue;
@@ -1535,6 +1521,26 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
 		spin_unlock_bh(&mfc_unres_lock);
 	}
 }
+/*
+ *	Close the multicast socket, and clear the vif tables etc
+ */
+
+static void mroute_clean_tables(struct mr_table *mrt, bool all)
+{
+	LIST_HEAD(list);
+	int i;
+
+	/* Shut down all active vif entries */
+	for (i = 0; i < mrt->maxvif; i++) {
+		if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+			continue;
+		mif6_delete(mrt, i, 0, &list);
+	}
+	unregister_netdevice_many(&list);
+
+	/* Wipe the cache */
+	mroute_clean_cache(mrt, all);
+}
 
 static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
 {
@@ -1703,6 +1709,13 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
 					    parent);
 		rtnl_unlock();
 		return ret;
+	case MRT6_DEL_MFC_ALL:
+		rtnl_lock();
+		ip6mr_for_each_table(mrt, net) {
+			mroute_clean_cache(mrt, true);
+		}
+		rtnl_unlock();
+		return 0;
 
 	/*
 	 *	Control PIM assert (to activate pim will activate assert)
-- 
2.20.1


^ permalink raw reply related

* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
From: Callum Sinclair @ 2019-01-30  2:25 UTC (permalink / raw)
  To: davem, kuznet, yoshfuji, nikolay, netdev, linux-kernel; +Cc: Callum Sinclair

Created a way to clear the multicast forwarding cache on a socket
without having to either remove the entries manually using the delete
entry socket option or destroy and recreate the multicast socket.

Callum Sinclair (1):
  ipmr: ip6mr: Create new sockopt to clear mfc cache only

 include/uapi/linux/mroute.h  |  3 ++-
 include/uapi/linux/mroute6.h |  3 ++-
 net/ipv4/ipmr.c              | 41 +++++++++++++++++++++-----------
 net/ipv6/ip6mr.c             | 45 +++++++++++++++++++++++-------------
 4 files changed, 60 insertions(+), 32 deletions(-)

-- 
2.20.1


^ permalink raw reply

* Are your photos ready for retouching?
From: Mindy @ 2019-01-29 10:46 UTC (permalink / raw)
  To: netdev

Are your photos ready for retouching? We are waiting to start working for
you soon.

No matter making white background or adding path to your pictures, we can
do it quickly for you.

We can do test on your current photos, please send some to start.

Thanks,
Mindy


^ permalink raw reply

* Re: [PATCH v4 bpf-next 1/9] bpf: introduce bpf_spin_lock
From: Alexei Starovoitov @ 2019-01-30  2:20 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Alexei Starovoitov, davem, daniel, jakub.kicinski, netdev,
	kernel-team, mingo, will.deacon, Paul McKenney, jannh
In-Reply-To: <20190129085903.GC28485@hirez.programming.kicks-ass.net>

On Tue, Jan 29, 2019 at 09:59:03AM +0100, Peter Zijlstra wrote:
> On Mon, Jan 28, 2019 at 01:37:12PM -0800, Alexei Starovoitov wrote:
> > On Mon, Jan 28, 2019 at 09:43:10AM +0100, Peter Zijlstra wrote:
> 
> > > Isn't that still broken? AFAIU networking progs can happen in task
> > > context (TX) and SoftIRQ context (RX), which can nest.
> > 
> > Sure. sendmsg side of networking can be interrupted by napi receive.
> > Both can have bpf progs attached at different points, but napi won't run
> > when bpf prog is running, because bpf prog disables preemption.
> 
> Disabling preemption is not sufficient, it needs to have done
> local_bh_disable(), which isn't unlikely given this is all networking
> code.

right. excellent point. Since bh is not disabled nesting of the sender side
socket filter is possible with receive side socket filter.
Theoretically the same socket filter prog can be nested.
I believe it's fine with the current state of things including
parrallel access to bpf maps
(my patch to add preempt_disable around socket filter is still needed).
But this point regarding local_bh_disable changes the plans for bpf_spin_lock.
We'd need local_bh_disable around socket filters and around syscall access
to map with 'struct bpf_spin_lock' or two new helpers bpf_spin_lock_irqsave
and corresponding verifier support.
I guess we'll argue about best option when that time comes.
For now there will be no bpf_spin_lock in socket filters and I need to
add local_bh_disable for syscall access to maps with bpf_spin_lock
to avoid deadlock.
I'll send a set of fixes for lockdep false positives and
respin bpf_spin_lock set.


^ permalink raw reply

* Re: [RFC PATCH 0/3] RV64G eBPF JIT
From: Palmer Dabbelt @ 2019-01-30  2:02 UTC (permalink / raw)
  To: bjorn.topel; +Cc: linux-riscv, bjorn.topel, daniel, davidlee, netdev
In-Reply-To: <20190115083518.10149-1-bjorn.topel@gmail.com>

On Tue, 15 Jan 2019 00:35:15 PST (-0800), bjorn.topel@gmail.com wrote:
> Hi!
>
> I've been hacking on a RV64G eBPF JIT compiler, and would like some
> feedback.
>
> Codewise, it needs some refactoring. Currently there's a bit too much
> copy-and-paste going on, and I know some places where I could optimize
> the code generation a bit (mostly BPF_K type of instructions, dealing
> with immediates).
>
> From a features perspective, two things are missing:
>
> * tail calls
> * "far-branches", i.e. conditional branches that reach beyond 13b.
>
> The test_bpf.ko (only tested on 4.20!) passes all tests.
>
> I've done all the tests on QEMU (version 3.1.50), so no real hardware.
>
> Some questions/observations:
>
> * I've added "HAVE_EFFICIENT_UNALIGNED_ACCESS" to
>   arch/riscv/Kconfig. Is this assumption correct?
>
> * emit_imm() just relies on lui, adds and shifts. No fancy xori cost
>   optimizations like GCC does.
>
> * Suggestions on how to implement the tail call, given that the
>   prologue/epilogue has variable size. I will dig into the details of
>   mips/arm64/x86. :-)
>
> Next steps (prior patch proper) is cleaning up the code, add tail
> calls, and making sure that bpftool disassembly works correctly.
>
> All input are welcome. This is my first RISC-V hack, so I sure there
> are a lot things to improve!
>
>
> Thanks,
> Björn
>
>
> Björn Töpel (3):
>   riscv: set HAVE_EFFICIENT_UNALIGNED_ACCESS
>   riscv: add build infra for JIT compiler
>   bpf, riscv: added eBPF JIT for RV64G
>
>  arch/riscv/Kconfig            |    2 +
>  arch/riscv/Makefile           |    4 +
>  arch/riscv/net/Makefile       |    5 +
>  arch/riscv/net/bpf_jit_comp.c | 1612 +++++++++++++++++++++++++++++++++
>  4 files changed, 1623 insertions(+)
>  create mode 100644 arch/riscv/net/Makefile
>  create mode 100644 arch/riscv/net/bpf_jit_comp.c

Thanks for doing this.  I saw a few reviews go by and I'm behind on email, so 
I'm going to drop this until a v2.

^ permalink raw reply

* Re: ethtool - manual changes in ethtool-copy.h
From: Maciej Żenczykowski @ 2019-01-30  1:57 UTC (permalink / raw)
  To: John W. Linville; +Cc: Michal Kubecek, Linux NetDev
In-Reply-To: <20190129204749.GD11815@tuxdriver.com>

On Tue, Jan 29, 2019 at 1:00 PM John W. Linville <linville@tuxdriver.com> wrote:
>
> On Tue, Jan 29, 2019 at 09:28:42PM +0100, Michal Kubecek wrote:
> > Hello,
> >
> > I'm sorry I didn't notice earlier but ethtool commit 4df55c81996d
> > ("ethtool: change to new sane powerpc64 kernel headers") adds changes to
> > ethtool-copy.h which are not in sync with kernel file it is generated
> > from.
> >
> > This file is supposed to be a copy of the sanitized kernel UAPI header,
> > i.e. what you get as include/linux/ethtool.h by "make headers_install"
> > in kernel tree. (The copy in ethtool git is currently a bit behind but
> > the missing recent changes only modify comments so that it's not really
> > a problem.)
> >
> > Modifying this file manually would mean that anyone who would update it
> > in the future (to sync with kernel changes) could not simply copy the
> > sanitized kernel header but would have to make sure to add your fragment
> > to it.
> >
> > As you only need to define the __SANE_USERSPACE_TYPES__ macro (on
> > ppc64), it might be possible to achieve the same goal in Makefile.
> >
> > Michal Kubecek
>
> Ooops -- thanks for noticing that Michal!
>
> Maciej, how soon might you be able to address this? What is the effect
> of simply reverting it? Just warnings on ppc64 builds?

Would this change be acceptable in the kernel header file this is
generated from?
Or would it mess something up?  I imagine it would be a problem... for
other users?
If so then could we just set this in ethtool Makefile... perhaps even
just blindly for all archs?

^ permalink raw reply

* Re: [RFC net-next 1/4] net: Reserve protocol identifiers for EnOcean
From: Andreas Färber @ 2019-01-30  1:42 UTC (permalink / raw)
  To: Alexander Aring
  Cc: linux-lpwan, linux-wpan, Alexander Aring, Stefan Schmidt, netdev,
	linux-kernel, support, Jonathan Cameron, Rob Herring
In-Reply-To: <20190129125708.plsbgcpcwhtezgo5@x220t>

Hi Alex,

Am 29.01.19 um 13:57 schrieb Alexander Aring:
> On Tue, Jan 29, 2019 at 06:01:27AM +0100, Andreas Färber wrote:
>> EnOcean wireless technology is based on ASK (ERP1) and FSK (ERP2) modulations
>> for sub-GHz and on IEEE 802.15.4 for 2.4 GHz.
>>
> 
> I am not sure what you try to do here. If I see that correctly you
> want to add for some special protocol vendor specific transceiver which
> is underneath an 802.15.4 transceiver a new ARPHRD type and even more
> for each modulation what it supports?

No. EnOcean uses a 4-byte node ID across PHY layers, which I am using a
single ARPHRD_ENOCEAN for (which you conveniently cut off above).

As indicated above, the 868 MHz transceiver is _not_ using 802.15.4 PHY
or MAC to my knowledge. It does sound like you spotted "IEEE 802.15.4"
and literally blended out all the rest...

> 
> If it's a 802.15.4 transceiver why not using the 802.15.4 subsystem?
> 
> For me it sounds more like a HardMAC transceiver driver for doing the
> vendor protocol. The different modulations is part of a 802.15.4 phy
> device class. Similar like in wireless.

I've tried to design this exactly so that one _could_ implement it based
on 802.15.4 PHY framework for 2.4 GHz or based on an FSK PHY for sub-GHz
as a soft-MAC, layered similarly to LoRaWAN vs. LoRa, alongside the ESP
serdev driver in this series.

In ESP3 the only 802.15.4 specific operations are getting/setting the
channel (COMMAND_2_4 packet type), and there's a CO_GET_FREQUENCY_INFO
command to discover frequency and protocol, with 802.15.4 having a
different ID than ERP2 (and I spot a value 0x30 for "Long Range" :-)).
So in theory it might be possible to instantiate an 802.15.4 PHY after
discovering that ESP3 value, but neither is this a generic 802.15.4 PHY
nor a generic FSK PHY, and none of that relates to above ARPHRD really.

PF_PACKET with SOCK_DGRAM for ETH_P_ERP2 gives me the subtelegram
contents to transmit via ESP, whereas SOCK_RAW would give the full frame
to transmit via FSK PHY. By avoiding a custom PF_ENOCEAN we seem to lose
the ability to prepend any protocol headers on the skb for SOCK_DGRAM.

Did you actually read my P.S. in the cover letter? I was glad to avoid
much PF_ socket boilerplate code here (as a playground for LoRa), and
now you're complaining about a single ARPHRD constant! :-/
By that standard we could stop implementing anything new... If you're
worried about number space, why has no one commented on the values added
for LoRa and other previous wireless technologies? No one had any such
comments on my LoRa RFC, nor on Jian-Hong's LoRaWAN patches, so I've
been reserving new ARPHRD_ constants for each technology I work on. If
ARPHRD_NONE would be a better value to use for PHY layers, no one
bothered to point it out so far! Nor did anyone suggest to Jian-Hong to
reuse ARPHRD_EUI64! And yet I spot nothing more suitable for EnOcean
addresses than a custom value. Fact is, the net_device wants some value.
Note that you have two ARPHRD constants assigned for 802.15.4 alone, so
please be fair to others.

An 802.15.4 PHY won't help me for 868 MHz FSK - by my reading 802.15.4
is PSK (BPSK/OQPSK), thus incompatible with ASK/OOK and FSK/MSK.

As noted in the cover letter, Semtech chips have FSK and OOK support
alongside LoRa modulation; so I am looking into FSK PHY support, both
for those chips as well as for some pure FSK/OOK transceivers posted to
linux-lpwan list (and potentially more, given time):
https://lists.infradead.org/pipermail/linux-lpwan/2019-January/000116.html
https://lists.infradead.org/pipermail/linux-lpwan/2019-January/000117.html
https://en.opensuse.org/User:A_faerber/LoRa_interop

Therefore an FSK PHY's netlink interface will need to be able to handle
the requirements of upper-layer protocols, such as:
* Wireless M-Bus (which I could not yet find a suitable 868MHz hard-MAC
for to test against, only 169MHz; Si4432 has an Application Note AN451),
* KNX RF (which I have not come across a hard-MAC for either),
* Sigfox downstream (cf. mm002 LoRa driver as hard-MAC; no public docs),
* Z-Wave (not enough docs to implement much more for now), and here
* EnOcean Radio Protocol 2.

In general I want to make sure my implementations can work with both
soft- and hard-MAC hardware out there, as demonstrated for LoRaWAN.
Pointing a user with hard-MAC device to a theoretical generic subsystem
of your preference doesn't help them, nor does it help to split the
community into separate hard-MAC vs. soft-MAC implementation camps that
make it hard for users to switch.
* For example, when looking for how to actually use the Pine64 Z-Wave
adapter, back in the day I merely found an OpenHAB Raspbian(?) image
that as an openSUSE contributor I would surely not block my board with;
no explanations, no instructions, nothing. And when you have a pure Java
application on the one hand and a C/Python/whatever application on the
other, chances are that the kernel is the only common point of reuse. I
surely mentioned that I hate any userspace applications that attempt to
detect hardware on spidev/i2c-dev/tty without using the kernel-provided
facilities such as DT; finally, serdev allows to move any such
hardware-dependent tty code into the kernel - we just need to figure out
how to best expose functionality there (and ideally grow some more
helpers). Just note how patch 3/4 reuses the kernel's crc8
implementation instead of re-implementing it from scratch. Similarly I'd
love for my AT based LoRa drivers to share more serdev code, despite
line ending and response styles differing greatly (think
serdev_device_readline w/args?); binary protocols like ESP here are
luckily not affected as much. It could also use some more/better
documentation, some of the return values are wrong.
* As another example, we seem to be lacking a generic SDR subsystem:
People with SDR hardware seem to use either downstream kernel modules,
possibly application-generated, or closed-source userspace libraries?
Neither seems able to currently reuse the net subsystem for protocols.
And yet I've been asked repeatedly to design drivers in a way they could
be used with SDR, too, but without any way to actually test that today.
Has anyone talked to the SDR chipset/equipment vendors to remedy that?
The one I was in contact with simply chose not to reply again to date...

For ETH_P_ we seem to be far away from 0xffff, so I don't see a problem
there? Not just was it the easiest thing to implement & test short-term,
but as outlined in the cover letter I saw no way here to turn that into
a non-net-subsystem because the data transmitted is not self-describing
(mostly battery-less sensors/actuators with ca. 4 byte data payload).
You must know that your device with id 0x12345678 conforms to profile X.

Is describing remote devices in DT an option? (CC'ing Rob and Jonathan)

/.../uart@foo {
	enocean {
		compatible = "enocean,esp3";
		#address-cells = <1>;
		#size-cells = <0>;

		window-handle@41424344 {
			compatible = "manufacturer1,handle";
			reg = <0x41424344>;
			enocean,equipment-profile = <1 2 3>;
			#io-channel-cells = <1>;
		};

		light-switch@41424348 {
			compatible = "manufacturer2,rocker";
			reg = <0x41424348>;
			enocean,equipment-profile = <4 5 6>;
			#io-channel-cells = <2>;
		};
	};
};

Pro: This would allow to abstract sensors (iio?) and actuators (gpio?).
     Cf. https://patchwork.ozlabs.org/patch/1028209/ for comparison.
Con: How to deal with it on ACPI or on DT platforms without Overlays?
     How would the kernel preserve remote device state across reboots?

So no, I don't think we can or should shoehorn non-802.15.4 PHYs into
your ieee802154 PHY layer. If you see ways to share code between the
various wireless PHYs, that would be great, but at present it seems like
mostly boilerplate code with nothing in your phy struct applying to FSK
or LoRa. Compare my cfglora series pointed to and Xue Liu's recent sysfs
patch under discussion. If no more comments turn up on my cfglora series
I'll copy it into a cfgfsk, so that I can integrate both into sx127x as
a base for further discussions at Netdevconf. Thanks.

Regards,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)

^ permalink raw reply

* Re: [PATCH net] vhost: fix OOB in get_rx_bufs()
From: Michael S. Tsirkin @ 2019-01-30  1:36 UTC (permalink / raw)
  To: David Miller
  Cc: jasowang, stefanha, kvm, virtualization, netdev, linux-kernel
In-Reply-To: <20190129.153810.493942539151548676.davem@davemloft.net>

On Tue, Jan 29, 2019 at 03:38:10PM -0800, David Miller wrote:
> From: David Miller <davem@davemloft.net>
> Date: Tue, 29 Jan 2019 15:10:26 -0800 (PST)
> 
> > Yeah the CVE pushed my hand a little bit, and I knew I was going to
> > send Linus a pull request today because David Watson needs some TLS
> > changes in net-next.
> 
> I also want to make a general comment.... for the record.
> 
> If I let patches slip consistently past 24 hours my backlog is
> unmanageable.  Even with aggressively applying things quickly I'm
> right now at 70-75.  If I do not do what I am doing, then it's in the
> 100-150 range.
> 
> So I am at the point where I often must move forward with patches that
> I think I personally can verify and vet on my own.

If it helps I can include most virtio stuff in my pull requests instead.
Or if that can't work since there's too often a dependency on net-next,
maybe Jason wants to create a tree and send pull requests to you.  Let
us know if that will help, and which of the options looks better from
your POV.

-- 
MST

^ permalink raw reply

* Re: [PATCH] rtlwifi: remove set but not used variable 'cmd_seq'
From: Pkshih @ 2019-01-30  1:31 UTC (permalink / raw)
  To: yuehaibing@huawei.com, kvalo@codeaurora.org
  Cc: linux-wireless@vger.kernel.org, netdev@vger.kernel.org
In-Reply-To: <e37bae9c-c920-56cf-7813-0004c017f02a@huawei.com>

On Tue, 2019-01-29 at 14:03 +0800, YueHaibing wrote:
> +cc netdev@vger.kernel.org
> 
> On 2019/1/29 13:57, YueHaibing wrote:
> > ping...
> > 
> > On 2018/9/11 20:12, YueHaibing wrote:
> >> Fixes gcc '-Wunused-but-set-variable' warning:
> >>
> >> drivers/net/wireless/realtek/rtlwifi/base.c: In function
> 'rtl_c2h_content_parsing':
> >> drivers/net/wireless/realtek/rtlwifi/base.c:2313:13: warning:
> >>  variable 'cmd_seq' set but not used [-Wunused-but-set-variable]
> >>
> >> Signed-off-by: YueHaibing <yuehaibing@huawei.com>

Thanks for your fix.

Acked-by: Ping-Ke Shih <pkshih@realtek.com>


> >> ---
> >>  drivers/net/wireless/realtek/rtlwifi/base.c | 3 +--
> >>  1 file changed, 1 insertion(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c
> b/drivers/net/wireless/realtek/rtlwifi/base.c
> >> index f4122c8..92b6918 100644
> >> --- a/drivers/net/wireless/realtek/rtlwifi/base.c
> >> +++ b/drivers/net/wireless/realtek/rtlwifi/base.c
> >> @@ -2310,11 +2310,10 @@ static void rtl_c2h_content_parsing(struct
> ieee80211_hw *hw,
> >>  	struct rtl_priv *rtlpriv = rtl_priv(hw);
> >>  	struct rtl_hal_ops *hal_ops = rtlpriv->cfg->ops;
> >>  	const struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
> >> -	u8 cmd_id, cmd_seq, cmd_len;
> >> +	u8 cmd_id, cmd_len;
> >>  	u8 *cmd_buf = NULL;
> >>  
> >>  	cmd_id = GET_C2H_CMD_ID(skb->data);
> >> -	cmd_seq = GET_C2H_SEQ(skb->data);
> >>  	cmd_len = skb->len - C2H_DATA_OFFSET;
> >>  	cmd_buf = GET_C2H_DATA_PTR(skb->data);
> >>
> >>
> >> .
> 




^ permalink raw reply

* Re: [PATCH] ath10k: snoc: remove set but not used variable 'ar_snoc'
From: YueHaibing @ 2019-01-30  1:31 UTC (permalink / raw)
  To: Brian Norris; +Cc: Kalle Valo, ath10k, netdev, linux-wireless, kernel-janitors
In-Reply-To: <CA+ASDXMQto_dqPOuUEX9vqqbWmor8qvpwxBVTg6tSnHkfsCzpw@mail.gmail.com>


On 2019/1/30 2:12, Brian Norris wrote:
> On Mon, Jan 28, 2019 at 9:53 PM YueHaibing <yuehaibing@huawei.com> wrote:
>>
>> ping...
> 
> For some reason, your patch shows up as Deferred in patchwork:
> 
> https://patchwork.kernel.org/patch/10589789/
> 
> So the maintainers have accidentally (?) ignored it. I'm not what the
> official suggestion is for that, but you might just resend.

Thank you for your review,  I'll resend it.

> 
> In any case...
> 
>> On 2018/9/6 10:29, YueHaibing wrote:
>>> From: Yue Haibing <yuehaibing@huawei.com>
>>>
>>> Fixes gcc '-Wunused-but-set-variable' warning:
>>>
>>> drivers/net/wireless/ath/ath10k/snoc.c: In function 'ath10k_snoc_tx_pipe_cleanup':
>>> drivers/net/wireless/ath/ath10k/snoc.c:681:22: warning:
>>>  variable 'ar_snoc' set but not used [-Wunused-but-set-variable]
>>>
>>> Signed-off-by: Yue Haibing <yuehaibing@huawei.com>
> 
> ...patch looks fine to me:
> 
> Reviewed-by: Brian Norris <briannorris@chromium.org>
> 
> 


^ permalink raw reply

* Re: [GIT] Networking
From: pr-tracker-bot @ 2019-01-30  1:25 UTC (permalink / raw)
  To: David Miller; +Cc: torvalds, akpm, netdev, linux-kernel
In-Reply-To: <20190129.125500.154282464274712566.davem@davemloft.net>

The pull request you sent on Tue, 29 Jan 2019 12:55:00 -0800 (PST):

> git://git.kernel.org/pub/scm/linux/kernel/git/davem/net master

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/62967898789dc1f09a06e59fa85ae2c5ca4dc2da

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker

^ permalink raw reply

* [PATCHv4 3/3] dt-bindings: net: dsa: add new MT7530 binding to support MT7621
From: gerg @ 2019-01-30  1:24 UTC (permalink / raw)
  To: sean.wang, linux-mediatek, bjorn, andrew, vivien.didelot,
	f.fainelli, netdev
  Cc: rene, john, neil, Greg Ungerer
In-Reply-To: <20190130012406.28271-1-gerg@kernel.org>

From: Greg Ungerer <gerg@kernel.org>

Add devicetree binding to support the compatible mt7530 switch as used
in the MediaTek MT7621 SoC.

Signed-off-by: Greg Ungerer <gerg@kernel.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 Documentation/devicetree/bindings/net/dsa/mt7530.txt | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

v1: initial patch
v2: use separate devicetree binding
v3: change text according to feedback, rebase onto 5.0-rc3
v4: rebase onto 5.0-rc4

diff --git a/Documentation/devicetree/bindings/net/dsa/mt7530.txt b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
index aa3527f71fdc..47aa205ee0bd 100644
--- a/Documentation/devicetree/bindings/net/dsa/mt7530.txt
+++ b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
@@ -3,12 +3,16 @@ Mediatek MT7530 Ethernet switch
 
 Required properties:
 
-- compatible: Must be compatible = "mediatek,mt7530";
+- compatible: may be compatible = "mediatek,mt7530"
+	or compatible = "mediatek,mt7621"
 - #address-cells: Must be 1.
 - #size-cells: Must be 0.
 - mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part
 	on multi-chip module belong to MT7623A has or the remotely standalone
 	chip as the function MT7623N reference board provided for.
+
+If compatible mediatek,mt7530 is set then the following properties are required
+
 - core-supply: Phandle to the regulator node necessary for the core power.
 - io-supply: Phandle to the regulator node necessary for the I/O power.
 	See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
-- 
2.17.1


^ permalink raw reply related

* [PATCHv4 2/3] net: dsa: mt7530: support the 7530 switch on the Mediatek MT7621 SoC
From: gerg @ 2019-01-30  1:24 UTC (permalink / raw)
  To: sean.wang, linux-mediatek, bjorn, andrew, vivien.didelot,
	f.fainelli, netdev
  Cc: rene, john, neil, Greg Ungerer
In-Reply-To: <20190130012406.28271-1-gerg@kernel.org>

From: Greg Ungerer <gerg@kernel.org>

The MediaTek MT7621 SoC device contains a 7530 switch, and the existing
linux kernel 7530 DSA switch driver can be used with it.

The bulk of the changes required stem from the 7621 having different
regulator and pad setup. The existing setup of these in the 7530
driver appears to be very specific to its implemtation in the Mediatek
7623 SoC. (Not entirely surprising given the 7623 is a quad core ARM
based SoC, and the 7621 is a dual core, dual thread MIPS based SoC).

Create a new devicetree type, "mediatek,mt7621", to support the 7530
switch in the 7621 SoC. There appears to be no usable ID register to
distinguish it from a 7530 in other hardware at runtime. This is used
to carry out the appropriate configuration and setup.

Signed-off-by: Greg Ungerer <gerg@kernel.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mt7530.c | 96 ++++++++++++++++++++++++----------------
 drivers/net/dsa/mt7530.h |  9 ++++
 2 files changed, 66 insertions(+), 39 deletions(-)

v1: initial patch
v2: use separate devicetree binding  
v3: rebase onto 5.0-rc3
v4: simplify by using of_device_get_match_data()
    fix casting for 7530/7621 ID to be 32 and 64 bit clean
    rebase onto 5.0-rc4

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index a8a2c728afba..c2b61500f958 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -621,17 +621,19 @@ static void mt7530_adjust_link(struct dsa_switch *ds, int port,
 	struct mt7530_priv *priv = ds->priv;
 
 	if (phy_is_pseudo_fixed_link(phydev)) {
-		dev_dbg(priv->dev, "phy-mode for master device = %x\n",
-			phydev->interface);
-
-		/* Setup TX circuit incluing relevant PAD and driving */
-		mt7530_pad_clk_setup(ds, phydev->interface);
-
-		/* Setup RX circuit, relevant PAD and driving on the host
-		 * which must be placed after the setup on the device side is
-		 * all finished.
-		 */
-		mt7623_pad_clk_setup(ds);
+		if (priv->id == ID_MT7530) {
+			dev_dbg(priv->dev, "phy-mode for master device = %x\n",
+				phydev->interface);
+
+			/* Setup TX circuit incluing relevant PAD and driving */
+			mt7530_pad_clk_setup(ds, phydev->interface);
+
+			/* Setup RX circuit, relevant PAD and driving on the
+			 * host which must be placed after the setup on the
+			 * device side is all finished.
+			 */
+			mt7623_pad_clk_setup(ds);
+		}
 	} else {
 		u16 lcl_adv = 0, rmt_adv = 0;
 		u8 flowctrl;
@@ -687,6 +689,10 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv,
 	/* Unknown unicast frame fordwarding to the cpu port */
 	mt7530_set(priv, MT7530_MFC, UNU_FFP(BIT(port)));
 
+	/* Set CPU port number */
+	if (priv->id == ID_MT7621)
+		mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
+
 	/* CPU port gets connected to all user ports of
 	 * the switch
 	 */
@@ -1219,24 +1225,27 @@ mt7530_setup(struct dsa_switch *ds)
 	 * as two netdev instances.
 	 */
 	dn = ds->ports[MT7530_CPU_PORT].master->dev.of_node->parent;
-	priv->ethernet = syscon_node_to_regmap(dn);
-	if (IS_ERR(priv->ethernet))
-		return PTR_ERR(priv->ethernet);
 
-	regulator_set_voltage(priv->core_pwr, 1000000, 1000000);
-	ret = regulator_enable(priv->core_pwr);
-	if (ret < 0) {
-		dev_err(priv->dev,
-			"Failed to enable core power: %d\n", ret);
-		return ret;
-	}
+	if (priv->id == ID_MT7530) {
+		priv->ethernet = syscon_node_to_regmap(dn);
+		if (IS_ERR(priv->ethernet))
+			return PTR_ERR(priv->ethernet);
+
+		regulator_set_voltage(priv->core_pwr, 1000000, 1000000);
+		ret = regulator_enable(priv->core_pwr);
+		if (ret < 0) {
+			dev_err(priv->dev,
+				"Failed to enable core power: %d\n", ret);
+			return ret;
+		}
 
-	regulator_set_voltage(priv->io_pwr, 3300000, 3300000);
-	ret = regulator_enable(priv->io_pwr);
-	if (ret < 0) {
-		dev_err(priv->dev, "Failed to enable io pwr: %d\n",
-			ret);
-		return ret;
+		regulator_set_voltage(priv->io_pwr, 3300000, 3300000);
+		ret = regulator_enable(priv->io_pwr);
+		if (ret < 0) {
+			dev_err(priv->dev, "Failed to enable io pwr: %d\n",
+				ret);
+			return ret;
+		}
 	}
 
 	/* Reset whole chip through gpio pin or memory-mapped registers for
@@ -1326,6 +1335,13 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
 	.port_vlan_del		= mt7530_port_vlan_del,
 };
 
+static const struct of_device_id mt7530_of_match[] = {
+	{ .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, },
+	{ .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mt7530_of_match);
+
 static int
 mt7530_probe(struct mdio_device *mdiodev)
 {
@@ -1356,13 +1372,21 @@ mt7530_probe(struct mdio_device *mdiodev)
 		}
 	}
 
-	priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
-	if (IS_ERR(priv->core_pwr))
-		return PTR_ERR(priv->core_pwr);
+	/* Get the hardware identifier from the devicetree node.
+	 * We will need it for some of the clock and regulator setup.
+	 */
+	priv->id = (unsigned int)(unsigned long)
+		of_device_get_match_data(&mdiodev->dev);
 
-	priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
-	if (IS_ERR(priv->io_pwr))
-		return PTR_ERR(priv->io_pwr);
+	if (priv->id == ID_MT7530) {
+		priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
+		if (IS_ERR(priv->core_pwr))
+			return PTR_ERR(priv->core_pwr);
+
+		priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
+		if (IS_ERR(priv->io_pwr))
+			return PTR_ERR(priv->io_pwr);
+	}
 
 	/* Not MCM that indicates switch works as the remote standalone
 	 * integrated circuit so the GPIO pin would be used to complete
@@ -1408,12 +1432,6 @@ mt7530_remove(struct mdio_device *mdiodev)
 	mutex_destroy(&priv->reg_mutex);
 }
 
-static const struct of_device_id mt7530_of_match[] = {
-	{ .compatible = "mediatek,mt7530" },
-	{ /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, mt7530_of_match);
-
 static struct mdio_driver mt7530_mdio_driver = {
 	.probe  = mt7530_probe,
 	.remove = mt7530_remove,
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index d9b407a22a58..a95ed958df5b 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -19,6 +19,11 @@
 #define MT7530_NUM_FDB_RECORDS		2048
 #define MT7530_ALL_MEMBERS		0xff
 
+enum {
+	ID_MT7530 = 0,
+	ID_MT7621 = 1,
+};
+
 #define	NUM_TRGMII_CTRL			5
 
 #define TRGMII_BASE(x)			(0x10000 + (x))
@@ -36,6 +41,9 @@
 #define  UNM_FFP(x)			(((x) & 0xff) << 16)
 #define  UNU_FFP(x)			(((x) & 0xff) << 8)
 #define  UNU_FFP_MASK			UNU_FFP(~0)
+#define  CPU_EN				BIT(7)
+#define  CPU_PORT(x)			((x) << 4)
+#define  CPU_MASK			(0xf << 4)
 
 /* Registers for address table access */
 #define MT7530_ATA1			0x74
@@ -430,6 +438,7 @@ struct mt7530_priv {
 	struct regulator	*core_pwr;
 	struct regulator	*io_pwr;
 	struct gpio_desc	*reset;
+	unsigned int		id;
 	bool			mcm;
 
 	struct mt7530_port	ports[MT7530_NUM_PORTS];
-- 
2.17.1


^ permalink raw reply related

* [PATCHv4 1/3] net: ethernet: mediatek: support MT7621 SoC ethernet hardware
From: gerg @ 2019-01-30  1:24 UTC (permalink / raw)
  To: sean.wang, linux-mediatek, bjorn, andrew, vivien.didelot,
	f.fainelli, netdev
  Cc: rene, john, neil, Greg Ungerer
In-Reply-To: <20190130012406.28271-1-gerg@kernel.org>

From: Bjørn Mork <bjorn@mork.no>

The Mediatek MT7621 SoC contains the same ethernet hardware module as
used on a number of other MediaTek SoC parts. There are some minor
differences to deal with but we can use the same driver to support
them all.

This patch is based on work by Bjørn Mork <bjorn@mork.no>, and his
original patch is at:

https://github.com/bmork/LEDE/commit/3293bc63f5461ca1eb0bbc4ed90145335e7e3404

There is an additional compatible devicetree type added, and the primary
change to the code required is to support a single interrupt (for both
RX and TX interrupts).

Signed-off-by: Bjørn Mork <bjorn@mork.no>
[gerg@kernel.org: rebase to mainline and irq handler fix]
Signed-off-by: Greg Ungerer <gerg@kernel.org>
---
 drivers/net/ethernet/mediatek/Kconfig       |  2 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 48 ++++++++++++++++++---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  4 ++
 3 files changed, 46 insertions(+), 8 deletions(-)

v2: first in series for this change
v3: rebase onto 5.0-rc3
v4: rebase onto 5.0-rc4

diff --git a/drivers/net/ethernet/mediatek/Kconfig b/drivers/net/ethernet/mediatek/Kconfig
index f9149d2a4694..43656f961891 100644
--- a/drivers/net/ethernet/mediatek/Kconfig
+++ b/drivers/net/ethernet/mediatek/Kconfig
@@ -1,6 +1,6 @@
 config NET_VENDOR_MEDIATEK
 	bool "MediaTek ethernet driver"
-	depends on ARCH_MEDIATEK
+	depends on ARCH_MEDIATEK || SOC_MT7621
 	---help---
 	  If you have a Mediatek SoC with ethernet, say Y.
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 49f926b7a91c..94d4663e3933 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1745,6 +1745,22 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t mtk_handle_irq(int irq, void *_eth)
+{
+	struct mtk_eth *eth = _eth;
+
+	if (mtk_r32(eth, MTK_PDMA_INT_MASK) & MTK_RX_DONE_INT) {
+		if (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT)
+			mtk_handle_irq_rx(irq, _eth);
+	}
+	if (mtk_r32(eth, MTK_QDMA_INT_MASK) & MTK_TX_DONE_INT) {
+		if (mtk_r32(eth, MTK_QMTK_INT_STATUS) & MTK_TX_DONE_INT)
+			mtk_handle_irq_tx(irq, _eth);
+	}
+
+	return IRQ_HANDLED;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void mtk_poll_controller(struct net_device *dev)
 {
@@ -2485,7 +2501,10 @@ static int mtk_probe(struct platform_device *pdev)
 	}
 
 	for (i = 0; i < 3; i++) {
-		eth->irq[i] = platform_get_irq(pdev, i);
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0)
+			eth->irq[i] = eth->irq[0];
+		else
+			eth->irq[i] = platform_get_irq(pdev, i);
 		if (eth->irq[i] < 0) {
 			dev_err(&pdev->dev, "no IRQ%d resource found\n", i);
 			return -ENXIO;
@@ -2528,13 +2547,21 @@ static int mtk_probe(struct platform_device *pdev)
 			goto err_deinit_hw;
 	}
 
-	err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
-			       dev_name(eth->dev), eth);
-	if (err)
-		goto err_free_dev;
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
+		err = devm_request_irq(eth->dev, eth->irq[0],
+				       mtk_handle_irq, 0,
+				       dev_name(eth->dev), eth);
+	} else {
+		err = devm_request_irq(eth->dev, eth->irq[1],
+				       mtk_handle_irq_tx, 0,
+				       dev_name(eth->dev), eth);
+		if (err)
+			goto err_free_dev;
 
-	err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
-			       dev_name(eth->dev), eth);
+		err = devm_request_irq(eth->dev, eth->irq[2],
+				       mtk_handle_irq_rx, 0,
+				       dev_name(eth->dev), eth);
+	}
 	if (err)
 		goto err_free_dev;
 
@@ -2607,6 +2634,12 @@ static const struct mtk_soc_data mt2701_data = {
 	.required_pctl = true,
 };
 
+static const struct mtk_soc_data mt7621_data = {
+	.caps = MTK_SHARED_INT,
+	.required_clks = MT7621_CLKS_BITMAP,
+	.required_pctl = false,
+};
+
 static const struct mtk_soc_data mt7622_data = {
 	.caps = MTK_DUAL_GMAC_SHARED_SGMII | MTK_GMAC1_ESW | MTK_HWLRO,
 	.required_clks = MT7622_CLKS_BITMAP,
@@ -2621,6 +2654,7 @@ static const struct mtk_soc_data mt7623_data = {
 
 const struct of_device_id of_mtk_match[] = {
 	{ .compatible = "mediatek,mt2701-eth", .data = &mt2701_data},
+	{ .compatible = "mediatek,mt7621-eth", .data = &mt7621_data},
 	{ .compatible = "mediatek,mt7622-eth", .data = &mt7622_data},
 	{ .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
 	{},
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 46819297fc3e..f7501997cea0 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -363,6 +363,7 @@
 #define ETHSYS_CHIPID4_7	0x4
 #define MT7623_ETH		7623
 #define MT7622_ETH		7622
+#define MT7621_ETH		7621
 
 /* ethernet subsystem config register */
 #define ETHSYS_SYSCFG0		0x14
@@ -488,6 +489,8 @@ enum mtk_clks_map {
 				 BIT(MTK_CLK_SGMII_CDR_FB) | \
 				 BIT(MTK_CLK_SGMII_CK) | \
 				 BIT(MTK_CLK_ETH2PLL))
+#define MT7621_CLKS_BITMAP	(0)
+
 enum mtk_dev_state {
 	MTK_HW_INIT,
 	MTK_RESETTING
@@ -567,6 +570,7 @@ struct mtk_rx_ring {
 #define MTK_DUAL_GMAC_SHARED_SGMII	(BIT(11) | MTK_GMAC1_SGMII | \
 					 MTK_GMAC2_SGMII)
 #define MTK_HWLRO			BIT(12)
+#define MTK_SHARED_INT			BIT(13)
 #define MTK_HAS_CAPS(caps, _x)		(((caps) & (_x)) == (_x))
 
 /* struct mtk_eth_data -	This is the structure holding all differences
-- 
2.17.1


^ permalink raw reply related

* [PATCHv4 0/3]: net: dsa: mt7530: support MT7530 in the MT7621 SoC
From: gerg @ 2019-01-30  1:24 UTC (permalink / raw)
  To: sean.wang, linux-mediatek, bjorn, andrew, vivien.didelot,
	f.fainelli, netdev
  Cc: rene, john, neil


This is the fourth version of a patch series supporting the MT7530 switch
as used in the MediaTek MT7621 SoC. Unlike the MediaTek MT7623 the MT7621
is built around a dual core MIPS CPU architecture. But inside it uses
basically the same 7530 switch.

This series resolves all issues I had with previous versions, and I can
now reliably use the driver on a 7621 SoC platform. These patches were
generated against linux-5.0-rc4.

The first patch enables support for the existing kernel mediatek ethernet
driver on the MT7621 SoC. This support is from Bjørn Mork, with an update
and fix by me. Using this driver fixed a number of problems I had
(TX checksums, large RX packet drop) over the staging driver
(drivers/staging/mt7621-eth).

Patch 2 modifies the mt7530 DSA driver to support the 7530 switch as
implemented in the Mediatek MT7621 SoC. The last patch updates the
devicetree bindings to reflect the new support in the mt7530 driver.

There is no real dependencies between the patches, so they can be taken
independantly.

Creating a new binding for the MT7621 seems like the only viable approach
to distinguish between a stand alone 7530 switch, the silicon module
in the MT7623 SoC and the silicon in the MT7621. Certainly the 7530 ID
register in the MT7623 and MT7621 returns the same value, "0x7530001".

Looking at the mt7530.c DSA driver it might make some sense to convert
the existing "mediatek,mcm" binding to something like "mediatek,mt7623"
to be consistent with this new MT7621 support. As far as I can tell
this is the intention of this binding.

 Documentation/devicetree/bindings/net/dsa/mt7530.txt |    6 -
 drivers/net/dsa/mt7530.c                             |   96 +++++++++++--------
 drivers/net/dsa/mt7530.h                             |    9 +
 drivers/net/ethernet/mediatek/Kconfig                |    2 
 drivers/net/ethernet/mediatek/mtk_eth_soc.c          |   48 ++++++++-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h          |    4 
 6 files changed, 117 insertions(+), 48 deletions(-)

v1: initial patch series
v2: rebase to linux-5.0-rc2
    include mediatek ethernet driver changes
    use devicetree binding to identify platform
v3: dropped mediatek ethernet driver auto negotiate patch
    change devicetree binding text as per feedback
    rebase onto 5.0-rc3
v4: simplify by using of_device_get_match_data()
    fix casting for 7530/7621 ID to be 32 and 64 bit clean
    add review-by tag
    rebase onto 5.0-rc4



^ permalink raw reply

* [PATCH net-next v2 11/12] net: dsa: b53: Add support for toggling IGMP snooping
From: Florian Fainelli @ 2019-01-30  0:55 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, andrew, vivien.didelot, davem, idosch, jiri,
	ilias.apalodimas, ivan.khoronzhuk, roopa, nikolay
In-Reply-To: <20190130005548.2212-1-f.fainelli@gmail.com>

Add the required configuration knobs to honor the turning off of IGMP
snooping (typically through the bridge interface) which means that when
IGMP snooping is off, we must be flooding mutlicast since we do not get
any notifications about IGMP join/leave through the network stack
running on the bridge.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/dsa/b53/b53_common.c | 68 ++++++++++++++++++++++++++++++++
 drivers/net/dsa/b53/b53_priv.h   |  2 +
 2 files changed, 70 insertions(+)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 6c894ad4768a..c0c064a544b9 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1640,6 +1640,73 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
 }
 EXPORT_SYMBOL(b53_fdb_dump);
 
+int b53_multicast_toggle(struct dsa_switch *ds, int port,
+			 bool mc_disabled)
+{
+	unsigned int cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
+	struct b53_device *dev = ds->priv;
+	struct net_device *bridge_dev;
+	struct dsa_port *dp;
+	unsigned int i;
+	u8 port_ctrl;
+	u16 mc_ctrl;
+
+	if (is5325(dev) || is5365(dev))
+		return -EOPNOTSUPP;
+
+	/* Handle the case were multiple bridges span the same switch device
+	 * and one of them has a different setting than what is being requested
+	 * which would be breaking filtering semantics for any of the other
+	 * bridge devices. We must also take care of non-bridged ports which
+	 * expect multicast filtering to remain turned on.
+	 */
+	for (i = 0; i < ds->num_ports; i++) {
+		if (dsa_is_unused_port(ds, i) || dsa_is_cpu_port(ds, i))
+			continue;
+
+		if (i == port)
+			continue;
+
+		dp = dsa_to_port(ds, i);
+		bridge_dev = dp->bridge_dev;
+		if ((bridge_dev &&
+		     bridge_dev != dsa_to_port(ds, port)->bridge_dev &&
+		     br_multicast_enabled(bridge_dev) != !mc_disabled) ||
+		     (!bridge_dev && mc_disabled)) {
+			netdev_err(dp->slave,
+				   "MC filtering is global to the switch!\n");
+			return -EINVAL;
+		}
+	}
+
+	/* Allow CPU port to receive multicast traffic */
+	b53_read8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(cpu_port), &port_ctrl);
+	if (mc_disabled)
+		port_ctrl |= PORT_CTRL_RX_MCST_EN;
+	else
+		port_ctrl &= ~PORT_CTRL_RX_MCST_EN;
+	b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(cpu_port), port_ctrl);
+
+	/* Allow port to flood multicast */
+	b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc_ctrl);
+	if (mc_disabled)
+		mc_ctrl |= BIT(port);
+	else
+		mc_ctrl &= ~BIT(port);
+	b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc_ctrl);
+
+	/* And flood IP multicast as well */
+	b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc_ctrl);
+	if (mc_disabled)
+		mc_ctrl |= BIT(port);
+	else
+		mc_ctrl &= ~BIT(port);
+	b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc_ctrl);
+
+	return 0;
+}
+EXPORT_SYMBOL(b53_multicast_toggle);
+
 int b53_mdb_prepare(struct dsa_switch *ds, int port,
 		    const struct switchdev_obj_port_mdb *mdb)
 {
@@ -2025,6 +2092,7 @@ static const struct dsa_switch_ops b53_switch_ops = {
 	.port_mirror_add	= b53_mirror_add,
 	.port_mirror_del	= b53_mirror_del,
 	.port_mdb_prepare	= b53_mdb_prepare,
+	.port_multicast_toggle	= b53_multicast_toggle,
 	.port_mdb_add		= b53_mdb_add,
 	.port_mdb_del		= b53_mdb_del,
 };
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index 620638ff9338..cd259fb8b00e 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -350,6 +350,8 @@ int b53_fdb_del(struct dsa_switch *ds, int port,
 		const unsigned char *addr, u16 vid);
 int b53_fdb_dump(struct dsa_switch *ds, int port,
 		 dsa_fdb_dump_cb_t *cb, void *data);
+int b53_multicast_toggle(struct dsa_switch *ds, int port,
+			 bool mc_disabled);
 int b53_mdb_prepare(struct dsa_switch *ds, int port,
 		    const struct switchdev_obj_port_mdb *mdb);
 void b53_mdb_add(struct dsa_switch *ds, int port,
-- 
2.17.1


^ permalink raw reply related

* [PATCH net-next v2 12/12] net: dsa: bcm_sf2: Enable management mode
From: Florian Fainelli @ 2019-01-30  0:55 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, andrew, vivien.didelot, davem, idosch, jiri,
	ilias.apalodimas, ivan.khoronzhuk, roopa, nikolay
In-Reply-To: <20190130005548.2212-1-f.fainelli@gmail.com>

Now that we have all the necessary plumbing in place to get notified
when a multicast MAC address must be programmed, configure the switch to
oeprate in managed mode and let the network stack learn about management
traffic.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/dsa/b53/b53_common.c | 39 ++++++++++++++++++++--
 drivers/net/dsa/b53/b53_priv.h   |  1 +
 drivers/net/dsa/bcm_sf2.c        | 56 +++++++++++++++++++++++---------
 drivers/net/dsa/bcm_sf2_regs.h   |  5 +++
 4 files changed, 84 insertions(+), 17 deletions(-)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index c0c064a544b9..10e115a43975 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -364,8 +364,6 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable,
 		b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5, &vc5);
 	}
 
-	mgmt &= ~SM_SW_FWD_MODE;
-
 	if (enable) {
 		vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID;
 		vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN;
@@ -490,6 +488,43 @@ static int b53_fast_age_vlan(struct b53_device *dev, u16 vid)
 	return b53_flush_arl(dev, FAST_AGE_VLAN);
 }
 
+void b53_port_learn_setup(struct dsa_switch *ds, int port)
+{
+	struct b53_device *dev = ds->priv;
+	u16 reg;
+
+	/* Enable learning */
+	b53_read16(dev, B53_CTRL_PAGE, B53_DIS_LEARN, &reg);
+	reg &= ~BIT(port);
+	b53_write16(dev, B53_CTRL_PAGE, B53_DIS_LEARN, reg);
+
+	/* Software learning control disabled */
+	b53_read16(dev, B53_CTRL_PAGE, B53_SFT_LRN_CTRL, &reg);
+	reg &= ~BIT(port);
+	b53_write16(dev, B53_CTRL_PAGE, B53_SFT_LRN_CTRL, reg);
+
+	/* Configure IP multicast, allow Unicast ARL misses to be forwarded */
+	b53_read16(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, &reg);
+	reg |= B53_IPMC_FWD_EN | B53_UC_FWD_EN;
+	b53_write16(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, reg);
+
+	/* Set port in Unicast lookup forward map */
+	b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &reg);
+	reg |= BIT(port);
+	b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, reg);
+
+	/* Do not set port in Multicast lookup forward map, learn */
+	b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &reg);
+	reg &= ~BIT(port);
+	b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, reg);
+
+	/* Do not set port in IP multicast lookup formward map, learn */
+	b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &reg);
+	reg &= ~BIT(port);
+	b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, reg);
+}
+EXPORT_SYMBOL(b53_port_learn_setup);
+
 void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
 {
 	struct b53_device *dev = ds->priv;
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index cd259fb8b00e..1806304c38cc 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -309,6 +309,7 @@ static inline int b53_switch_get_reset_gpio(struct b53_device *dev)
 #endif
 
 /* Exported functions towards other drivers */
+void b53_port_learn_setup(struct dsa_switch *ds, int port);
 void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port);
 int b53_configure_vlan(struct dsa_switch *ds);
 void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset,
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 361fbde76654..c9e6ffb737a4 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -51,19 +51,19 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
 	reg &= ~P_TXQ_PSM_VDD(port);
 	core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
 
-	/* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
-	reg = core_readl(priv, CORE_IMP_CTL);
-	reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN);
-	reg &= ~(RX_DIS | TX_DIS);
-	core_writel(priv, reg, CORE_IMP_CTL);
+	/* Enable forwarding and managed mode */
+	core_writel(priv, SW_FWDG_EN | SW_FWDG_MODE, CORE_SWMODE);
 
-	/* Enable forwarding */
-	core_writel(priv, SW_FWDG_EN, CORE_SWMODE);
+	/* Configure port for learning */
+	b53_port_learn_setup(ds, port);
 
-	/* Enable IMP port in dumb mode */
-	reg = core_readl(priv, CORE_SWITCH_CTRL);
-	reg |= MII_DUMB_FWDG_EN;
-	core_writel(priv, reg, CORE_SWITCH_CTRL);
+	/* Enable IGMP and MLD high-level protocol snooping support */
+	reg = HL_PRTC_IGMP_RPTLVE_EN | HL_PRTC_IGMP_RPTVLE_FWD_MODE |
+	      HL_PRTC_IGMP_QRY_EN | HL_PRTC_IGMP_QRY_FWD_MODE |
+	      HL_PRTC_IGMP_UKN_EN | HL_PRTC_IGMP_UKN_FWD_MODE |
+	      HL_PRTC_MLD_RPTDONE_EN | HL_PRTC_MLD_RPTDONE_FWD_MODE |
+	      HL_PRTC_MLD_QRY_EN | HL_PRTC_MLD_QRY_FWD_MODE;
+	b53_write32(priv->dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL, reg);
 
 	/* Configure Traffic Class to QoS mapping, allow each priority to map
 	 * to a different queue number
@@ -75,10 +75,26 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
 
 	b53_brcm_hdr_setup(ds, port);
 
+	/* Set IMP0 or IMP1 port to be managed port, enable BPDU */
+	reg = core_readl(priv, CORE_GMNCFGCFG);
+	reg &= ~(FRM_MGNP_MASK << FRM_MGNP_SHIFT);
+	if (port == core_readl(priv, CORE_IMP0_PRT_ID))
+		reg |= FRM_MNGP_IMP0 << FRM_MGNP_SHIFT;
+	if (port == core_readl(priv, CORE_IMP1_PRT_ID))
+		reg |= FRM_MGNP_IMP_DUAL << FRM_MGNP_SHIFT;
+	reg |= RXBPDU_EN;
+	core_writel(priv, reg, CORE_GMNCFGCFG);
+
 	/* Force link status for IMP port */
 	reg = core_readl(priv, offset);
 	reg |= (MII_SW_OR | LINK_STS);
 	core_writel(priv, reg, offset);
+
+	/* Enable Broadcast, Unicast forwarding to IMP port */
+	reg = core_readl(priv, CORE_IMP_CTL);
+	reg |= (RX_BCST_EN | RX_UCST_EN);
+	reg &= ~(RX_DIS | TX_DIS);
+	core_writel(priv, reg, CORE_IMP_CTL);
 }
 
 static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable)
@@ -166,10 +182,8 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
 	reg &= ~P_TXQ_PSM_VDD(port);
 	core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
 
-	/* Enable learning */
-	reg = core_readl(priv, CORE_DIS_LEARN);
-	reg &= ~BIT(port);
-	core_writel(priv, reg, CORE_DIS_LEARN);
+	/* Configure port for learning */
+	b53_port_learn_setup(ds, port);
 
 	/* Enable Broadcom tags for that port if requested */
 	if (priv->brcm_tag_mask & BIT(port))
@@ -683,6 +697,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
 {
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 	unsigned int port;
+	u32 reg;
 
 	bcm_sf2_intr_disable(priv);
 
@@ -695,6 +710,13 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
 			bcm_sf2_port_disable(ds, port, NULL);
 	}
 
+	/* Disable management mode since we won't be able to
+	 * perform any tasks while being suspended.
+	 */
+	reg = core_readl(priv, CORE_SWMODE);
+	reg &= ~SW_FWDG_MODE;
+	core_writel(priv, reg, CORE_SWMODE);
+
 	return 0;
 }
 
@@ -930,6 +952,10 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
 	.set_rxnfc		= bcm_sf2_set_rxnfc,
 	.port_mirror_add	= b53_mirror_add,
 	.port_mirror_del	= b53_mirror_del,
+	.port_multicast_toggle	= b53_multicast_toggle,
+	.port_mdb_prepare	= b53_mdb_prepare,
+	.port_mdb_add		= b53_mdb_add,
+	.port_mdb_del		= b53_mdb_del,
 };
 
 struct bcm_sf2_of_data {
diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h
index 0a1e530d52b7..211db9a2e9e9 100644
--- a/drivers/net/dsa/bcm_sf2_regs.h
+++ b/drivers/net/dsa/bcm_sf2_regs.h
@@ -222,8 +222,13 @@ enum bcm_sf2_reg_offs {
 #define CORE_GMNCFGCFG			0x0800
 #define  RST_MIB_CNT			(1 << 0)
 #define  RXBPDU_EN			(1 << 1)
+#define  FRM_MGNP_SHIFT			6
+#define  FRM_MGNP_MASK			0x3
+#define  FRM_MNGP_IMP0			2
+#define  FRM_MGNP_IMP_DUAL		3
 
 #define CORE_IMP0_PRT_ID		0x0804
+#define CORE_IMP1_PRT_ID		0x0808
 
 #define CORE_RST_MIB_CNT_EN		0x0950
 
-- 
2.17.1


^ permalink raw reply related

* [PATCH net-next v2 09/12] net: dsa: Make VLAN filtering use DSA notifiers
From: Florian Fainelli @ 2019-01-30  0:55 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, andrew, vivien.didelot, davem, idosch, jiri,
	ilias.apalodimas, ivan.khoronzhuk, roopa, nikolay
In-Reply-To: <20190130005548.2212-1-f.fainelli@gmail.com>

In preparation for allowing for global checks that would apply to the
entire switch and not just on a per-port basis, make the VLAN filtering
attribute follow other switchdev attributes/objects and make it use the
DSA notifier infrastructure.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 net/dsa/dsa_priv.h | 11 ++++++++++-
 net/dsa/port.c     | 17 +++++++----------
 net/dsa/switch.c   | 29 +++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 1f4972dab9f2..1e3db5f2a699 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -26,6 +26,7 @@ enum {
 	DSA_NOTIFIER_MDB_DEL,
 	DSA_NOTIFIER_VLAN_ADD,
 	DSA_NOTIFIER_VLAN_DEL,
+	DSA_NOTIFIER_VLAN_FILTERING,
 };
 
 /* DSA_NOTIFIER_AGEING_TIME */
@@ -57,7 +58,7 @@ struct dsa_notifier_mdb_info {
 	int port;
 };
 
-/* DSA_NOTIFIER_VLAN_* */
+/* DSA_NOTIFIER_VLAN_{ADD,DEL} */
 struct dsa_notifier_vlan_info {
 	const struct switchdev_obj_port_vlan *vlan;
 	struct switchdev_trans *trans;
@@ -65,6 +66,14 @@ struct dsa_notifier_vlan_info {
 	int port;
 };
 
+/* DSA_NOTIFIER_VLAN_FILTERING */
+struct dsa_notifier_vlan_filtering_info {
+	bool vlan_filtering;
+	struct switchdev_trans *trans;
+	int sw_index;
+	int port;
+};
+
 struct dsa_slave_priv {
 	/* Copy of CPU port xmit for faster access in slave transmit hot path */
 	struct sk_buff *	(*xmit)(struct sk_buff *skb,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 185e85a4f5f0..d7b057d46460 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -146,17 +146,14 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
 int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
 			    struct switchdev_trans *trans)
 {
-	struct dsa_switch *ds = dp->ds;
-
-	/* bridge skips -EOPNOTSUPP, so skip the prepare phase */
-	if (switchdev_trans_ph_prepare(trans))
-		return 0;
-
-	if (ds->ops->port_vlan_filtering)
-		return ds->ops->port_vlan_filtering(ds, dp->index,
-						    vlan_filtering);
+	struct dsa_notifier_vlan_filtering_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.trans = trans,
+		.vlan_filtering = vlan_filtering,
+	};
 
-	return 0;
+	return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_FILTERING, &info);
 }
 
 int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 142b294d3446..831334dc5e79 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -235,6 +235,32 @@ static int dsa_switch_vlan_del(struct dsa_switch *ds,
 	return 0;
 }
 
+static int dsa_switch_vlan_filtering(struct dsa_switch *ds,
+				     struct dsa_notifier_vlan_filtering_info *info)
+{
+	struct switchdev_trans *trans = info->trans;
+	bool vlan_filtering = info->vlan_filtering;
+	int port = info->port;
+	int err;
+
+	/* bridge skips -EOPNOTSUPP, so skip the prepare phase */
+	if (switchdev_trans_ph_prepare(trans))
+		return 0;
+
+	/* Build a mask of port members */
+	bitmap_zero(ds->bitmap, ds->num_ports);
+	if (ds->index == info->sw_index)
+		set_bit(port, ds->bitmap);
+
+	for_each_set_bit(port, ds->bitmap, ds->num_ports) {
+		err = ds->ops->port_vlan_filtering(ds, port, vlan_filtering);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
 static int dsa_switch_event(struct notifier_block *nb,
 			    unsigned long event, void *info)
 {
@@ -269,6 +295,9 @@ static int dsa_switch_event(struct notifier_block *nb,
 	case DSA_NOTIFIER_VLAN_DEL:
 		err = dsa_switch_vlan_del(ds, info);
 		break;
+	case DSA_NOTIFIER_VLAN_FILTERING:
+		err = dsa_switch_vlan_filtering(ds, info);
+		break;
 	default:
 		err = -EOPNOTSUPP;
 		break;
-- 
2.17.1


^ permalink raw reply related

* [PATCH net-next v2 10/12] net: dsa: Wire up multicast IGMP snooping attribute notification
From: Florian Fainelli @ 2019-01-30  0:55 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, andrew, vivien.didelot, davem, idosch, jiri,
	ilias.apalodimas, ivan.khoronzhuk, roopa, nikolay
In-Reply-To: <20190130005548.2212-1-f.fainelli@gmail.com>

The bridge can at runtime be configured with or without IGMP snooping
enabled but we were not processing the switchdev attribute that notifies
about that toggle, do this now.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 include/net/dsa.h  |  2 ++
 net/dsa/dsa_priv.h | 11 +++++++++++
 net/dsa/port.c     | 13 +++++++++++++
 net/dsa/slave.c    |  4 ++++
 net/dsa/switch.c   | 28 ++++++++++++++++++++++++++++
 5 files changed, 58 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 7f2a668ef2cc..2ee1ede7df5c 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -425,6 +425,8 @@ struct dsa_switch_ops {
 	/*
 	 * Multicast database
 	 */
+	int	(*port_multicast_toggle)(struct dsa_switch *ds, int port,
+					 bool mc_disabled);
 	int (*port_mdb_prepare)(struct dsa_switch *ds, int port,
 				const struct switchdev_obj_port_mdb *mdb);
 	void (*port_mdb_add)(struct dsa_switch *ds, int port,
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 1e3db5f2a699..221753777cf5 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -27,6 +27,7 @@ enum {
 	DSA_NOTIFIER_VLAN_ADD,
 	DSA_NOTIFIER_VLAN_DEL,
 	DSA_NOTIFIER_VLAN_FILTERING,
+	DSA_NOTIFIER_MC_DISABLED,
 };
 
 /* DSA_NOTIFIER_AGEING_TIME */
@@ -74,6 +75,14 @@ struct dsa_notifier_vlan_filtering_info {
 	int port;
 };
 
+/* DSA_NOTIFIER_MC_DISABLED */
+struct dsa_notifier_mc_disabled_info {
+	bool mc_disabled;
+	struct switchdev_trans *trans;
+	int sw_index;
+	int port;
+};
+
 struct dsa_slave_priv {
 	/* Copy of CPU port xmit for faster access in slave transmit hot path */
 	struct sk_buff *	(*xmit)(struct sk_buff *skb,
@@ -155,6 +164,8 @@ int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy);
 void dsa_port_disable(struct dsa_port *dp, struct phy_device *phy);
 int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
 void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
+int dsa_port_multicast_toggle(struct dsa_port *dp, bool mc_disabled,
+			      struct switchdev_trans *trans);
 int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
 			    struct switchdev_trans *trans);
 int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index d7b057d46460..148458941b51 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -143,6 +143,19 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
 	dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
 }
 
+int dsa_port_multicast_toggle(struct dsa_port *dp, bool mc_disabled,
+			      struct switchdev_trans *trans)
+{
+	struct dsa_notifier_mc_disabled_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.trans = trans,
+		.mc_disabled = mc_disabled,
+	};
+
+	return dsa_port_notify(dp, DSA_NOTIFIER_MC_DISABLED, &info);
+}
+
 int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
 			    struct switchdev_trans *trans)
 {
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 306fd1b45f0c..f3b3cf34804f 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -337,6 +337,10 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
 	case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
 		ret = dsa_port_ageing_time(dp, attr->u.ageing_time, trans);
 		break;
+	case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
+		ret = dsa_port_multicast_toggle(dp, attr->u.mc_disabled,
+						trans);
+		break;
 	default:
 		ret = -EOPNOTSUPP;
 		break;
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 831334dc5e79..e095eb808434 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -261,6 +261,31 @@ static int dsa_switch_vlan_filtering(struct dsa_switch *ds,
 	return 0;
 }
 
+static int dsa_switch_mc_disabled(struct dsa_switch *ds,
+				  struct dsa_notifier_mc_disabled_info *info)
+{
+	struct switchdev_trans *trans = info->trans;
+	bool mc_disabled = info->mc_disabled;
+	int port = info->port;
+	int err;
+
+	if (switchdev_trans_ph_prepare(trans))
+		return ds->ops->port_multicast_toggle ? 0 : -EOPNOTSUPP;
+
+	/* Build a mask of port members */
+	bitmap_zero(ds->bitmap, ds->num_ports);
+	if (ds->index == info->sw_index)
+		set_bit(port, ds->bitmap);
+
+	for_each_set_bit(port, ds->bitmap, ds->num_ports) {
+		err = ds->ops->port_multicast_toggle(ds, port, mc_disabled);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
 static int dsa_switch_event(struct notifier_block *nb,
 			    unsigned long event, void *info)
 {
@@ -298,6 +323,9 @@ static int dsa_switch_event(struct notifier_block *nb,
 	case DSA_NOTIFIER_VLAN_FILTERING:
 		err = dsa_switch_vlan_filtering(ds, info);
 		break;
+	case DSA_NOTIFIER_MC_DISABLED:
+		err = dsa_switch_mc_disabled(ds, info);
+		break;
 	default:
 		err = -EOPNOTSUPP;
 		break;
-- 
2.17.1


^ permalink raw reply related

* [PATCH net-next v2 08/12] net: dsa: Add ndo_vlan_rx_{add,kill}_vid implementation
From: Florian Fainelli @ 2019-01-30  0:55 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, andrew, vivien.didelot, davem, idosch, jiri,
	ilias.apalodimas, ivan.khoronzhuk, roopa, nikolay
In-Reply-To: <20190130005548.2212-1-f.fainelli@gmail.com>

In order to properly support VLAN filtering being enabled/disabled on a
bridge, while having other ports being non bridge port members, we need
to support the ndo_vlan_rx_{add,kill}_vid callbacks in order to make
sure the non-bridge ports can continue receiving VLAN tags, even when
the switch is globally configured to do ingress/egress VID checking.

We don't allow configuring VLAN devices on a bridge port member though,
since the bridge with VLAN awareness should be taking care of that, if
needed.

Since we can call dsa_port_vlan_{add,del} with a bridge_dev pointer
NULL, we now need to check that in these two functions.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 net/dsa/port.c  | 12 +++++++++--
 net/dsa/slave.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/net/dsa/port.c b/net/dsa/port.c
index 2d7e01b23572..185e85a4f5f0 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -252,7 +252,11 @@ int dsa_port_vlan_add(struct dsa_port *dp,
 		.vlan = vlan,
 	};
 
-	if (br_vlan_enabled(dp->bridge_dev))
+	/* Can be called from dsa_slave_port_obj_add() or
+	 * dsa_slave_vlan_rx_add_vid()
+	 */
+	if ((dp->bridge_dev && br_vlan_enabled(dp->bridge_dev)) ||
+	    !dp->bridge_dev)
 		return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
 
 	return 0;
@@ -270,7 +274,11 @@ int dsa_port_vlan_del(struct dsa_port *dp,
 	if (netif_is_bridge_master(vlan->obj.orig_dev))
 		return -EOPNOTSUPP;
 
-	if (br_vlan_enabled(dp->bridge_dev))
+	/* Can be called from dsa_slave_port_obj_del() or
+	 * dsa_slave_vlan_rx_kill_vid()
+	 */
+	if ((dp->bridge_dev && br_vlan_enabled(dp->bridge_dev)) ||
+	    !dp->bridge_dev)
 		return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
 
 	return 0;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index a6a803262929..306fd1b45f0c 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1027,6 +1027,54 @@ static int dsa_slave_get_ts_info(struct net_device *dev,
 	return ds->ops->get_ts_info(ds, p->dp->index, ts);
 }
 
+static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
+				     u16 vid)
+{
+	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct switchdev_obj_port_vlan vlan = { };
+	int ret = 0;
+
+	/* If the port is bridged and the bridge is VLAN aware, let the bridge
+	 * manage VLANs
+	 */
+	if (dp->bridge_dev && br_vlan_enabled(dp->bridge_dev))
+		return -EINVAL;
+
+	/* This API only allows programming tagged, non-PVID VIDs */
+	vlan.vid_begin = vid;
+	vlan.vid_end = vid;
+
+	ret = dsa_port_vlan_add(dp, &vlan, NULL);
+	if (ret == -EOPNOTSUPP)
+		ret = 0;
+
+	return ret;
+}
+
+static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
+				      u16 vid)
+{
+	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct switchdev_obj_port_vlan vlan = { };
+	int ret = 0;
+
+	/* If the port is bridged and the bridge is VLAN aware, let the bridge
+	 * manage VLANs
+	 */
+	if (dp->bridge_dev && br_vlan_enabled(dp->bridge_dev))
+		return -EINVAL;
+
+	/* This API only allows programming tagged, non-PVID VIDs */
+	vlan.vid_begin = vid;
+	vlan.vid_end = vid;
+
+	ret = dsa_port_vlan_del(dp, &vlan);
+	if (ret == -EOPNOTSUPP)
+		ret = 0;
+
+	return ret;
+}
+
 static const struct ethtool_ops dsa_slave_ethtool_ops = {
 	.get_drvinfo		= dsa_slave_get_drvinfo,
 	.get_regs_len		= dsa_slave_get_regs_len,
@@ -1091,6 +1139,8 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
 	.ndo_get_phys_port_name	= dsa_slave_get_phys_port_name,
 	.ndo_setup_tc		= dsa_slave_setup_tc,
 	.ndo_get_stats64	= dsa_slave_get_stats64,
+	.ndo_vlan_rx_add_vid	= dsa_slave_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= dsa_slave_vlan_rx_kill_vid,
 };
 
 static const struct switchdev_ops dsa_slave_switchdev_ops = {
@@ -1351,7 +1401,8 @@ int dsa_slave_create(struct dsa_port *port)
 	if (slave_dev == NULL)
 		return -ENOMEM;
 
-	slave_dev->features = master->vlan_features | NETIF_F_HW_TC;
+	slave_dev->features = master->vlan_features | NETIF_F_HW_TC |
+				NETIF_F_HW_VLAN_CTAG_FILTER;
 	slave_dev->hw_features |= NETIF_F_HW_TC;
 	slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
 	eth_hw_addr_inherit(slave_dev, master);
-- 
2.17.1


^ permalink raw reply related

* [PATCH net-next v2 07/12] net: dsa: Add ability to program multicast filter for CPU port
From: Florian Fainelli @ 2019-01-30  0:55 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, andrew, vivien.didelot, davem, idosch, jiri,
	ilias.apalodimas, ivan.khoronzhuk, roopa, nikolay
In-Reply-To: <20190130005548.2212-1-f.fainelli@gmail.com>

When the switch ports operate as individual network devices, the switch
driver might have configured the switch to flood multicast all the way
to the CPU port. This is really undesireable as it can lead to receiving
a lot of unwanted traffic that the network stack needs to filter in
software.

For each valid multicast address, program it into the switch's MDB only
when the host is interested in receiving such traffic, e.g: running an
multicast application.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 net/dsa/slave.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 91de3a663226..a6a803262929 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -68,6 +68,39 @@ static int dsa_slave_get_iflink(const struct net_device *dev)
 	return dsa_slave_to_master(dev)->ifindex;
 }
 
+static int dsa_slave_sync_unsync_mdb_addr(struct net_device *dev,
+					  const unsigned char *addr, bool add)
+{
+	struct switchdev_obj_port_mdb mdb = {
+		.obj = {
+			.id = SWITCHDEV_OBJ_ID_HOST_MDB,
+			.flags = SWITCHDEV_F_DEFER,
+		},
+		.vid = 0,
+	};
+	int ret = -EOPNOTSUPP;
+
+	ether_addr_copy(mdb.addr, addr);
+	if (add)
+		ret = switchdev_port_obj_add(dev, &mdb.obj, NULL);
+	else
+		ret = switchdev_port_obj_del(dev, &mdb.obj);
+
+	return ret;
+}
+
+static int dsa_slave_sync_mdb_addr(struct net_device *dev,
+				   const unsigned char *addr)
+{
+	return dsa_slave_sync_unsync_mdb_addr(dev, addr, true);
+}
+
+static int dsa_slave_unsync_mdb_addr(struct net_device *dev,
+				     const unsigned char *addr)
+{
+	return dsa_slave_sync_unsync_mdb_addr(dev, addr, false);
+}
+
 static int dsa_slave_open(struct net_device *dev)
 {
 	struct net_device *master = dsa_slave_to_master(dev);
@@ -126,6 +159,8 @@ static int dsa_slave_close(struct net_device *dev)
 
 	dev_mc_unsync(master, dev);
 	dev_uc_unsync(master, dev);
+	__hw_addr_unsync_dev(&dev->mc, dev, dsa_slave_unsync_mdb_addr);
+
 	if (dev->flags & IFF_ALLMULTI)
 		dev_set_allmulti(master, -1);
 	if (dev->flags & IFF_PROMISC)
@@ -150,7 +185,17 @@ static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
 static void dsa_slave_set_rx_mode(struct net_device *dev)
 {
 	struct net_device *master = dsa_slave_to_master(dev);
+	struct dsa_port *dp = dsa_slave_to_port(dev);
 
+	/* If the port is bridged, the bridge takes care of sending
+	 * SWITCHDEV_OBJ_ID_HOST_MDB to program the host's MC filter
+	 */
+	if (netdev_mc_empty(dev) || dp->bridge_dev)
+		goto out;
+
+	__hw_addr_sync_dev(&dev->mc, dev, dsa_slave_sync_mdb_addr,
+			   dsa_slave_unsync_mdb_addr);
+out:
 	dev_mc_sync(master, dev);
 	dev_uc_sync(master, dev);
 }
@@ -1396,6 +1441,11 @@ static int dsa_slave_changeupper(struct net_device *dev,
 
 	if (netif_is_bridge_master(info->upper_dev)) {
 		if (info->linking) {
+			/* Remove existing MC addresses that might have been
+			 * programmed
+			 */
+			__hw_addr_unsync_dev(&dev->mc, dev,
+					     dsa_slave_unsync_mdb_addr);
 			err = dsa_port_bridge_join(dp, info->upper_dev);
 			err = notifier_from_errno(err);
 		} else {
-- 
2.17.1


^ permalink raw reply related

* [PATCH net-next v2 06/12] net: dsa: b53: Add support for MDB
From: Florian Fainelli @ 2019-01-30  0:55 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, andrew, vivien.didelot, davem, idosch, jiri,
	ilias.apalodimas, ivan.khoronzhuk, roopa, nikolay
In-Reply-To: <20190130005548.2212-1-f.fainelli@gmail.com>

In preparation for supporting IGMP snooping with or without the use of
a bridge, add support within b53_common.c to program the ARL entries for
multicast operations. The key difference is that a multicast ARL entry
is comprised of a bitmask of enabled ports, instead of a port number.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/dsa/b53/b53_common.c | 62 ++++++++++++++++++++++++++++++--
 drivers/net/dsa/b53/b53_priv.h   |  8 ++++-
 2 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 2fef4c564420..6c894ad4768a 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1503,11 +1503,25 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
 		idx = 1;
 	}
 
-	memset(&ent, 0, sizeof(ent));
-	ent.port = port;
+	/* For multicast address, the port is a bitmask and the validity
+	 * is determined by having at least one port being still active
+	 */
+	if (!is_multicast_ether_addr(addr)) {
+		ent.port = port;
+		ent.is_valid = is_valid;
+	} else {
+		if (is_valid)
+			ent.port |= BIT(port);
+		else
+			ent.port &= ~BIT(port);
+
+		ent.is_valid = !!(ent.port);
+	}
+
 	ent.is_valid = is_valid;
 	ent.vid = vid;
 	ent.is_static = true;
+	ent.is_age = false;
 	memcpy(ent.mac, addr, ETH_ALEN);
 	b53_arl_from_entry(&mac_vid, &fwd_entry, &ent);
 
@@ -1626,6 +1640,47 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
 }
 EXPORT_SYMBOL(b53_fdb_dump);
 
+int b53_mdb_prepare(struct dsa_switch *ds, int port,
+		    const struct switchdev_obj_port_mdb *mdb)
+{
+	struct b53_device *priv = ds->priv;
+
+	/* 5325 and 5365 require some more massaging, but could
+	 * be supported eventually
+	 */
+	if (is5325(priv) || is5365(priv))
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+EXPORT_SYMBOL(b53_mdb_prepare);
+
+void b53_mdb_add(struct dsa_switch *ds, int port,
+		 const struct switchdev_obj_port_mdb *mdb)
+{
+	struct b53_device *priv = ds->priv;
+	int ret;
+
+	ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true);
+	if (ret)
+		dev_err(ds->dev, "failed to add MDB entry\n");
+}
+EXPORT_SYMBOL(b53_mdb_add);
+
+int b53_mdb_del(struct dsa_switch *ds, int port,
+		const struct switchdev_obj_port_mdb *mdb)
+{
+	struct b53_device *priv = ds->priv;
+	int ret;
+
+	ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, false);
+	if (ret)
+		dev_err(ds->dev, "failed to delete MDB entry\n");
+
+	return ret;
+}
+EXPORT_SYMBOL(b53_mdb_del);
+
 int b53_br_join(struct dsa_switch *ds, int port, struct net_device *br)
 {
 	struct b53_device *dev = ds->priv;
@@ -1969,6 +2024,9 @@ static const struct dsa_switch_ops b53_switch_ops = {
 	.port_fdb_del		= b53_fdb_del,
 	.port_mirror_add	= b53_mirror_add,
 	.port_mirror_del	= b53_mirror_del,
+	.port_mdb_prepare	= b53_mdb_prepare,
+	.port_mdb_add		= b53_mdb_add,
+	.port_mdb_del		= b53_mdb_del,
 };
 
 struct b53_chip_data {
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index 4dc7ee38b258..620638ff9338 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -251,7 +251,7 @@ b53_build_op(write48, u64);
 b53_build_op(write64, u64);
 
 struct b53_arl_entry {
-	u8 port;
+	u16 port;
 	u8 mac[ETH_ALEN];
 	u16 vid;
 	u8 is_valid:1;
@@ -350,6 +350,12 @@ int b53_fdb_del(struct dsa_switch *ds, int port,
 		const unsigned char *addr, u16 vid);
 int b53_fdb_dump(struct dsa_switch *ds, int port,
 		 dsa_fdb_dump_cb_t *cb, void *data);
+int b53_mdb_prepare(struct dsa_switch *ds, int port,
+		    const struct switchdev_obj_port_mdb *mdb);
+void b53_mdb_add(struct dsa_switch *ds, int port,
+		 const struct switchdev_obj_port_mdb *mdb);
+int b53_mdb_del(struct dsa_switch *ds, int port,
+		const struct switchdev_obj_port_mdb *mdb);
 int b53_mirror_add(struct dsa_switch *ds, int port,
 		   struct dsa_mall_mirror_tc_entry *mirror, bool ingress);
 enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port);
-- 
2.17.1


^ permalink raw reply related

* [PATCH net-next v2 05/12] net: dsa: b53: Define registers for IGMP snooping
From: Florian Fainelli @ 2019-01-30  0:55 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, andrew, vivien.didelot, davem, idosch, jiri,
	ilias.apalodimas, ivan.khoronzhuk, roopa, nikolay
In-Reply-To: <20190130005548.2212-1-f.fainelli@gmail.com>

Define all necessary registers in order to implement IGMP snooping later
on, which are mostly comprised of the high-level protocol register
control definitions.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/dsa/b53/b53_regs.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/net/dsa/b53/b53_regs.h b/drivers/net/dsa/b53/b53_regs.h
index 2a9f421680aa..b4aecd4552b6 100644
--- a/drivers/net/dsa/b53/b53_regs.h
+++ b/drivers/net/dsa/b53/b53_regs.h
@@ -115,6 +115,8 @@
 #define B53_UC_FLOOD_MASK		0x32
 #define B53_MC_FLOOD_MASK		0x34
 #define B53_IPMC_FLOOD_MASK		0x36
+#define B53_DIS_LEARN			0x3c
+#define B53_SFT_LRN_CTRL		0x3e
 
 /*
  * Override Ports 0-7 State on devices with xMII interfaces (8 bit)
@@ -253,6 +255,26 @@
 /* Revision ID register (8 bit) */
 #define B53_REV_ID			0x40
 
+/* High-level Protocol Control Register (32 bit) */
+#define B53_HL_PRTC_CTRL		0x50
+#define  HL_PRTC_ARP_EN			(1 << 0)
+#define  HL_PRTC_RARP_EN		(1 << 1)
+#define  HL_PRTC_DHCP_EN		(1 << 2)
+#define  HL_PRTC_ICMPV4_EN		(1 << 3)
+#define  HL_PRTC_ICMPV6_EN		(1 << 4)
+#define  HL_PRTC_ICMPV6_FWD_MODE	(1 << 5)
+#define  HL_PRTC_IGMP_DIP_EN		(1 << 8)
+#define  HL_PRTC_IGMP_RPTLVE_EN		(1 << 9)
+#define  HL_PRTC_IGMP_RPTVLE_FWD_MODE	(1 << 10)
+#define  HL_PRTC_IGMP_QRY_EN		(1 << 11)
+#define  HL_PRTC_IGMP_QRY_FWD_MODE	(1 << 12)
+#define  HL_PRTC_IGMP_UKN_EN		(1 << 13)
+#define  HL_PRTC_IGMP_UKN_FWD_MODE	(1 << 14)
+#define  HL_PRTC_MLD_RPTDONE_EN		(1 << 15)
+#define  HL_PRTC_MLD_RPTDONE_FWD_MODE	(1 << 16)
+#define  HL_PRTC_MLD_QRY_EN		(1 << 17)
+#define  HL_PRTC_MLD_QRY_FWD_MODE	(1 << 18)
+
 /* Broadcom header RX control (16 bit) */
 #define B53_BRCM_HDR_RX_DIS		0x60
 
-- 
2.17.1


^ permalink raw reply related

* [PATCH net-next v2 04/12] net: systemport: Fix reception of BPDUs
From: Florian Fainelli @ 2019-01-30  0:55 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, andrew, vivien.didelot, davem, idosch, jiri,
	ilias.apalodimas, ivan.khoronzhuk, roopa, nikolay
In-Reply-To: <20190130005548.2212-1-f.fainelli@gmail.com>

SYSTEMPORT has its RXCHK parser block that attempts to validate the
packet structures, unfortunately setting the L2 header check bit will
cause Bridge PDUs (BPDUs) to be incorrectly rejected because they look
like LLC/SNAP packets with a non-IPv4 or non-IPv6 Ethernet Type.

Fixes: 4e8aedfe78c7 ("net: systemport: Turn on offloads by default")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/ethernet/broadcom/bcmsysport.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index f9521d0274b7..f374c8ddf719 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -134,6 +134,10 @@ static void bcm_sysport_set_rx_csum(struct net_device *dev,
 
 	priv->rx_chk_en = !!(wanted & NETIF_F_RXCSUM);
 	reg = rxchk_readl(priv, RXCHK_CONTROL);
+	/* Clear L2 header checks, which would prevent BPDUs
+	 * from being received.
+	 */
+	reg &= ~RXCHK_L2_HDR_DIS;
 	if (priv->rx_chk_en)
 		reg |= RXCHK_EN;
 	else
-- 
2.17.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox