* [PATCH 1/3] net: dsa: Add DT bindings for Vitesse VSC73xx switches
From: Linus Walleij @ 2018-06-14 12:35 UTC (permalink / raw)
To: Andrew Lunn, Vivien Didelot, Florian Fainelli
Cc: netdev, openwrt-devel, LEDE Development List, Gabor Juhos,
Linus Walleij, devicetree
In-Reply-To: <20180614123534.8063-1-linus.walleij@linaro.org>
This adds the device tree bindings for the Vitesse VSC73xx
switches. We also add the vendor name for Vitesse.
Cc: devicetree@vger.kernel.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
.../bindings/net/dsa/vitesse,vsc73xx.txt | 81 +++++++++++++++++++
.../devicetree/bindings/vendor-prefixes.txt | 1 +
2 files changed, 82 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.txt
diff --git a/Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.txt b/Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.txt
new file mode 100644
index 000000000000..474cdba5fa37
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.txt
@@ -0,0 +1,81 @@
+Vitess VSC73xx Switches
+=======================
+
+This defines device tree bindings for the Vitesse VSC73xx switch chips.
+The Vitesse company has been acquired by Microsemi and Microsemi in turn
+acquired by Microchip but retains this vendor branding.
+
+The currently supported switch chips are:
+Vitesse VSC7385 SparX-G5 5+1-port Integrated Gigabit Ethernet Switch
+Vitesse VSC7388 SparX-G8 8-port Integrated Gigabit Ethernet Switch
+Vitesse VSC7395 SparX-G5e 5+1-port Integrated Gigabit Ethernet Switch
+Vitesse VSC7398 SparX-G8e 8-port Integrated Gigabit Ethernet Switch
+
+The device tree node is an SPI device so it must reside inside a SPI bus
+device tree node, see spi/spi-bus.txt
+
+Required properties:
+
+- compatible: must be exactly one of:
+ "vitesse,vsc7385"
+ "vitesse,vsc7388"
+ "vitesse,vsc7395"
+ "vitesse,vsc7398"
+- gpio-controller: indicates that this switch is also a GPIO controller,
+ see gpio/
+- #gpio-cells: this must be set to <2> and indicates that we are a twocell
+ GPIO controller.
+
+Optional properties:
+
+- reset-gpios: a handle to a GPIO line that can issue reset of the chip.
+ It should be tagged as active low.
+
+Required subnodes:
+
+See net/dsa/dsa.txt for a list of additional required and optional properties
+and subnodes of DSA switches.
+
+Examples:
+
+switch@0 {
+ compatible = "vitesse,vsc7395";
+ reg = <0>;
+ /* Specified for 2.5 MHz or below */
+ spi-max-frequency = <2500000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "lan1";
+ };
+ port@1 {
+ reg = <1>;
+ label = "lan2";
+ };
+ port@2 {
+ reg = <2>;
+ label = "lan3";
+ };
+ port@3 {
+ reg = <3>;
+ label = "lan4";
+ };
+ vsc: port@6 {
+ reg = <6>;
+ label = "cpu";
+ ethernet = <&gmac1>;
+ phy-mode = "rgmii";
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ pause;
+ };
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index b5f978a4cac6..e8473894700c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -385,6 +385,7 @@ v3 V3 Semiconductor
variscite Variscite Ltd.
via VIA Technologies, Inc.
virtio Virtual I/O Device Specification, developed by the OASIS consortium
+vitesse Vitesse Semiconductor Corporation
vivante Vivante Corporation
vocore VoCore Studio
voipac Voipac Technologies s.r.o.
--
2.17.1
^ permalink raw reply related
* [PATCH 0/3] DSA driver for Vitesse VSC73xx
From: Linus Walleij @ 2018-06-14 12:35 UTC (permalink / raw)
To: Andrew Lunn, Vivien Didelot, Florian Fainelli
Cc: netdev, openwrt-devel, LEDE Development List, Gabor Juhos,
Linus Walleij
This is my effort to get the VSC73xx switch chips working with
Linux.
It works for me with this device:
https://dflund.se/~triad/krad/itian-squareone/
Which has Vitesse VSC7395 embedded in it.
I got this device from Florian Fainelli who got it from Tomasz
Figa I think. It's cute.
The device has been run with custom firmware blobs in OpenWRT
ar71xx for years. Those download some code to the 8051 CPU
and that starts to run the show.
https://github.com/openwrt/openwrt/blob/master/target/linux/ar71xx/files/drivers/spi/spi-vsc7385.c
I strongly suspect these devices can just use this driver as
well and toss out that firmware, Linux will just step in and take
control instead. It's not even much traffic over SPI going on.
It also makes it possible for us to implement VLAN support on
top of this if there is interest.
The firmware mostly makes sense when using this device with
an EEPROM inside a stand-alone switch anyway. Linux should be
in control when we use it.
We can write our own firmware for this thing if we want. It's
not even hard (well for some definition of hard) it just requires
patience and time. Until then, just taking control of it using
SPI and disabling the 8051 CPU works just fine. The target device
was using exactly this method: SPI nothing else.
I boot it:
vsc73xx spi0.0: VSC7395 (rev: 0) switch found
vsc73xx spi0.0: iCPU disabled, no external memory
vsc73xx spi0.0: MAC for control frames: B2:BF:79:2F:A3:E1
vsc73xx spi0.0: set up the switch
libphy: dsa slave smi: probed
vsc73xx spi0.0: reset PHY - disallowed
Vitesse VSC7395 dsa-0.0:00: attached PHY driver [Vitesse VSC7395] (mii_bus:phy_addr=dsa-0.0:00, irq=POLL)
vsc73xx spi0.0: reset PHY - disallowed
Vitesse VSC7395 dsa-0.0:01: attached PHY driver [Vitesse VSC7395] (mii_bus:phy_addr=dsa-0.0:01, irq=POLL)
vsc73xx spi0.0: reset PHY - disallowed
Vitesse VSC7395 dsa-0.0:02: attached PHY driver [Vitesse VSC7395] (mii_bus:phy_addr=dsa-0.0:02, irq=POLL)
vsc73xx spi0.0: reset PHY - disallowed
Vitesse VSC7395 dsa-0.0:03: attached PHY driver [Vitesse VSC7395] (mii_bus:phy_addr=dsa-0.0:03, irq=POLL)
vsc73xx spi0.0: port 6: 1000 Mbit mode full duplex
DSA: tree 0 setup
Then I do like this:
ifconfig eth1 169.254.1.2 netmask 255.255.255.0 up
gemini-ethernet-port 6000c000.ethernet-port eth1: connected to PHY "fixed-0:00"
Generic PHY fixed-0:00: attached PHY driver [Generic PHY] (mii_bus:phy_addr=fixed-0:00, irq=POLL)
phy_id=0x00000000, phy_mode=rgmii
gemini-ethernet-port 6000c000.ethernet-port: set GMAC0 and GMAC1 to MII/RGMII mode
gemini-ethernet-port 6000c000.ethernet-port eth1: connect to RGMII
gemini-ethernet-port 6000c000.ethernet-port eth1: gmac_enable_irq device 1 enable
gemini-ethernet-port 6000c000.ethernet-port eth1: opened
IPv6: ADDRCONF(NETDEV_UP): eth1: link is not ready
root@gemini:/ gemini-ethernet-port 6000c000.ethernet-port eth1: connect to RGMII @ 1Gbit
IPv6: ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
Hey it works.
ifconfig lan1 up
vsc73xx spi0.0: enable port 0
IPv6: ADDRCONF(NETDEV_UP): lan1: link is not ready
IPv6: ADDRCONF(NETDEV_CHANGE): lan1: link becomes ready
vsc73xx spi0.0: port 0: 100 Mbit mode full duplex
vsc73xx spi0.0 lan1: Link is Up - 100Mbps/Full - flow control rx/tx
ifconfig
eth0 Link encap:Ethernet HWaddr F2:07:A7:EC:84:88
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:28
eth1 Link encap:Ethernet HWaddr FE:7F:EB:C9:05:DF
inet addr:169.254.1.2 Bcast:169.254.1.255 Mask:255.255.255.0
inet6 addr: fe80::fe7f:eb00:1c9:5df/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:58 errors:0 dropped:6 overruns:0 frame:0
TX packets:75 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:5532 (5.4 KiB) TX bytes:6814 (6.6 KiB)
Interrupt:29
lan1 Link encap:Ethernet HWaddr FE:7F:EB:C9:05:DF
inet6 addr: fe80::fc7f:ebff:fec9:5df/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:726 (726.0 B)
ethtool -S lan1
NIC statistics:
tx_packets: 13
tx_bytes: 1006
rx_packets: 0
rx_bytes: 0
RxEtherStatsOctets: 88396
RxEtherStatsPkts: 887
RxBroadcast+MulticastPkts: 34
RxTotalErrorPackets: 0
TxEtherStatsOctets: 86860
TxEtherStatsPkts: 874
TxBroadcast+MulticastPkts: 20
TxTotalErrorPackets: 0
Linus Walleij (3):
net: dsa: Add DT bindings for Vitesse VSC73xx switches
net: phy: vitesse: Add support for VSC73xx
net: dsa: Add Vitesse VSC73xx DSA router driver
.../bindings/net/dsa/vitesse,vsc73xx.txt | 81 +
.../devicetree/bindings/vendor-prefixes.txt | 1 +
drivers/net/dsa/Kconfig | 12 +
drivers/net/dsa/Makefile | 1 +
drivers/net/dsa/vitesse-vsc73xx.c | 1362 +++++++++++++++++
drivers/net/phy/vitesse.c | 162 ++
6 files changed, 1619 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.txt
create mode 100644 drivers/net/dsa/vitesse-vsc73xx.c
--
2.17.1
^ permalink raw reply
* Re: [PATCH] selftests: bpf: config: add config fragments
From: William Tu @ 2018-06-14 12:08 UTC (permalink / raw)
To: Anders Roxell
Cc: Daniel Borkmann, Alexei Starovoitov, Shuah Khan,
Linux Kernel Network Developers, LKML,
open list:KERNEL SELFTEST FRAMEWORK
In-Reply-To: <CADYN=9+3V4fpqbjh-X4VUVWd_X38XSYhEbZoRBffcx=-nMtF8g@mail.gmail.com>
On Thu, Jun 14, 2018 at 4:42 AM, Anders Roxell <anders.roxell@linaro.org> wrote:
> On 14 June 2018 at 13:06, William Tu <u9012063@gmail.com> wrote:
>> On Tue, Jun 12, 2018 at 5:08 PM, Daniel Borkmann <daniel@iogearbox.net> wrote:
>>> On 06/12/2018 01:05 PM, Anders Roxell wrote:
>>>> Tests test_tunnel.sh fails due to config fragments ins't enabled.
>>>>
>>>> Fixes: 933a741e3b82 ("selftests/bpf: bpf tunnel test.")
>>>> Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
>>>> ---
>>>>
>>>> All tests passes except ip6gretap that still fails. I'm unsure why.
>>>> Ideas?
>>
>> Hi Anders,
>>
>> ip6erspan is based on ip6gretap, does ip6erspan pass?
>
> it did pass when I was sending the email.
> However, I retested this on next-20180613 and now it fails.
>
Does 'ip -s link show' show any errors/dropped on ip6gretap device?
Thanks
William
^ permalink raw reply
* [PATCH bpf-net] selftests/bpf: delete xfrm tunnel when test exits.
From: William Tu @ 2018-06-14 12:01 UTC (permalink / raw)
To: netdev; +Cc: anders.roxell
Make the printting of bpf xfrm tunnel better and
cleanup xfrm state and policy when xfrm test finishes.
Signed-off-by: William Tu <u9012063@gmail.com>
---
tools/testing/selftests/bpf/test_tunnel.sh | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_tunnel.sh b/tools/testing/selftests/bpf/test_tunnel.sh
index aeb2901f21f4..7b1946b340be 100755
--- a/tools/testing/selftests/bpf/test_tunnel.sh
+++ b/tools/testing/selftests/bpf/test_tunnel.sh
@@ -608,28 +608,26 @@ setup_xfrm_tunnel()
test_xfrm_tunnel()
{
config_device
- #tcpdump -nei veth1 ip &
- output=$(mktemp)
- cat /sys/kernel/debug/tracing/trace_pipe | tee $output &
- setup_xfrm_tunnel
+ > /sys/kernel/debug/tracing/trace
+ setup_xfrm_tunnel
tc qdisc add dev veth1 clsact
tc filter add dev veth1 proto ip ingress bpf da obj test_tunnel_kern.o \
sec xfrm_get_state
ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
sleep 1
- grep "reqid 1" $output
+ grep "reqid 1" /sys/kernel/debug/tracing/trace
check_err $?
- grep "spi 0x1" $output
+ grep "spi 0x1" /sys/kernel/debug/tracing/trace
check_err $?
- grep "remote ip 0xac100164" $output
+ grep "remote ip 0xac100164" /sys/kernel/debug/tracing/trace
check_err $?
cleanup
if [ $ret -ne 0 ]; then
- echo -e ${RED}"FAIL: xfrm tunnel"${NC}
- return 1
- fi
- echo -e ${GREEN}"PASS: xfrm tunnel"${NC}
+ echo -e ${RED}"FAIL: xfrm tunnel"${NC}
+ return 1
+ fi
+ echo -e ${GREEN}"PASS: xfrm tunnel"${NC}
}
attach_bpf()
@@ -657,6 +655,10 @@ cleanup()
ip link del ip6geneve11 2> /dev/null
ip link del erspan11 2> /dev/null
ip link del ip6erspan11 2> /dev/null
+ ip xfrm policy delete dir out src 10.1.1.200/32 dst 10.1.1.100/32 2> /dev/null
+ ip xfrm policy delete dir in src 10.1.1.100/32 dst 10.1.1.200/32 2> /dev/null
+ ip xfrm state delete src 172.16.1.100 dst 172.16.1.200 proto esp spi 0x1 2> /dev/null
+ ip xfrm state delete src 172.16.1.200 dst 172.16.1.100 proto esp spi 0x2 2> /dev/null
}
cleanup_exit()
--
2.7.4
^ permalink raw reply related
* Re: [RFC PATCH RESEND] tcp: avoid F-RTO if SACK and timestamps are disabled
From: Ilpo Järvinen @ 2018-06-14 11:51 UTC (permalink / raw)
To: Michal Kubecek; +Cc: Yuchung Cheng, netdev, Eric Dumazet, LKML
In-Reply-To: <20180614093408.5e34ijwhome4t5yn@unicorn.suse.cz>
[-- Attachment #1: Type: text/plain, Size: 8186 bytes --]
On Thu, 14 Jun 2018, Michal Kubecek wrote:
> On Thu, Jun 14, 2018 at 11:42:43AM +0300, Ilpo Järvinen wrote:
> > On Wed, 13 Jun 2018, Yuchung Cheng wrote:
> > > On Wed, Jun 13, 2018 at 9:55 AM, Michal Kubecek <mkubecek@suse.cz> wrote:
> > > >
> > > > When F-RTO algorithm (RFC 5682) is used on connection without both SACK and
> > > > timestamps (either because of (mis)configuration or because the other
> > > > endpoint does not advertise them), specific pattern loss can make RTO grow
> > > > exponentially until the sender is only able to send one packet per two
> > > > minutes (TCP_RTO_MAX).
> > > >
> > > > One way to reproduce is to
> > > >
> > > > - make sure the connection uses neither SACK nor timestamps
> > > > - let tp->reorder grow enough so that lost packets are retransmitted
> > > > after RTO (rather than when high_seq - snd_una > reorder * MSS)
> > > > - let the data flow stabilize
> > > > - drop multiple sender packets in "every second" pattern
> >
> > Hmm? What is deterministically dropping every second packet for a
> > particular flow that has RTOs in between?
>
> AFAIK the customer we managed to push to investigate the primary source
> of the packet loss identified some problems with their load balancing
> solution but I don't have more details. For the record, the loss didn't
> last through the phase of RTO growing exponentially (so that there were
> no lost retransmissions) but did last long enough to drop at least 20
> packets. With the exponential growth, that was enough for RTO to reach
> TCP_RTO_MAX (120s) and make the connection essentially stalled.
>
> Actually, it doesn't need to be exactly "every second". As long as you
> don't lose two consecutive segments (which would allow you to fall back
> in step (2a)), you can have more than one received segments between them
> and get the same issue.
>
> > Years back I was privately contacted by somebody from a middlebox vendor
> > for a case with very similar exponentially growing RTO due to the FRTO
> > heuristic. It turned out that they didn't want to send dupacks for
> > out-of-order packets because they wanted to keep the TCP side of their
> > deep packet inspection middlebox primitive. He claimed that the middlebox
> > doesn't need to send dupacks because there could be such a TCP
> > implementation that too doesn't do them either (not that he had anything
> > to point to besides their middlebox ;-)), which according to him was
> > not required because of his intepretation of RFC793 (IIRC). ...Nevermind
> > anything that has occurred since that era.
> >
> > ...Back then, I also envisioned in that mail exchange with him that a
> > middlebox could break FRTO by always forcing a drop on the key packet
> > FRTO depends on. Ironically, that is exactly what is required to trigger
> > this issue? Sure, every a heuristic can be fooled if a deterministic (or
> > crafted) pattern is introduced to defeat that particular heuristic.
>
> OK, let me elaborate a bit more about the background. Within last few
> months, we had six different reports of TCP stalls (typically for NFS
> connections alternating between idle period and bulk transfers) which
> started after an upgrade from SLE11 (with 3.0 kernel) to SLE12 SP2 or
> SP3 (both 4.4 kernel).
>
> Two of them were analysed down to the NAS on the other side which was
> sending SACK blocks violating the RFC in two different ways - as
> described in thread "TCP one-by-one acking - RFC interpretation
> question".
>
> Three of them do not seem to show any apparent RFC violation and the
> problem is only in RTO doubling with each retransmission while there are
> no usable replies that could be used for RTT estimate (in the absence of
> both SACK and timestamps).
>
> For the sake of completeness, there was also one report from two days
> ago which looked almost the same but in the end it turned out that in
> this case, SLES (with Firefox) was the receiver and sender was actually
> Windows 2016 server with Microsoft IIS.
>
> > I'd prefer that networks "dropping every second packet" of a flow to be
> > fixed rather than FRTO?
>
> Yes, that was my first reaction that their primary focus should be the
> lossy network. However, it's not behaving like this all the time, the
> periods of loss are relatively short - but long enough to trigger the
> "RTO loop".
>
> > In addition, one could even argue that the sender is sending whole the
> > time with lower and lower rate (given the exponentially increasing RTO)
> > and still gets losses, so that a further rate reduction would be the
> > correct action. ...But take this intuitive reasoning with some grain of
> > salt (that is, I can see reasons myself to disagree with it :-)).
>
> As I explained above, the loss was over by the time of first RTO
> retransmission. I should probably have made that clear in the commit
> message.
Right. I had a preconveived mental image from another, similar case which
requires a loss after each RTO but it does seem to be case here (and I
only took look into the drill after sending the first mail out).
> > > > - either there is no new data to send or acks received in response to new
> > > > data are also window updates (i.e. not dupacks by definition)
> >
> > Can you explain what exactly do you mean with this "no new data to send"
> > condition here as F-RTO is/should not be used if there's no new data to
> > send?!?
>
> AFAICS RFC 5682 is not explicit about this and offers multiple options.
> Anyway, this is not essential and in most of the customer provided
> captures, it wasn't the case.
Lacking the new segments is essential for hiding the actual bug as the
trace would look weird otherwise with a burst of new data segments (due
to the other bug).
> > ...Or, why is the receiver going against SHOULD in RFC5681:
> > "A TCP receiver SHOULD send an immediate duplicate ACK when an out-
> > of-order segment arrives."
> > ? ...And yes, I know there's this very issue with window updates masking
> > duplicate ACKs in Linux TCP receiver but I was met with some skepticism
> > on whether fixing it is worth it or not.
>
> Normally, we would have timestamps (and even SACK). Without them, you
> cannot reliably recognize a dupack with changed window size from
> a spontaneous window update.
No! The window should not update window on ACKs the receiver intends to
designate as "duplicate ACKs". That is not without some potential cost
though as it requires delaying window updates up to the next cumulative
ACK. In the non-SACK series one of the changes is fixing this for
non-SACK Linux TCP flows.
> > > Acked-by: Yuchung Cheng <ycheng@google.com>
> > >
> > > Thanks for the patch (and packedrill test)! I would encourage
> > > submitting an errata to F-RTO RFC about this case.
> >
> > Unless there's a convincing explination how such a drop pattern would
> > occur in real world except due to serious brokeness/misconfiguration on
> > network side (that should not be there), I'm not that sure it's exactly
> > what erratas are meant for.
>
> As explained above, this commit was not inspired by some theoretical
> study trying to find dark corner cases, it was result of investigation
> of reports from multiple customer encountering the problem in
> real-life. Sure, there was always something bad, namely SACK/timestamps
> being disabled and network losing packets, but the effect (one packet
> per two minutes) is so disastrous that I believe it should be handled.
Yes, I was guessing/hoping that the every second packet stuff was just for
the reproducer (but of course it could have been something that is
just very broken - it wouldn't surprise me that much :-(). Now, however,
I think if the FRTO undo bug is fixed, the main problem that remains is
that with new data to send, then FRTO logic will not send anything after
the first ACK and there won't be second ACK leading to that RTO loop.
Given that FRTO RFC already recommends falling back to normal RTO recovery
in the cases where there's no new data to send, I don't think there's
anything that needs to be changed in the RFC that would warrant an errata.
--
i.
^ permalink raw reply
* Re: [PATCHv2 net-next] sctp: add support for SCTP_REUSE_PORT sockopt
From: Neil Horman @ 2018-06-14 11:49 UTC (permalink / raw)
To: Xin Long
Cc: network dev, linux-sctp, Marcelo Ricardo Leitner, Michael Tuexen,
davem
In-Reply-To: <26fda4cd22604d88a68a58c2b007231984e5f4f0.1528947888.git.lucien.xin@gmail.com>
On Thu, Jun 14, 2018 at 11:44:48AM +0800, Xin Long wrote:
> This feature is actually already supported by sk->sk_reuse which can be
> set by socket level opt SO_REUSEADDR. But it's not working exactly as
> RFC6458 demands in section 8.1.27, like:
>
> - This option only supports one-to-one style SCTP sockets
> - This socket option must not be used after calling bind()
> or sctp_bindx().
>
> Besides, SCTP_REUSE_PORT sockopt should be provided for user's programs.
> Otherwise, the programs with SCTP_REUSE_PORT from other systems will not
> work in linux.
>
> To separate it from the socket level version, this patch adds 'reuse' in
> sctp_sock and it works pretty much as sk->sk_reuse, but with some extra
> setup limitations that are needed when it is being enabled.
>
> "It should be noted that the behavior of the socket-level socket option
> to reuse ports and/or addresses for SCTP sockets is unspecified", so it
> leaves SO_REUSEADDR as is for the compatibility.
>
> Note that the name SCTP_REUSE_PORT is kind of confusing, it is identical
> to SO_REUSEADDR with some extra restriction, so here it uses 'reuse' in
> sctp_sock instead of 'reuseport'. As for sk->sk_reuseport support for
> SCTP, it will be added in another patch.
>
> Thanks to Neil to make this clear.
>
> v1->v2:
> - add sctp_sk->reuse to separate it from the socket level version.
>
Thanks Xin, Assuming some documentation for man sctp(7) is in the works
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply
* Re: mainline: x86_64: kernel panic: RIP: 0010:__xfrm_policy_check+0xcb/0x690
From: Anders Roxell @ 2018-06-14 11:47 UTC (permalink / raw)
To: William Tu
Cc: Steffen Klassert, Naresh Kamboju, Networking, David S. Miller,
Herbert Xu, open list:KERNEL SELFTEST FRAMEWORK, open list
In-Reply-To: <CALDO+SY6BGctJtZamvATrXDpy7zFCCGid5kqsZRQ7mtFUdxZ-Q@mail.gmail.com>
On 14 June 2018 at 13:15, William Tu <u9012063@gmail.com> wrote:
> On Tue, Jun 12, 2018 at 5:09 AM, Anders Roxell <anders.roxell@linaro.org> wrote:
>> On 12 June 2018 at 10:34, Steffen Klassert <steffen.klassert@secunet.com> wrote:
>>> On Mon, Jun 11, 2018 at 10:11:46PM +0530, Naresh Kamboju wrote:
>>>> Kernel panic on x86_64 machine running mainline 4.17.0 kernel while testing
>>>> selftests bpf test_tunnel.sh test caused this kernel panic.
>>>> I have noticed this kernel panic start happening from
>>>> 4.17.0-rc7-next-20180529 and still happening on 4.17.0-next-20180608.
>>>>
>>>> [ 213.638287] BUG: unable to handle kernel NULL pointer dereference
>>>> at 0000000000000008
>>>> ++[ ip xfrm poli 213.674036] PGD 0 P4D 0
>>>> [ 213.674118] audit: type=1327 audit(1528917683.623:7):
>>>> proctitle=6970007866726D00706F6C69637900616464007372630031302E312E312E3130302F3332006473740031302E312E312E3230302F33320064697200696E00746D706C00737263003137322E31362E312E31303000647374003137322E31362E312E3230300070726F746F006573700072657169640031006D6F64650074756E6E
>>>> [ 213.677950] Oops: 0000 [#1] SMP PTI
>>>> cy[ add src 10.1. 213.677952] CPU: 2 PID: 0 Comm: swapper/2 Tainted:
>>>> G W 4.17.0-next-20180608 #1
>>>> [ 213.677953] Hardware name: Supermicro SYS-5019S-ML/X11SSH-F, BIOS
>>>> 2.0b 07/27/2017
>>>> [ 213.726998] RIP: 0010:__xfrm_policy_check+0xcb/0x690
>>>> [ 213.731962] Code: 80 3d 0a d8 f1 00 00 0f 84 c1 02 00 00 4c 8b 25
>>>> 2b af f4 00 e8 66 a6 6a ff 85 c0 74 0d 80 3d eb d7 f1 00 00 0f 84 d5
>>>> 02 00 00 <49> 8b 44 24 08 48 85 c0 74 0c 48 8d b5 78 ff ff ff 4c 89 ff
>>>> ff d0
>>>
>>> This looks like a bug that I've seen already. If it is what I think,
>>> then commit 2c205dd3981f ("netfilter: add struct nf_nat_hook and use
>>> it") introduced this bug.
>>>
>>> There was already a fix for this on the netdev list, but
>>> I don't know the current status of that patch:
>>>
>>> https://patchwork.ozlabs.org/patch/921387/
>>
>> Hi, I applied the patch and ran bpf/test_tunnel.sh and I I couldn't
>> see any crash.
>> However, the script never returned (I had to Ctrl+c to get back), any ideas ?
>> See log from the test below.
>>
>> Cheers,
>> Anders
>>
>> [0;92mPASS: xfrm tunnel[0m
>
> Hi Anders,
> I think it should return 0 if you reach the above line.
Yes it should but it didn't.
However, when I reran the test_tunnel.sh today with kernel next-20180613
I got back from from the script and the test passed "PASS: xfrm tunnel".
So I'm not sure what happened before. =/
> The console output looks pretty messy due to using 'tee'
> I will send a patch to make the output more readable.
Great.
Cheers,
Anders
^ permalink raw reply
* Re: [RFC v2, net-next, PATCH 4/4] net/cpsw_switchdev: add switchdev mode of operation on cpsw driver
From: Ilias Apalodimas @ 2018-06-14 11:43 UTC (permalink / raw)
Cc: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, ivecera,
andrew, f.fainelli, francois.ozog, yogeshs, spatton, Jose.Abreu
In-Reply-To: <20180614113958.GC2518@nanopsycho.orion>
On Thu, Jun 14, 2018 at 01:39:58PM +0200, Jiri Pirko wrote:
> Thu, Jun 14, 2018 at 01:34:04PM CEST, ilias.apalodimas@linaro.org wrote:
> >On Thu, Jun 14, 2018 at 01:30:28PM +0200, Jiri Pirko wrote:
> >> Thu, Jun 14, 2018 at 01:11:30PM CEST, ilias.apalodimas@linaro.org wrote:
> >>
> >> [...]
> >>
> >> >@@ -2711,6 +2789,10 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
> >> > if (of_property_read_bool(node, "dual_emac"))
> >> > data->switch_mode = CPSW_DUAL_EMAC;
> >> >
> >> >+ /* switchdev overrides DTS */
> >> >+ if (IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV))
> >> >+ data->switch_mode = CPSW_SWITCHDEV;
> >>
> >> So you force CPSW_SWITCHDEV mode if the CONFIG_TI_CPSW_SWITCHDEV is
> >> enabled. That does not sound right. I think that user should tell what
> >> mode does he want regardless what the kernel config is.
> >We discussed this during the V1 of the RFC. Yes it doesn't seem good, but the
> >device currently configures the modes using DTS (which is not correct). I choose
> >the .config due to that. I can't think of anything better, but i am open to
> >suggestions
>
> Agreed that DTS does fit as well. I think that this might be a job for
> devlink parameters (patchset is going to be sent upstream next week).
> You do have 1 bus address for the whole device (both ports), right?
>
Yes devlink sounds reasonable. I thyink there's only one bus for it, but then
again i am far from an expert on the hardware interrnals. Grygorii can correct
me if i am wrong.
Thanks for taking time to read this,
Ilias
^ permalink raw reply
* Re: [PATCH] selftests: bpf: config: add config fragments
From: Anders Roxell @ 2018-06-14 11:42 UTC (permalink / raw)
To: William Tu
Cc: Daniel Borkmann, Alexei Starovoitov, Shuah Khan,
Linux Kernel Network Developers, LKML,
open list:KERNEL SELFTEST FRAMEWORK
In-Reply-To: <CALDO+SY3qNYAOSiYC3645C7YY9LSx7ggg0GjY76m4TbBfF_t3A@mail.gmail.com>
On 14 June 2018 at 13:06, William Tu <u9012063@gmail.com> wrote:
> On Tue, Jun 12, 2018 at 5:08 PM, Daniel Borkmann <daniel@iogearbox.net> wrote:
>> On 06/12/2018 01:05 PM, Anders Roxell wrote:
>>> Tests test_tunnel.sh fails due to config fragments ins't enabled.
>>>
>>> Fixes: 933a741e3b82 ("selftests/bpf: bpf tunnel test.")
>>> Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
>>> ---
>>>
>>> All tests passes except ip6gretap that still fails. I'm unsure why.
>>> Ideas?
>
> Hi Anders,
>
> ip6erspan is based on ip6gretap, does ip6erspan pass?
it did pass when I was sending the email.
However, I retested this on next-20180613 and now it fails.
Cheers,
Anders
^ permalink raw reply
* Re: [RFC v2, net-next, PATCH 4/4] net/cpsw_switchdev: add switchdev mode of operation on cpsw driver
From: Jiri Pirko @ 2018-06-14 11:39 UTC (permalink / raw)
To: Ilias Apalodimas
Cc: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, ivecera,
andrew, f.fainelli, francois.ozog, yogeshs, spatton, Jose.Abreu
In-Reply-To: <20180614113404.GB32505@apalos>
Thu, Jun 14, 2018 at 01:34:04PM CEST, ilias.apalodimas@linaro.org wrote:
>On Thu, Jun 14, 2018 at 01:30:28PM +0200, Jiri Pirko wrote:
>> Thu, Jun 14, 2018 at 01:11:30PM CEST, ilias.apalodimas@linaro.org wrote:
>>
>> [...]
>>
>> >@@ -2711,6 +2789,10 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
>> > if (of_property_read_bool(node, "dual_emac"))
>> > data->switch_mode = CPSW_DUAL_EMAC;
>> >
>> >+ /* switchdev overrides DTS */
>> >+ if (IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV))
>> >+ data->switch_mode = CPSW_SWITCHDEV;
>>
>> So you force CPSW_SWITCHDEV mode if the CONFIG_TI_CPSW_SWITCHDEV is
>> enabled. That does not sound right. I think that user should tell what
>> mode does he want regardless what the kernel config is.
>We discussed this during the V1 of the RFC. Yes it doesn't seem good, but the
>device currently configures the modes using DTS (which is not correct). I choose
>the .config due to that. I can't think of anything better, but i am open to
>suggestions
Agreed that DTS does fit as well. I think that this might be a job for
devlink parameters (patchset is going to be sent upstream next week).
You do have 1 bus address for the whole device (both ports), right?
^ permalink raw reply
* Re: [PATCH net-next] sctp: define sctp_packet_gso_append to build GSO frames
From: Neil Horman @ 2018-06-14 11:36 UTC (permalink / raw)
To: David Miller
Cc: lucien.xin, netdev, linux-sctp, marcelo.leitner, eric.dumazet
In-Reply-To: <20180613.190559.1358933130944096340.davem@davemloft.net>
On Wed, Jun 13, 2018 at 07:05:59PM -0700, David Miller wrote:
> From: Neil Horman <nhorman@tuxdriver.com>
> Date: Wed, 13 Jun 2018 20:46:43 -0400
>
> > Do you have any performance numbers to compare with and without this
> > patch? Adding a function like this implies that any fixes that go
> > into skb_gro_receive now need to be evaluated for this function too,
> > which means theres an implied overhead in maintaining it. If we're
> > signing up for that, I'd like to know that theres a significant
> > performance benefit.
>
> Neil, I asked Xin and Marcelo to do this.
>
> There is no reason for GSO code to use a GRO helper.
>
> And this is, in particular, blocking some skb_gro_receive() surgery
> I plan to perform.
>
I agree, I wasn't aware of your intentions regarding skb_gro_receive, and have
acked the patch
Neil
^ permalink raw reply
* Re: [PATCH net-next] sctp: define sctp_packet_gso_append to build GSO frames
From: Neil Horman @ 2018-06-14 11:35 UTC (permalink / raw)
To: Xin Long
Cc: network dev, linux-sctp, Marcelo Ricardo Leitner, davem,
Eric Dumazet
In-Reply-To: <CADvbK_czQPXnzP723q6rH1c9Aps6RYgtdOe8eN6H75KHquwsoQ@mail.gmail.com>
On Thu, Jun 14, 2018 at 09:21:52AM +0800, Xin Long wrote:
> On Thu, Jun 14, 2018 at 8:46 AM, Neil Horman <nhorman@tuxdriver.com> wrote:
> > On Thu, Jun 14, 2018 at 07:37:02AM +0800, Xin Long wrote:
> >> Now sctp GSO uses skb_gro_receive() to append the data into head
> >> skb frag_list. However it actually only needs very few code from
> >> skb_gro_receive(). Besides, NAPI_GRO_CB has to be set while most
> >> of its members are not needed here.
> >>
> >> This patch is to add sctp_packet_gso_append() to build GSO frames
> >> instead of skb_gro_receive(), and it would avoid many unnecessary
> >> checks and make the code clearer.
> >>
> >> Note that sctp will use page frags instead of frag_list to build
> >> GSO frames in another patch. But it may take time, as sctp's GSO
> >> frames may have different size. skb_segment() can only split it
> >> into the frags with the same size, which would break the border
> >> of sctp chunks.
> >>
> >> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> > Do you have any performance numbers to compare with and without this patch?
> > Adding a function like this implies that any fixes that go into skb_gro_receive
> > now need to be evaluated for this function too, which means theres an implied
> > overhead in maintaining it. If we're signing up for that, I'd like to know that
> > theres a significant performance benefit.
> Hi Neil,
>
> I don't think there's a noticeable performance benefit since it's
> just avoided some checks and variables settings.
>
> The new function makes SCTP GSO code clearer and readable,
> as skb_gro_receive() should only be used in the GRO code paths,
> it's confusing in sctp tx path.
>
> We're doing this, actually because skb_gro_receive() is being
> changed now, it would not be suitable for SCTP GSO, see:
> https://www.spinics.net/lists/netdev/msg507716.html
>
Ok, I'm not on board if the only reason was to improve readability, as I didn't
want to maintain two separate code paths, but if skb_gro_receive isn't going to
be useable, then I'm ok with it
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply
* Re: [RFC v2, net-next, PATCH 4/4] net/cpsw_switchdev: add switchdev mode of operation on cpsw driver
From: Ilias Apalodimas @ 2018-06-14 11:34 UTC (permalink / raw)
To: Jiri Pirko
Cc: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, ivecera,
andrew, f.fainelli, francois.ozog, yogeshs, spatton, Jose.Abreu
In-Reply-To: <20180614113028.GB2518@nanopsycho.orion>
On Thu, Jun 14, 2018 at 01:30:28PM +0200, Jiri Pirko wrote:
> Thu, Jun 14, 2018 at 01:11:30PM CEST, ilias.apalodimas@linaro.org wrote:
>
> [...]
>
> >@@ -2711,6 +2789,10 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
> > if (of_property_read_bool(node, "dual_emac"))
> > data->switch_mode = CPSW_DUAL_EMAC;
> >
> >+ /* switchdev overrides DTS */
> >+ if (IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV))
> >+ data->switch_mode = CPSW_SWITCHDEV;
>
> So you force CPSW_SWITCHDEV mode if the CONFIG_TI_CPSW_SWITCHDEV is
> enabled. That does not sound right. I think that user should tell what
> mode does he want regardless what the kernel config is.
We discussed this during the V1 of the RFC. Yes it doesn't seem good, but the
device currently configures the modes using DTS (which is not correct). I choose
the .config due to that. I can't think of anything better, but i am open to
suggestions
^ permalink raw reply
* Re: [RFC v2, net-next, PATCH 4/4] net/cpsw_switchdev: add switchdev mode of operation on cpsw driver
From: Ilias Apalodimas @ 2018-06-14 11:32 UTC (permalink / raw)
To: Jiri Pirko
Cc: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, ivecera,
andrew, f.fainelli, francois.ozog, yogeshs, spatton, Jose.Abreu
In-Reply-To: <20180614112349.GA2518@nanopsycho.orion>
On Thu, Jun 14, 2018 at 01:23:49PM +0200, Jiri Pirko wrote:
> Thu, Jun 14, 2018 at 01:11:30PM CEST, ilias.apalodimas@linaro.org wrote:
> >This patch enables switchdev funtionality on the driver based on a
> >.config option(CONFIG_TI_CPSW_SWITCHDEV). CPSW driver used a DTS option
> >called dual_emac to enable switch or dual emac mode. The new config option
> >will override this configuration.
> >
> >It creates 2 ports, eth0 and eth1(that can be renamed to sw0p1 and sw0p2
> >via udev rules).
>
> Actually the current udev should rename the netdevs by default,
> according the phys_port_name. Could you check?
I will if i manage to compile udev properly for this board
^ permalink raw reply
* Re: [RFC v2, net-next, PATCH 4/4] net/cpsw_switchdev: add switchdev mode of operation on cpsw driver
From: Jiri Pirko @ 2018-06-14 11:30 UTC (permalink / raw)
To: Ilias Apalodimas
Cc: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, ivecera,
andrew, f.fainelli, francois.ozog, yogeshs, spatton, Jose.Abreu
In-Reply-To: <1528974690-31600-5-git-send-email-ilias.apalodimas@linaro.org>
Thu, Jun 14, 2018 at 01:11:30PM CEST, ilias.apalodimas@linaro.org wrote:
[...]
>@@ -2711,6 +2789,10 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
> if (of_property_read_bool(node, "dual_emac"))
> data->switch_mode = CPSW_DUAL_EMAC;
>
>+ /* switchdev overrides DTS */
>+ if (IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV))
>+ data->switch_mode = CPSW_SWITCHDEV;
So you force CPSW_SWITCHDEV mode if the CONFIG_TI_CPSW_SWITCHDEV is
enabled. That does not sound right. I think that user should tell what
mode does he want regardless what the kernel config is.
^ permalink raw reply
* Re: [RFC v2, net-next, PATCH 4/4] net/cpsw_switchdev: add switchdev mode of operation on cpsw driver
From: Jiri Pirko @ 2018-06-14 11:23 UTC (permalink / raw)
To: Ilias Apalodimas
Cc: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, ivecera,
andrew, f.fainelli, francois.ozog, yogeshs, spatton, Jose.Abreu
In-Reply-To: <1528974690-31600-5-git-send-email-ilias.apalodimas@linaro.org>
Thu, Jun 14, 2018 at 01:11:30PM CEST, ilias.apalodimas@linaro.org wrote:
>This patch enables switchdev funtionality on the driver based on a
>.config option(CONFIG_TI_CPSW_SWITCHDEV). CPSW driver used a DTS option
>called dual_emac to enable switch or dual emac mode. The new config option
>will override this configuration.
>
>It creates 2 ports, eth0 and eth1(that can be renamed to sw0p1 and sw0p2
>via udev rules).
Actually the current udev should rename the netdevs by default,
according the phys_port_name. Could you check?
^ permalink raw reply
* Re: [PATCH v2 3/5] batman: use BIT_ULL for NL80211_STA_INFO_* attribute types
From: Sven Eckelmann @ 2018-06-14 11:20 UTC (permalink / raw)
To: Johannes Berg
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r,
linux-wireless-u79uwXL29TY76Z2rM5mHXA, Omer Efrat
In-Reply-To: <1528974316.26847.0.camel-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 709 bytes --]
On Donnerstag, 14. Juni 2018 13:05:16 CEST Johannes Berg wrote:
[...]
> > in commit 739960f128e5 ("cfg80211/nl80211: Add support for
> > NL80211_STA_INFO_RX_DURATION")
>
> Yeah, which actually means this patch isn't needed?
>
> BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT) is fine since
> NL80211_STA_INFO_EXPECTED_THROUGHPUT is actually == 27.
Hadn't verified this before but this would make sense. So no fixes here - just
some "cleanup" patch to make these tests more consistent. Thanks for checking.
@Omer: If you want it as cleanup patch then make it clear in the patch that
the warning you've showed here is not actually not something which you will
see in in the modified code.
Kind regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: mainline: x86_64: kernel panic: RIP: 0010:__xfrm_policy_check+0xcb/0x690
From: William Tu @ 2018-06-14 11:15 UTC (permalink / raw)
To: Anders Roxell
Cc: Steffen Klassert, Naresh Kamboju, Networking, David S. Miller,
herbert, open list:KERNEL SELFTEST FRAMEWORK, open list
In-Reply-To: <CADYN=9LztFGUOb-RaEByN-G-E1MpnEv_HtZtObhyZUWWt0nffg@mail.gmail.com>
On Tue, Jun 12, 2018 at 5:09 AM, Anders Roxell <anders.roxell@linaro.org> wrote:
> On 12 June 2018 at 10:34, Steffen Klassert <steffen.klassert@secunet.com> wrote:
>> On Mon, Jun 11, 2018 at 10:11:46PM +0530, Naresh Kamboju wrote:
>>> Kernel panic on x86_64 machine running mainline 4.17.0 kernel while testing
>>> selftests bpf test_tunnel.sh test caused this kernel panic.
>>> I have noticed this kernel panic start happening from
>>> 4.17.0-rc7-next-20180529 and still happening on 4.17.0-next-20180608.
>>>
>>> [ 213.638287] BUG: unable to handle kernel NULL pointer dereference
>>> at 0000000000000008
>>> ++[ ip xfrm poli 213.674036] PGD 0 P4D 0
>>> [ 213.674118] audit: type=1327 audit(1528917683.623:7):
>>> proctitle=6970007866726D00706F6C69637900616464007372630031302E312E312E3130302F3332006473740031302E312E312E3230302F33320064697200696E00746D706C00737263003137322E31362E312E31303000647374003137322E31362E312E3230300070726F746F006573700072657169640031006D6F64650074756E6E
>>> [ 213.677950] Oops: 0000 [#1] SMP PTI
>>> cy[ add src 10.1. 213.677952] CPU: 2 PID: 0 Comm: swapper/2 Tainted:
>>> G W 4.17.0-next-20180608 #1
>>> [ 213.677953] Hardware name: Supermicro SYS-5019S-ML/X11SSH-F, BIOS
>>> 2.0b 07/27/2017
>>> [ 213.726998] RIP: 0010:__xfrm_policy_check+0xcb/0x690
>>> [ 213.731962] Code: 80 3d 0a d8 f1 00 00 0f 84 c1 02 00 00 4c 8b 25
>>> 2b af f4 00 e8 66 a6 6a ff 85 c0 74 0d 80 3d eb d7 f1 00 00 0f 84 d5
>>> 02 00 00 <49> 8b 44 24 08 48 85 c0 74 0c 48 8d b5 78 ff ff ff 4c 89 ff
>>> ff d0
>>
>> This looks like a bug that I've seen already. If it is what I think,
>> then commit 2c205dd3981f ("netfilter: add struct nf_nat_hook and use
>> it") introduced this bug.
>>
>> There was already a fix for this on the netdev list, but
>> I don't know the current status of that patch:
>>
>> https://patchwork.ozlabs.org/patch/921387/
>
> Hi, I applied the patch and ran bpf/test_tunnel.sh and I I couldn't
> see any crash.
> However, the script never returned (I had to Ctrl+c to get back), any ideas ?
> See log from the test below.
>
> Cheers,
> Anders
>
> [0;92mPASS: xfrm tunnel[0m
Hi Anders,
I think it should return 0 if you reach the above line.
The console output looks pretty messy due to using 'tee'
I will send a patch to make the output more readable.
Thanks
William
^ permalink raw reply
* Re: [BUG] net: stmmac: socfpga ethernet no longer working on linux-next
From: Marek Vasut @ 2018-06-14 10:59 UTC (permalink / raw)
To: Jose Abreu, Dinh Nguyen, netdev; +Cc: David Miller, clabbe, Dinh Nguyen
In-Reply-To: <dbc3dc9b-7eaf-2480-74a7-a25bcb9428e9@synopsys.com>
On 06/14/2018 10:18 AM, Jose Abreu wrote:
> On 14-06-2018 08:38, Jose Abreu wrote:
>> Hello,
>>
>> On 13-06-2018 21:46, Dinh Nguyen wrote:
>>> Hi,
>>>
>>> The stmmac ethernet has stopped working in linux-next and linus/master
>>> branch(v4.17-11782-gbe779f03d563)
>>>
>>> It appears that the stmmac ethernet has stopped working after these 2 commits:
>>>
>>> 4dbbe8dde848 net: stmmac: Add support for U32 TC filter using Flexible RX Parser
>>> 5f0456b43140 net: stmmac: Implement logic to automatically select HW Interface
>>>
>>> If I move to this commit "565020aaeebf net: stmmac: Disable ACS
>>> Feature for GMAC >= 4", then the stmmac works again on SoCFPGA.
>>>
>>> I was following this thread:
>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__www.spinics.net_lists_netdev_msg502858.html&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=yaVFU4TjGY0gVF8El1uKcisy6TPsyCl9uN7Wsis-qhY&m=fvPkLp2xlWolmIYwoFLmALhxlycg1w0UmxiYdT7qojc&s=aC4a2U3X_siDxSNz3c5OeadhEJWll31yP-oi5nNar94&e=
>>>
>>> Was wondering if there was a patch to fix dwmac-sun8i that the socfpga
>>> platform needs as well?
>> Probably. I will check and get back to you ASAP.
>
> This seems to be a different problem. Can you send me your dmesg
> log and DT bindings you are using?
arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts
for example fails for me in next/master. Worked on 4.17-rc7.
--
Best regards,
Marek Vasut
^ permalink raw reply
* [RFC v2, net-next, PATCH 4/4] net/cpsw_switchdev: add switchdev mode of operation on cpsw driver
From: Ilias Apalodimas @ 2018-06-14 11:11 UTC (permalink / raw)
To: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, jiri,
ivecera, andrew, f.fainelli
Cc: francois.ozog, yogeshs, spatton, Jose.Abreu, Ilias Apalodimas
In-Reply-To: <1528974690-31600-1-git-send-email-ilias.apalodimas@linaro.org>
This patch enables switchdev funtionality on the driver based on a
.config option(CONFIG_TI_CPSW_SWITCHDEV). CPSW driver used a DTS option
called dual_emac to enable switch or dual emac mode. The new config option
will override this configuration.
It creates 2 ports, eth0 and eth1(that can be renamed to sw0p1 and sw0p2
via udev rules).
sw0p1 and sw0p2 are the netdev interfaces connected to PHY devices.
This hardware also has a CPU port which is configured invidividually in
the case of VLANs.
On device init all netdevices (including the CPU port) will operate on
VLAN 0. sw0p1 and sw0p2 will operate as normal netdev interfaces.
Once they are added in a bridge the default bridge vlan will not be added
to the CPU port. In order to get an ip address on br0 you'll need to add
the CPU port on that vlan by issuing:
bridge vlan add dev br0 vid <vid> pvid untagged self
Multicast traffic:
setting IFF_MULTICAST on and off will affect registered multicast on that
port(if enabled port will be added on registered multicast traffic mask).
This muct occur before adding VLANs on the interfaces. If you change the
flag after the VLAN configuration you need to re-issue the VLAN config
commands.
MDBs/FDBs:
If the CPU port is member of the appropriate VLANs then switchdev API
will add FDB/MDB entries uppon detection. If the CPU port is not a member
the user can manually specify the entries.
ALE_P0_UNI_FLOOD will be enabled when the first interface joins the bridge
and will be disabled once the last interface leaves the bridge
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
drivers/net/ethernet/ti/Kconfig | 9 +
drivers/net/ethernet/ti/Makefile | 1 +
drivers/net/ethernet/ti/cpsw.c | 306 +++++++++++++++++++++-
drivers/net/ethernet/ti/cpsw_priv.h | 2 +
drivers/net/ethernet/ti/cpsw_switchdev.c | 418 +++++++++++++++++++++++++++++++
drivers/net/ethernet/ti/cpsw_switchdev.h | 4 +
6 files changed, 731 insertions(+), 9 deletions(-)
create mode 100644 drivers/net/ethernet/ti/cpsw_switchdev.c
create mode 100644 drivers/net/ethernet/ti/cpsw_switchdev.h
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index 9263d63..a299d86 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -73,6 +73,15 @@ config TI_CPSW
To compile this driver as a module, choose M here: the module
will be called cpsw.
+config TI_CPSW_SWITCHDEV
+ bool "TI CPSW switchdev support"
+ depends on TI_CPSW
+ depends on NET_SWITCHDEV
+ help
+ Enable switchdev support on TI's CPSW Ethernet Switch.
+
+ This will allow you to configure the switch using standard tools.
+
config TI_CPTS
bool "TI Common Platform Time Sync (CPTS) Support"
depends on TI_CPSW || TI_KEYSTONE_NETCP || COMPILE_TEST
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
index 0be551d..d6eb2a2 100644
--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o
obj-$(CONFIG_TI_CPSW_ALE) += cpsw_ale.o
obj-$(CONFIG_TI_CPTS_MOD) += cpts.o
obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
+obj-$(CONFIG_TI_CPSW_SWITCHDEV) += cpsw_switchdev.o
ti_cpsw-y := cpsw.o
obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index e5765cc..b501908 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -18,12 +18,10 @@
#include <linux/clk.h>
#include <linux/timer.h>
#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/irqreturn.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/etherdevice.h>
-#include <linux/netdevice.h>
#include <linux/net_tstamp.h>
#include <linux/phy.h>
#include <linux/workqueue.h>
@@ -43,6 +41,7 @@
#include "cpsw.h"
#include "cpsw_ale.h"
#include "cpsw_priv.h"
+#include "cpsw_switchdev.h"
#include "cpts.h"
#include "davinci_cpdma.h"
@@ -361,6 +360,13 @@ struct cpsw_hw_stats {
u32 rxdmaoverruns;
};
+struct cpsw_switchdev_event_work {
+ struct work_struct work;
+ struct switchdev_notifier_fdb_info fdb_info;
+ struct cpsw_priv *priv;
+ unsigned long event;
+};
+
#define CPSW_STAT(m) CPSW_STATS, \
sizeof(((struct cpsw_hw_stats *)0)->m), \
offsetof(struct cpsw_hw_stats, m)
@@ -488,14 +494,32 @@ static int cpsw_is_switch(u8 switch_mode)
return switch_mode == CPSW_TI_SWITCH;
}
+static int cpsw_is_switchdev(u8 switch_mode)
+{
+ return switch_mode == CPSW_SWITCHDEV;
+}
+
static int cpsw_slave_index(struct cpsw_priv *priv)
{
struct cpsw_common *cpsw = priv->cpsw;
+#if IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV)
+ if (priv->emac_port == HOST_PORT_NUM)
+ return -1;
+#endif
+
return cpsw->data.switch_mode ? priv->emac_port - 1 :
cpsw->data.active_slave;
}
+static void cpsw_switchdev_port_enable(struct net_device *ndev)
+{
+#if IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV)
+ cpsw_port_switchdev_init(ndev);
+ ndev->features |= NETIF_F_NETNS_LOCAL;
+#endif
+}
+
static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
{
struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
@@ -521,6 +545,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
if (enable) {
/* Enable Bypass */
cpsw_ale_control_set(ale, 0, ALE_BYPASS, 1);
+ cpsw_ale_set_allmulti(ale, IFF_ALLMULTI);
dev_dbg(&ndev->dev, "promiscuity enabled\n");
} else {
@@ -554,6 +579,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
/* Flood All Unicast Packets to Host port */
cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 1);
+ cpsw_ale_set_allmulti(ale, IFF_ALLMULTI);
dev_dbg(&ndev->dev, "promiscuity enabled\n");
} else {
/* Don't Flood All Unicast Packets to Host port */
@@ -568,6 +594,19 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
}
dev_dbg(&ndev->dev, "promiscuity disabled\n");
}
+ } else if (cpsw_is_switchdev(cpsw->data.switch_mode)) {
+ /* When interfaces are placed into a bridge they'll switch to
+ * promiscuous mode. In switchdev case ALE_P0_UNI_FLOOD is
+ * changed whether any switch port participates in the bridge
+ * or not
+ */
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ int slave_idx = cpsw_slave_index(priv);
+ int slave_num;
+
+ slave_num = cpsw_get_slave_port(slave_idx);
+ cpsw_ale_control_set(ale, slave_num, ALE_PORT_NOLEARN, 0);
+ cpsw_ale_control_set(ale, slave_num, ALE_PORT_NO_SA_UPDATE, 0);
}
}
@@ -586,7 +625,6 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
if (ndev->flags & IFF_PROMISC) {
/* Enable promiscuous mode */
cpsw_set_promiscious(ndev, true);
- cpsw_ale_set_allmulti(cpsw->ale, IFF_ALLMULTI);
return;
} else {
/* Disable promiscuous mode */
@@ -721,6 +759,10 @@ static void cpsw_rx_handler(void *token, int len, int status)
return;
}
+#if IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV)
+ if (cpsw_is_switchdev(cpsw->data.switch_mode))
+ skb->offload_fwd_mark = 1;
+#endif
new_skb = netdev_alloc_skb_ip_align(ndev, cpsw->rx_packet_max);
if (new_skb) {
skb_copy_queue_mapping(new_skb, skb);
@@ -1427,10 +1469,13 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
if (!cpsw_is_dual_mac(cpsw->data.switch_mode)) {
- cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr, HOST_PORT_NUM,
- 0, 0);
+ char stpa[] = {0x01, 0x80, 0xc2, 0x0, 0x0, 0x0};
+
cpsw_ale_add_mcast(cpsw->ale, priv->ndev->broadcast,
ALE_PORT_HOST, 0, 0, ALE_MCAST_FWD_2);
+ cpsw_ale_add_mcast(cpsw->ale, stpa,
+ ALE_PORT_HOST, ALE_SUPER, 0,
+ ALE_MCAST_BLOCK_LEARN_FWD);
}
}
@@ -1529,11 +1574,14 @@ static int cpsw_ndo_open(struct net_device *ndev)
for_each_slave(priv, cpsw_slave_open, priv);
/* Add default VLAN */
- if (!cpsw_is_dual_mac(cpsw->data.switch_mode))
+ if (!cpsw_is_dual_mac(cpsw->data.switch_mode)) {
cpsw_add_default_vlan(priv);
- else
+ cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr, HOST_PORT_NUM, 0,
+ 0);
+ } else {
cpsw_ale_add_vlan(cpsw->ale, cpsw->data.default_vlan,
ALE_ALL_PORTS, ALE_ALL_PORTS, 0, 0);
+ }
/* initialize shared resources for every ndev */
if (!cpsw->usage_count) {
@@ -1852,6 +1900,9 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
if (!netif_running(dev))
return -EINVAL;
+ if (slave_no < 0)
+ return -EOPNOTSUPP;
+
switch (cmd) {
case SIOCSHWTSTAMP:
return cpsw_hwtstamp_set(dev, req);
@@ -1941,7 +1992,7 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
u32 port_mask;
struct cpsw_common *cpsw = priv->cpsw;
- if (cpsw_is_dual_mac(cpsw->data.switch_mode)) {
+ if (!cpsw_is_switch(cpsw->data.switch_mode)) {
port_mask = (1 << priv->emac_port) | ALE_PORT_HOST;
if (priv->ndev->flags & IFF_ALLMULTI)
@@ -1989,6 +2040,10 @@ static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
if (vid == cpsw->data.default_vlan)
return 0;
+ if (cpsw_is_switchdev(cpsw->data.switch_mode) &&
+ (netif_is_bridge_port(ndev)))
+ return -EOPNOTSUPP;
+
ret = pm_runtime_get_sync(cpsw->dev);
if (ret < 0) {
pm_runtime_put_noidle(cpsw->dev);
@@ -2025,6 +2080,10 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
if (vid == cpsw->data.default_vlan)
return 0;
+ if (cpsw_is_switchdev(cpsw->data.switch_mode) &&
+ (netif_is_bridge_port(ndev)))
+ return -EOPNOTSUPP;
+
ret = pm_runtime_get_sync(cpsw->dev);
if (ret < 0) {
pm_runtime_put_noidle(cpsw->dev);
@@ -2056,6 +2115,24 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
return ret;
}
+static int cpsw_ndo_get_phys_port_name(struct net_device *ndev, char *name,
+ size_t len)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
+ int err;
+
+ if (!cpsw_is_switchdev(cpsw->data.switch_mode))
+ return -EOPNOTSUPP;
+
+ err = snprintf(name, len, "p%d", priv->emac_port);
+
+ if (err >= len)
+ return -EINVAL;
+
+ return 0;
+}
+
static int cpsw_ndo_set_tx_maxrate(struct net_device *ndev, int queue, u32 rate)
{
struct cpsw_priv *priv = netdev_priv(ndev);
@@ -2122,6 +2199,7 @@ static const struct net_device_ops cpsw_netdev_ops = {
#endif
.ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid,
+ .ndo_get_phys_port_name = cpsw_ndo_get_phys_port_name,
};
static int cpsw_get_regs_len(struct net_device *ndev)
@@ -2711,6 +2789,10 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
if (of_property_read_bool(node, "dual_emac"))
data->switch_mode = CPSW_DUAL_EMAC;
+ /* switchdev overrides DTS */
+ if (IS_ENABLED(CONFIG_TI_CPSW_SWITCHDEV))
+ data->switch_mode = CPSW_SWITCHDEV;
+
/*
* Populate all the child nodes here...
*/
@@ -2874,6 +2956,9 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
cpsw->slaves[1].ndev = ndev;
ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+ if (cpsw_is_switchdev(cpsw->data.switch_mode))
+ cpsw_switchdev_port_enable(ndev);
+
ndev->netdev_ops = &cpsw_netdev_ops;
ndev->ethtool_ops = &cpsw_ethtool_ops;
@@ -2903,6 +2988,196 @@ static const struct soc_device_attribute cpsw_soc_devices[] = {
{ /* sentinel */ }
};
+static bool cpsw_port_dev_check(const struct net_device *dev)
+{
+ return dev->netdev_ops == &cpsw_netdev_ops;
+}
+
+static void cpsw_fdb_offload_notify(struct net_device *ndev,
+ struct switchdev_notifier_fdb_info *rcv)
+{
+ struct switchdev_notifier_fdb_info info;
+
+ info.addr = rcv->addr;
+ info.vid = rcv->vid;
+ call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED,
+ ndev, &info.info);
+}
+
+static void cpsw_switchdev_event_work(struct work_struct *work)
+{
+ struct cpsw_switchdev_event_work *switchdev_work =
+ container_of(work, struct cpsw_switchdev_event_work, work);
+ struct cpsw_priv *priv = switchdev_work->priv;
+ struct switchdev_notifier_fdb_info *fdb;
+ struct cpsw_common *cpsw = priv->cpsw;
+ int port = priv->emac_port;
+
+ rtnl_lock();
+ switch (switchdev_work->event) {
+ case SWITCHDEV_FDB_ADD_TO_DEVICE:
+ fdb = &switchdev_work->fdb_info;
+ if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
+ port = HOST_PORT_NUM;
+ cpsw_ale_add_ucast(cpsw->ale, (u8 *)fdb->addr, port, ALE_VLAN,
+ fdb->vid);
+ cpsw_fdb_offload_notify(priv->ndev, fdb);
+ break;
+ case SWITCHDEV_FDB_DEL_TO_DEVICE:
+ fdb = &switchdev_work->fdb_info;
+ if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
+ port = HOST_PORT_NUM;
+ cpsw_ale_del_ucast(cpsw->ale, (u8 *)fdb->addr, port, ALE_VLAN,
+ fdb->vid);
+ break;
+ default:
+ break;
+ }
+ rtnl_unlock();
+
+ kfree(switchdev_work->fdb_info.addr);
+ kfree(switchdev_work);
+ dev_put(priv->ndev);
+}
+
+/* called under rcu_read_lock() */
+static int cpsw_switchdev_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *ndev = switchdev_notifier_info_to_dev(ptr);
+ struct switchdev_notifier_fdb_info *fdb_info = ptr;
+ struct cpsw_switchdev_event_work *switchdev_work;
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (!cpsw_port_dev_check(ndev))
+ return NOTIFY_DONE;
+
+ switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
+ if (WARN_ON(!switchdev_work))
+ return NOTIFY_BAD;
+
+ INIT_WORK(&switchdev_work->work, cpsw_switchdev_event_work);
+ switchdev_work->priv = priv;
+ switchdev_work->event = event;
+
+ switch (event) {
+ case SWITCHDEV_FDB_ADD_TO_DEVICE:
+ case SWITCHDEV_FDB_DEL_TO_DEVICE:
+ memcpy(&switchdev_work->fdb_info, ptr,
+ sizeof(switchdev_work->fdb_info));
+ switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
+ ether_addr_copy((u8 *)switchdev_work->fdb_info.addr,
+ fdb_info->addr);
+ dev_hold(ndev);
+ break;
+ default:
+ kfree(switchdev_work);
+ return NOTIFY_DONE;
+ }
+
+ queue_work(system_long_wq, &switchdev_work->work);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block cpsw_switchdev_notifier = {
+ .notifier_call = cpsw_switchdev_event,
+};
+
+static void cpsw_netdevice_port_link(struct net_device *ndev)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
+
+ if (!cpsw->br_members) {
+ cpsw_ale_control_set(cpsw->ale, HOST_PORT_NUM, ALE_P0_UNI_FLOOD,
+ 1);
+ dev_dbg(&ndev->dev, "Set P0_UNI_FLOOD\n");
+ }
+ cpsw->br_members++;
+}
+
+static void cpsw_netdevice_port_unlink(struct net_device *ndev)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
+
+ cpsw->br_members--;
+ if (!cpsw->br_members) {
+ cpsw_ale_control_set(cpsw->ale, HOST_PORT_NUM, ALE_P0_UNI_FLOOD,
+ 0);
+ dev_dbg(&ndev->dev, "unset P0_UNI_FLOOD\n");
+ }
+}
+
+/* netdev notifier */
+static int cpsw_netdevice_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
+ struct netdev_notifier_changeupper_info *info;
+
+ switch (event) {
+ case NETDEV_CHANGEUPPER:
+ info = ptr;
+ if (!info->master)
+ goto out;
+ if (info->linking)
+ cpsw_netdevice_port_link(ndev);
+ else
+ cpsw_netdevice_port_unlink(ndev);
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+
+out:
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block cpsw_netdevice_nb __read_mostly = {
+ .notifier_call = cpsw_netdevice_event,
+};
+
+static int cpsw_register_notifiers(struct cpsw_priv *priv)
+{
+ int ret;
+
+ ret = register_netdevice_notifier(&cpsw_netdevice_nb);
+ if (ret) {
+ cpsw_err(priv, probe, "can't register netdevice notifier\n");
+ return ret;
+ }
+
+ ret = register_switchdev_notifier(&cpsw_switchdev_notifier);
+ if (ret) {
+ cpsw_err(priv, probe, "can't register switchdev notifier\n");
+ goto unreg_netdevice;
+ }
+
+ return ret;
+
+unreg_netdevice:
+ ret = unregister_netdevice_notifier(&cpsw_netdevice_nb);
+
+ return ret;
+}
+
+static int cpsw_unregister_notifiers(struct cpsw_priv *priv)
+{
+ int ret;
+
+ ret = unregister_switchdev_notifier(&cpsw_switchdev_notifier);
+ if (ret)
+ dev_err(priv->dev, "can't unregister switchdev notifier\n");
+
+ ret += unregister_netdevice_notifier(&cpsw_netdevice_nb);
+ if (ret)
+ dev_err(priv->dev, "can't unregister netdevice notifier\n");
+
+ return ret;
+}
+
static int cpsw_probe(struct platform_device *pdev)
{
struct clk *clk;
@@ -3135,6 +3410,9 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_dma_ret;
}
+ if (cpsw_is_switchdev(cpsw->data.switch_mode))
+ cpsw_switchdev_port_enable(ndev);
+
ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX;
ndev->netdev_ops = &cpsw_netdev_ops;
@@ -3202,6 +3480,12 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_dma_ret;
}
+ if (cpsw_is_switchdev(cpsw->data.switch_mode)) {
+ ret = cpsw_register_notifiers(priv);
+ if (ret)
+ goto clean_dma_ret;
+ }
+
cpsw_notice(priv, probe,
"initialized device (regs %pa, irq %d, pool size %d)\n",
&ss_res->start, ndev->irq, dma_params.descs_pool_size);
@@ -3227,7 +3511,8 @@ static int cpsw_probe(struct platform_device *pdev)
static int cpsw_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
- struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
int ret;
ret = pm_runtime_get_sync(&pdev->dev);
@@ -3236,6 +3521,9 @@ static int cpsw_remove(struct platform_device *pdev)
return ret;
}
+ if (cpsw_is_switchdev(cpsw->data.switch_mode))
+ ret = cpsw_unregister_notifiers(priv);
+
if (!cpsw_is_switch(cpsw->data.switch_mode))
unregister_netdev(cpsw->slaves[1].ndev);
unregister_netdev(ndev);
diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h
index 86a2709..4380b1c 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.h
+++ b/drivers/net/ethernet/ti/cpsw_priv.h
@@ -33,6 +33,7 @@
enum {
CPSW_TI_SWITCH,
CPSW_DUAL_EMAC,
+ CPSW_SWITCHDEV,
};
struct cpsw_slave_data {
@@ -98,6 +99,7 @@ struct cpsw_common {
int rx_ch_num, tx_ch_num;
int speed;
int usage_count;
+ u8 br_members;
};
struct cpsw_priv {
diff --git a/drivers/net/ethernet/ti/cpsw_switchdev.c b/drivers/net/ethernet/ti/cpsw_switchdev.c
new file mode 100644
index 0000000..528e99e
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpsw_switchdev.c
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Texas Instruments switchdev Driver
+ *
+ * Copyright (C) 2018 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if_bridge.h>
+#include <net/switchdev.h>
+#include "cpsw.h"
+#include "cpsw_priv.h"
+#include "cpsw_ale.h"
+
+static u32 cpsw_switchdev_get_ver(struct net_device *ndev)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct cpsw_common *cpsw = priv->cpsw;
+
+ return cpsw->version;
+}
+
+static int cpsw_port_stp_state_set(struct cpsw_priv *priv,
+ struct switchdev_trans *trans, u8 state)
+{
+ struct cpsw_common *cpsw = priv->cpsw;
+ u8 cpsw_state;
+ int ret = 0;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ switch (state) {
+ case BR_STATE_FORWARDING:
+ cpsw_state = ALE_PORT_STATE_FORWARD;
+ break;
+ case BR_STATE_LEARNING:
+ cpsw_state = ALE_PORT_STATE_LEARN;
+ break;
+ case BR_STATE_DISABLED:
+ cpsw_state = ALE_PORT_STATE_DISABLE;
+ break;
+ case BR_STATE_LISTENING:
+ case BR_STATE_BLOCKING:
+ cpsw_state = ALE_PORT_STATE_BLOCK;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ ret = cpsw_ale_control_set(cpsw->ale, priv->emac_port,
+ ALE_PORT_STATE, cpsw_state);
+ dev_dbg(priv->dev, "ale state: %u\n", cpsw_state);
+
+ return ret;
+}
+
+static int cpsw_port_attr_br_flags_set(struct cpsw_priv *priv,
+ struct switchdev_trans *trans,
+ struct net_device *orig_dev,
+ unsigned long brport_flags)
+{
+ struct cpsw_common *cpsw = priv->cpsw;
+ bool unreg_mcast_add = false;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ if (brport_flags & BR_MCAST_FLOOD)
+ unreg_mcast_add = true;
+ cpsw_ale_set_unreg_mcast(cpsw->ale, BIT(priv->emac_port),
+ unreg_mcast_add);
+
+ return 0;
+}
+
+static int cpsw_port_attr_set(struct net_device *ndev,
+ const struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ u8 state;
+ int ret;
+
+ dev_dbg(priv->dev, "attr: id %u dev: %s port: %u\n", attr->id,
+ priv->ndev->name, priv->emac_port);
+
+ switch (attr->id) {
+ case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
+ ret = cpsw_port_stp_state_set(priv, trans, attr->u.stp_state);
+ dev_dbg(priv->dev, "stp state: %u\n", state);
+ break;
+ case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
+ ret = cpsw_port_attr_br_flags_set(priv, trans, attr->orig_dev,
+ attr->u.brport_flags);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int cpsw_port_attr_get(struct net_device *dev,
+ struct switchdev_attr *attr)
+{
+ u32 cpsw_ver;
+ int err = 0;
+
+ switch (attr->id) {
+ case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
+ cpsw_ver = cpsw_switchdev_get_ver(dev);
+ attr->u.ppid.id_len = sizeof(cpsw_ver);
+ memcpy(&attr->u.ppid.id, &cpsw_ver, attr->u.ppid.id_len);
+ break;
+ case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
+ attr->u.brport_flags_support = BR_MCAST_FLOOD;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
+static u16 cpsw_get_pvid(struct cpsw_priv *priv)
+{
+ struct cpsw_common *cpsw = priv->cpsw;
+ u32 __iomem *port_vlan_reg;
+ u32 pvid;
+
+ if (priv->emac_port) {
+ int reg = CPSW2_PORT_VLAN;
+
+ if (cpsw->version == CPSW_VERSION_1)
+ reg = CPSW1_PORT_VLAN;
+ pvid = slave_read(cpsw->slaves + (priv->emac_port - 1), reg);
+ } else {
+ port_vlan_reg = &cpsw->host_port_regs->port_vlan;
+ pvid = readl(port_vlan_reg);
+ }
+
+ pvid = pvid & 0xfff;
+
+ return pvid;
+}
+
+static void cpsw_set_pvid(struct cpsw_priv *priv, u16 vid, bool cfi, u32 cos)
+{
+ struct cpsw_common *cpsw = priv->cpsw;
+ void __iomem *port_vlan_reg;
+ u32 pvid;
+
+ pvid = vid;
+ pvid |= cfi ? BIT(12) : 0;
+ pvid |= (cos & 0x7) << 13;
+
+ if (priv->emac_port) {
+ int reg = CPSW2_PORT_VLAN;
+
+ if (cpsw->version == CPSW_VERSION_1)
+ reg = CPSW1_PORT_VLAN;
+ /* no barrier */
+ slave_write(cpsw->slaves + (priv->emac_port - 1), pvid, reg);
+ } else {
+ /* CPU port */
+ port_vlan_reg = &cpsw->host_port_regs->port_vlan;
+ writel(pvid, port_vlan_reg);
+ }
+}
+
+static int cpsw_port_vlan_add(struct cpsw_priv *priv, bool untag, bool pvid,
+ u16 vid, struct net_device *orig_dev)
+{
+ bool cpu_port = netif_is_bridge_master(orig_dev);
+ struct cpsw_common *cpsw = priv->cpsw;
+ int unreg_mcast_mask = 0;
+ int reg_mcast_mask = 0;
+ int untag_mask = 0;
+ int port_mask;
+ int ret = 0;
+ u32 flags;
+
+ if (cpu_port) {
+ port_mask = BIT(HOST_PORT_NUM);
+ flags = orig_dev->flags;
+ unreg_mcast_mask = port_mask;
+ } else {
+ port_mask = BIT(priv->emac_port);
+ flags = priv->ndev->flags;
+ }
+
+ if (flags & IFF_MULTICAST)
+ reg_mcast_mask = port_mask;
+
+ if (untag)
+ untag_mask = port_mask;
+
+ ret = cpsw_ale_vlan_add_modify(cpsw->ale, vid, port_mask, untag_mask,
+ reg_mcast_mask, unreg_mcast_mask);
+ if (ret) {
+ dev_err(priv->dev, "Unable to add vlan\n");
+ return ret;
+ }
+
+ if (!pvid)
+ return ret;
+
+ cpsw_set_pvid(priv, vid, 0, 0);
+
+ dev_dbg(priv->dev, "VID add: %u dev: %s port: %u\n", vid,
+ priv->ndev->name, priv->emac_port);
+
+ return ret;
+}
+
+static int cpsw_port_vlan_del(struct cpsw_priv *priv, u16 vid,
+ struct net_device *orig_dev)
+{
+ bool cpu_port = netif_is_bridge_master(orig_dev);
+ struct cpsw_common *cpsw = priv->cpsw;
+ int port_mask;
+ int ret = 0;
+
+ if (cpu_port)
+ port_mask = BIT(HOST_PORT_NUM);
+ else
+ port_mask = BIT(priv->emac_port);
+
+ ret = cpsw_ale_vlan_del_modify(cpsw->ale, vid, port_mask);
+ if (ret != 0)
+ return ret;
+
+ /* We don't care for the return value here, error is returned only if
+ * the unicast entry is not present
+ */
+ cpsw_ale_del_ucast(cpsw->ale, priv->mac_addr,
+ HOST_PORT_NUM, ALE_VLAN, vid);
+
+ if (vid == cpsw_get_pvid(priv))
+ cpsw_set_pvid(priv, 0, 0, 0);
+
+ /* We don't care for the return value here, error is returned only if
+ * the multicast entry is not present
+ */
+ cpsw_ale_del_mcast(cpsw->ale, priv->ndev->broadcast,
+ 0, ALE_VLAN, vid);
+
+ dev_dbg(priv->dev, "VID del: %u dev: %s port: %u\n", vid,
+ priv->ndev->name, priv->emac_port);
+
+ return ret;
+}
+
+static int cpsw_port_vlans_add(struct cpsw_priv *priv,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct switchdev_trans *trans)
+{
+ bool untag = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
+ struct net_device *orig_dev = vlan->obj.orig_dev;
+ bool cpu_port = netif_is_bridge_master(orig_dev);
+ bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+ u16 vid;
+
+ if (cpu_port && !(vlan->flags & BRIDGE_VLAN_INFO_BRENTRY))
+ return 0;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
+ int err;
+
+ err = cpsw_port_vlan_add(priv, untag, pvid, vid, orig_dev);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int cpsw_port_vlans_del(struct cpsw_priv *priv,
+ const struct switchdev_obj_port_vlan *vlan)
+
+{
+ struct net_device *orig_dev = vlan->obj.orig_dev;
+ u16 vid;
+
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
+ int err;
+
+ err = cpsw_port_vlan_del(priv, vid, orig_dev);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int cpsw_port_mdb_add(struct cpsw_priv *priv,
+ struct switchdev_obj_port_mdb *mdb,
+ struct switchdev_trans *trans)
+
+{
+ struct net_device *orig_dev = mdb->obj.orig_dev;
+ bool cpu_port = netif_is_bridge_master(orig_dev);
+ struct cpsw_common *cpsw = priv->cpsw;
+ int port_mask;
+ int err;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ if (cpu_port)
+ port_mask = BIT(HOST_PORT_NUM);
+ else
+ port_mask = BIT(priv->emac_port);
+
+ err = cpsw_ale_mcast_add_modify(cpsw->ale, mdb->addr, port_mask,
+ ALE_VLAN, mdb->vid, 0);
+
+ dev_dbg(priv->dev, "MDB add: %pM dev: %s vid %u port: %u\n", mdb->addr,
+ priv->ndev->name, mdb->vid, priv->emac_port);
+
+ return err;
+}
+
+static int cpsw_port_mdb_del(struct cpsw_priv *priv,
+ struct switchdev_obj_port_mdb *mdb)
+
+{
+ struct net_device *orig_dev = mdb->obj.orig_dev;
+ bool cpu_port = netif_is_bridge_master(orig_dev);
+ struct cpsw_common *cpsw = priv->cpsw;
+ int del_mask;
+ int err;
+
+ if (cpu_port)
+ del_mask = BIT(HOST_PORT_NUM);
+ else
+ del_mask = BIT(priv->emac_port);
+ err = cpsw_ale_mcast_del_modify(cpsw->ale, mdb->addr, del_mask,
+ ALE_VLAN, mdb->vid);
+ dev_dbg(priv->dev, "MDB del: %pM dev: %s vid %u port: %u\n", mdb->addr,
+ priv->ndev->name, mdb->vid, priv->emac_port);
+
+ return err;
+}
+
+static int cpsw_port_obj_add(struct net_device *ndev,
+ const struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
+{
+ struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
+ struct switchdev_obj_port_mdb *mdb = SWITCHDEV_OBJ_PORT_MDB(obj);
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ int err = 0;
+
+ switch (obj->id) {
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ err = cpsw_port_vlans_add(priv, vlan, trans);
+ break;
+ case SWITCHDEV_OBJ_ID_PORT_MDB:
+ case SWITCHDEV_OBJ_ID_HOST_MDB:
+ err = cpsw_port_mdb_add(priv, mdb, trans);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static int cpsw_port_obj_del(struct net_device *ndev,
+ const struct switchdev_obj *obj)
+{
+ struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
+ struct switchdev_obj_port_mdb *mdb = SWITCHDEV_OBJ_PORT_MDB(obj);
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ int err = 0;
+
+ switch (obj->id) {
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ err = cpsw_port_vlans_del(priv, vlan);
+ break;
+ case SWITCHDEV_OBJ_ID_PORT_MDB:
+ case SWITCHDEV_OBJ_ID_HOST_MDB:
+ err = cpsw_port_mdb_del(priv, mdb);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static const struct switchdev_ops cpsw_port_switchdev_ops = {
+ .switchdev_port_attr_set = cpsw_port_attr_set,
+ .switchdev_port_attr_get = cpsw_port_attr_get,
+ .switchdev_port_obj_add = cpsw_port_obj_add,
+ .switchdev_port_obj_del = cpsw_port_obj_del,
+};
+
+void cpsw_port_switchdev_init(struct net_device *ndev)
+{
+ ndev->switchdev_ops = &cpsw_port_switchdev_ops;
+}
diff --git a/drivers/net/ethernet/ti/cpsw_switchdev.h b/drivers/net/ethernet/ti/cpsw_switchdev.h
new file mode 100644
index 0000000..4940462
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpsw_switchdev.h
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <net/switchdev.h>
+
+void cpsw_port_switchdev_init(struct net_device *ndev);
--
2.7.4
^ permalink raw reply related
* [RFC v2, net-next, PATCH 3/4] net/cpsw: prepare cpsw for switchdev support
From: Ilias Apalodimas @ 2018-06-14 11:11 UTC (permalink / raw)
To: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, jiri,
ivecera, andrew, f.fainelli
Cc: francois.ozog, yogeshs, spatton, Jose.Abreu, Ilias Apalodimas
In-Reply-To: <1528974690-31600-1-git-send-email-ilias.apalodimas@linaro.org>
A following patch introduces switchdev functionality. Prepare cpsw
driver to accommodate an extra mode of operation using switchdev.
This patch does not changes the cpsw driver current functionality
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
drivers/net/ethernet/ti/cpsw.c | 146 ++++++++++++++++++++++++------------
drivers/net/ethernet/ti/cpsw_priv.h | 7 +-
2 files changed, 104 insertions(+), 49 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index d13b57f..e5765cc 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -147,9 +147,6 @@ do { \
#define CPSW_CMINTMAX_INTVL (1000 / CPSW_CMINTMIN_CNT)
#define CPSW_CMINTMIN_INTVL ((1000 / CPSW_CMINTMAX_CNT) + 1)
-#define cpsw_slave_index(cpsw, priv) \
- ((cpsw->data.dual_emac) ? priv->emac_port : \
- cpsw->data.active_slave)
#define IRQ_NUM 2
#define CPSW_MAX_QUEUES 8
#define CPSW_CPDMA_DESCS_POOL_SIZE_DEFAULT 256
@@ -182,6 +179,9 @@ static int descs_pool_size = CPSW_CPDMA_DESCS_POOL_SIZE_DEFAULT;
module_param(descs_pool_size, int, 0444);
MODULE_PARM_DESC(descs_pool_size, "Number of CPDMA CPPI descriptors in pool");
+static int cpsw_is_dual_mac(u8 switch_mode);
+static int cpsw_is_switch(u8 switch_mode);
+
struct cpsw_wr_regs {
u32 id_ver;
u32 soft_reset;
@@ -434,8 +434,9 @@ static const struct cpsw_stats cpsw_gstrings_ch_stats[] = {
struct cpsw_slave *slave; \
struct cpsw_common *cpsw = (priv)->cpsw; \
int n; \
- if (cpsw->data.dual_emac) \
- (func)((cpsw)->slaves + priv->emac_port, ##arg);\
+ if (!cpsw_is_switch(cpsw->data.switch_mode)) \
+ (func)((cpsw)->slaves + priv->emac_port - 1, \
+ ##arg); \
else \
for (n = cpsw->data.slaves, \
slave = cpsw->slaves; \
@@ -445,7 +446,7 @@ static const struct cpsw_stats cpsw_gstrings_ch_stats[] = {
#define cpsw_dual_emac_src_port_detect(cpsw, status, ndev, skb) \
do { \
- if (!cpsw->data.dual_emac) \
+ if (cpsw_is_switch(cpsw->data.switch_mode)) \
break; \
if (CPDMA_RX_SOURCE_PORT(status) == 1) { \
ndev = cpsw->slaves[0].ndev; \
@@ -457,7 +458,7 @@ static const struct cpsw_stats cpsw_gstrings_ch_stats[] = {
} while (0)
#define cpsw_add_mcast(cpsw, priv, addr) \
do { \
- if (cpsw->data.dual_emac) { \
+ if (cpsw_is_dual_mac(cpsw->data.switch_mode)) { \
struct cpsw_slave *slave = cpsw->slaves + \
priv->emac_port; \
int slave_port = cpsw_get_slave_port( \
@@ -477,13 +478,31 @@ static inline int cpsw_get_slave_port(u32 slave_num)
return slave_num + 1;
}
+static int cpsw_is_dual_mac(u8 switch_mode)
+{
+ return switch_mode == CPSW_DUAL_EMAC;
+}
+
+static int cpsw_is_switch(u8 switch_mode)
+{
+ return switch_mode == CPSW_TI_SWITCH;
+}
+
+static int cpsw_slave_index(struct cpsw_priv *priv)
+{
+ struct cpsw_common *cpsw = priv->cpsw;
+
+ return cpsw->data.switch_mode ? priv->emac_port - 1 :
+ cpsw->data.active_slave;
+}
+
static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
{
struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
struct cpsw_ale *ale = cpsw->ale;
int i;
- if (cpsw->data.dual_emac) {
+ if (cpsw_is_dual_mac(cpsw->data.switch_mode)) {
bool flag = false;
/* Enabling promiscuous mode for one interface will be
@@ -509,7 +528,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
cpsw_ale_control_set(ale, 0, ALE_BYPASS, 0);
dev_dbg(&ndev->dev, "promiscuity disabled\n");
}
- } else {
+ } else if (cpsw_is_switch(cpsw->data.switch_mode)) {
if (enable) {
unsigned long timeout = jiffies + HZ;
@@ -556,10 +575,11 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
+ int slave_no = cpsw_slave_index(priv);
int vid;
- if (cpsw->data.dual_emac)
- vid = cpsw->slaves[priv->emac_port].port_vlan;
+ if (cpsw_is_dual_mac(cpsw->data.switch_mode))
+ vid = cpsw->slaves[slave_no].port_vlan;
else
vid = cpsw->data.default_vlan;
@@ -630,8 +650,9 @@ static void cpsw_tx_handler(void *token, int len, int status)
static void cpsw_rx_vlan_encap(struct sk_buff *skb)
{
struct cpsw_priv *priv = netdev_priv(skb->dev);
- struct cpsw_common *cpsw = priv->cpsw;
u32 rx_vlan_encap_hdr = *((u32 *)skb->data);
+ struct cpsw_common *cpsw = priv->cpsw;
+ int slave_no = cpsw_slave_index(priv);
u16 vtag, vid, prio, pkt_type;
/* Remove VLAN header encapsulation word */
@@ -652,8 +673,8 @@ static void cpsw_rx_vlan_encap(struct sk_buff *skb)
if (!vid)
return;
/* Ignore default vlans in dual mac mode */
- if (cpsw->data.dual_emac &&
- vid == cpsw->slaves[priv->emac_port].port_vlan)
+ if (cpsw_is_dual_mac(cpsw->data.switch_mode) &&
+ vid == cpsw->slaves[slave_no].port_vlan)
return;
prio = (rx_vlan_encap_hdr >>
@@ -682,9 +703,9 @@ static void cpsw_rx_handler(void *token, int len, int status)
cpsw_dual_emac_src_port_detect(cpsw, status, ndev, skb);
if (unlikely(status < 0) || unlikely(!netif_running(ndev))) {
- /* In dual emac mode check for all interfaces */
- if (cpsw->data.dual_emac && cpsw->usage_count &&
- (status >= 0)) {
+ /* In any other that switch mode check for all interfaces */
+ if (!cpsw_is_switch(cpsw->data.switch_mode) &&
+ cpsw->usage_count && status >= 0) {
/* The packet received is for the interface which
* is already down and the other interface is up
* and running, instead of freeing which results
@@ -1235,11 +1256,11 @@ static inline int cpsw_tx_packet_submit(struct cpsw_priv *priv,
struct sk_buff *skb,
struct cpdma_chan *txch)
{
- struct cpsw_common *cpsw = priv->cpsw;
skb_tx_timestamp(skb);
+
return cpdma_chan_submit(txch, skb, skb->data, skb->len,
- priv->emac_port + cpsw->data.dual_emac);
+ priv->emac_port);
}
static inline void cpsw_add_dual_emac_def_ale_entries(
@@ -1314,7 +1335,7 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
slave_port = cpsw_get_slave_port(slave->slave_num);
- if (cpsw->data.dual_emac)
+ if (cpsw_is_dual_mac(cpsw->data.switch_mode))
cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port);
else
cpsw_ale_add_mcast(cpsw->ale, priv->ndev->broadcast,
@@ -1393,8 +1414,8 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
control_reg = readl(&cpsw->regs->control);
control_reg |= CPSW_VLAN_AWARE | CPSW_RX_VLAN_ENCAP;
writel(control_reg, &cpsw->regs->control);
- fifo_mode = (cpsw->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE :
- CPSW_FIFO_NORMAL_MODE;
+ fifo_mode = cpsw_is_dual_mac(cpsw->data.switch_mode) ?
+ CPSW_FIFO_DUAL_MAC_MODE : CPSW_FIFO_NORMAL_MODE;
writel(fifo_mode, &cpsw->host_port_regs->tx_in_ctl);
/* setup host port priority mapping */
@@ -1405,7 +1426,7 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
cpsw_ale_control_set(cpsw->ale, HOST_PORT_NUM,
ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
- if (!cpsw->data.dual_emac) {
+ if (!cpsw_is_dual_mac(cpsw->data.switch_mode)) {
cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr, HOST_PORT_NUM,
0, 0);
cpsw_ale_add_mcast(cpsw->ale, priv->ndev->broadcast,
@@ -1508,7 +1529,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
for_each_slave(priv, cpsw_slave_open, priv);
/* Add default VLAN */
- if (!cpsw->data.dual_emac)
+ if (!cpsw_is_dual_mac(cpsw->data.switch_mode))
cpsw_add_default_vlan(priv);
else
cpsw_ale_add_vlan(cpsw->ale, cpsw->data.default_vlan,
@@ -1685,9 +1706,13 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
{
struct cpsw_slave *slave;
struct cpsw_common *cpsw = priv->cpsw;
+ int slave_no = cpsw_slave_index(priv);
u32 ctrl, mtype;
- slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)];
+ if (slave_no < 0)
+ return;
+
+ slave = &cpsw->slaves[slave_no];
ctrl = slave_read(slave, CPSW2_CONTROL);
switch (cpsw->version) {
@@ -1822,7 +1847,7 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
{
struct cpsw_priv *priv = netdev_priv(dev);
struct cpsw_common *cpsw = priv->cpsw;
- int slave_no = cpsw_slave_index(cpsw, priv);
+ int slave_no = cpsw_slave_index(priv);
if (!netif_running(dev))
return -EINVAL;
@@ -1863,6 +1888,7 @@ static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p)
struct cpsw_priv *priv = netdev_priv(ndev);
struct sockaddr *addr = (struct sockaddr *)p;
struct cpsw_common *cpsw = priv->cpsw;
+ int slave_no = cpsw_slave_index(priv);
int flags = 0;
u16 vid = 0;
int ret;
@@ -1876,8 +1902,8 @@ static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p)
return ret;
}
- if (cpsw->data.dual_emac) {
- vid = cpsw->slaves[priv->emac_port].port_vlan;
+ if (cpsw_is_dual_mac(cpsw->data.switch_mode)) {
+ vid = cpsw->slaves[slave_no].port_vlan;
flags = ALE_VLAN;
}
@@ -1915,8 +1941,8 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
u32 port_mask;
struct cpsw_common *cpsw = priv->cpsw;
- if (cpsw->data.dual_emac) {
- port_mask = (1 << (priv->emac_port + 1)) | ALE_PORT_HOST;
+ if (cpsw_is_dual_mac(cpsw->data.switch_mode)) {
+ port_mask = (1 << priv->emac_port) | ALE_PORT_HOST;
if (priv->ndev->flags & IFF_ALLMULTI)
unreg_mcast_mask = port_mask;
@@ -1969,7 +1995,7 @@ static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
return ret;
}
- if (cpsw->data.dual_emac) {
+ if (cpsw_is_dual_mac(cpsw->data.switch_mode)) {
/* In dual EMAC, reserved VLAN id should not be used for
* creating VLAN interfaces as this can break the dual
* EMAC port separation
@@ -2005,7 +2031,7 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
return ret;
}
- if (cpsw->data.dual_emac) {
+ if (cpsw_is_dual_mac(cpsw->data.switch_mode)) {
int i;
for (i = 0; i < cpsw->data.slaves; i++) {
@@ -2183,7 +2209,10 @@ static int cpsw_get_link_ksettings(struct net_device *ndev,
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
- int slave_no = cpsw_slave_index(cpsw, priv);
+ int slave_no = cpsw_slave_index(priv);
+
+ if (slave_no < 0)
+ return -EOPNOTSUPP;
if (!cpsw->slaves[slave_no].phy)
return -EOPNOTSUPP;
@@ -2197,7 +2226,10 @@ static int cpsw_set_link_ksettings(struct net_device *ndev,
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
- int slave_no = cpsw_slave_index(cpsw, priv);
+ int slave_no = cpsw_slave_index(priv);
+
+ if (slave_no < 0)
+ return -EOPNOTSUPP;
if (cpsw->slaves[slave_no].phy)
return phy_ethtool_ksettings_set(cpsw->slaves[slave_no].phy,
@@ -2210,7 +2242,10 @@ static void cpsw_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
- int slave_no = cpsw_slave_index(cpsw, priv);
+ int slave_no = cpsw_slave_index(priv);
+
+ if (slave_no < 0)
+ return;
wol->supported = 0;
wol->wolopts = 0;
@@ -2223,7 +2258,10 @@ static int cpsw_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
- int slave_no = cpsw_slave_index(cpsw, priv);
+ int slave_no = cpsw_slave_index(priv);
+
+ if (slave_no < 0)
+ return -EOPNOTSUPP;
if (cpsw->slaves[slave_no].phy)
return phy_ethtool_set_wol(cpsw->slaves[slave_no].phy, wol);
@@ -2487,7 +2525,10 @@ static int cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
- int slave_no = cpsw_slave_index(cpsw, priv);
+ int slave_no = cpsw_slave_index(priv);
+
+ if (slave_no < 0)
+ return -EOPNOTSUPP;
if (cpsw->slaves[slave_no].phy)
return phy_ethtool_get_eee(cpsw->slaves[slave_no].phy, edata);
@@ -2499,7 +2540,10 @@ static int cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
- int slave_no = cpsw_slave_index(cpsw, priv);
+ int slave_no = cpsw_slave_index(priv);
+
+ if (slave_no < 0)
+ return -EOPNOTSUPP;
if (cpsw->slaves[slave_no].phy)
return phy_ethtool_set_eee(cpsw->slaves[slave_no].phy, edata);
@@ -2511,7 +2555,10 @@ static int cpsw_nway_reset(struct net_device *ndev)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
- int slave_no = cpsw_slave_index(cpsw, priv);
+ int slave_no = cpsw_slave_index(priv);
+
+ if (slave_no < 0)
+ return -EOPNOTSUPP;
if (cpsw->slaves[slave_no].phy)
return genphy_restart_aneg(cpsw->slaves[slave_no].phy);
@@ -2662,7 +2709,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
data->mac_control = prop;
if (of_property_read_bool(node, "dual_emac"))
- data->dual_emac = 1;
+ data->switch_mode = CPSW_DUAL_EMAC;
/*
* Populate all the child nodes here...
@@ -2743,7 +2790,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
if (ret)
return ret;
}
- if (data->dual_emac) {
+ if (cpsw_is_dual_mac(data->switch_mode)) {
if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
&prop)) {
dev_err(&pdev->dev, "Missing dual_emac_res_vlan in DT.\n");
@@ -2823,7 +2870,7 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
}
memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN);
- priv_sl2->emac_port = 1;
+ priv_sl2->emac_port = 2;
cpsw->slaves[1].ndev = ndev;
ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
@@ -2947,7 +2994,10 @@ static int cpsw_probe(struct platform_device *pdev)
cpsw->slaves[i].slave_num = i;
cpsw->slaves[0].ndev = ndev;
- priv->emac_port = 0;
+ if (cpsw_is_switch(cpsw->data.switch_mode))
+ priv->emac_port = HOST_PORT_NUM;
+ else
+ priv->emac_port = 1;
clk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(clk)) {
@@ -3106,7 +3156,7 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_dma_ret;
}
- if (cpsw->data.dual_emac) {
+ if (!cpsw_is_switch(cpsw->data.switch_mode)) {
ret = cpsw_probe_dual_emac(priv);
if (ret) {
cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
@@ -3186,7 +3236,7 @@ static int cpsw_remove(struct platform_device *pdev)
return ret;
}
- if (cpsw->data.dual_emac)
+ if (!cpsw_is_switch(cpsw->data.switch_mode))
unregister_netdev(cpsw->slaves[1].ndev);
unregister_netdev(ndev);
@@ -3195,7 +3245,7 @@ static int cpsw_remove(struct platform_device *pdev)
cpsw_remove_dt(pdev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- if (cpsw->data.dual_emac)
+ if (!cpsw_is_switch(cpsw->data.switch_mode))
free_netdev(cpsw->slaves[1].ndev);
free_netdev(ndev);
return 0;
@@ -3208,7 +3258,7 @@ static int cpsw_suspend(struct device *dev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
- if (cpsw->data.dual_emac) {
+ if (!cpsw_is_switch(cpsw->data.switch_mode)) {
int i;
for (i = 0; i < cpsw->data.slaves; i++) {
@@ -3237,7 +3287,7 @@ static int cpsw_resume(struct device *dev)
/* shut up ASSERT_RTNL() warning in netif_set_real_num_tx/rx_queues */
rtnl_lock();
- if (cpsw->data.dual_emac) {
+ if (!cpsw_is_switch(cpsw->data.switch_mode)) {
int i;
for (i = 0; i < cpsw->data.slaves; i++) {
diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h
index 3b02a83..86a2709 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.h
+++ b/drivers/net/ethernet/ti/cpsw_priv.h
@@ -30,6 +30,11 @@
#define CPSW2_TX_PRI_MAP 0x18 /* Tx Header Priority to Switch Pri Mapping */
#define CPSW2_TS_SEQ_MTYPE 0x1c /* Time Sync Sequence ID Offset and Msg Type */
+enum {
+ CPSW_TI_SWITCH,
+ CPSW_DUAL_EMAC,
+};
+
struct cpsw_slave_data {
struct device_node *phy_node;
char phy_id[MII_BUS_ID_SIZE];
@@ -48,7 +53,7 @@ struct cpsw_platform_data {
u32 bd_ram_size; /*buffer descriptor ram size */
u32 mac_control; /* Mac control register */
u16 default_vlan; /* Def VLAN for ALE lookup in VLAN aware mode*/
- bool dual_emac; /* Enable Dual EMAC mode */
+ u8 switch_mode; /* Enable Dual EMAC/switchdev mode */
};
struct cpsw_slave {
--
2.7.4
^ permalink raw reply related
* [RFC v2, net-next, PATCH 2/4] net/cpsw_ale: add functions to modify VLANs/MDBs
From: Ilias Apalodimas @ 2018-06-14 11:11 UTC (permalink / raw)
To: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, jiri,
ivecera, andrew, f.fainelli
Cc: francois.ozog, yogeshs, spatton, Jose.Abreu, Ilias Apalodimas
In-Reply-To: <1528974690-31600-1-git-send-email-ilias.apalodimas@linaro.org>
A following patch introduces switchdev functionality. Add functions
to cpsw ALE engine to modify VLANs/MDBs
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
drivers/net/ethernet/ti/cpsw_ale.c | 188 ++++++++++++++++++++++++++++++++++++-
drivers/net/ethernet/ti/cpsw_ale.h | 10 ++
2 files changed, 195 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 93dc05c..98e6bcd 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -287,6 +287,9 @@ int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
if (cpsw_ale_get_mcast(ale_entry)) {
u8 addr[6];
+ if (cpsw_ale_get_super(ale_entry))
+ continue;
+
cpsw_ale_get_addr(ale_entry, addr);
if (!is_broadcast_ether_addr(addr))
cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
@@ -365,7 +368,7 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
cpsw_ale_set_addr(ale_entry, addr);
- cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
+ cpsw_ale_set_super(ale_entry, (flags & ALE_SUPER) ? 1 : 0);
cpsw_ale_set_mcast_state(ale_entry, mcast_state);
mask = cpsw_ale_get_port_mask(ale_entry,
@@ -409,6 +412,46 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
}
EXPORT_SYMBOL_GPL(cpsw_ale_del_mcast);
+static int cpsw_ale_read_mc(struct cpsw_ale *ale, u8 *addr, int flags, u16 vid)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
+ if (idx >= 0)
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ return cpsw_ale_get_port_mask(ale_entry, ale->port_mask_bits);
+}
+
+int cpsw_ale_mcast_add_modify(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid, int mcast_state)
+{
+ int mcast_members, ret;
+
+ mcast_members = cpsw_ale_read_mc(ale, addr, flags, vid) | port_mask;
+ ret = cpsw_ale_add_mcast(ale, addr, mcast_members, flags, vid,
+ mcast_state);
+
+ return ret;
+}
+
+int cpsw_ale_mcast_del_modify(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid)
+{
+ int mcast_members, ret;
+ int idx;
+
+ mcast_members = cpsw_ale_read_mc(ale, addr, flags, vid) & ~port_mask;
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
+ if (idx < 0)
+ return 0;
+ ret = cpsw_ale_del_mcast(ale, addr, mcast_members, flags, vid);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpsw_ale_mcast_del_modify);
+
/* ALE NetCP NU switch specific vlan functions */
static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
int reg_mcast, int unreg_mcast)
@@ -424,6 +467,52 @@ static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
}
+static int cpsw_ale_read_untagged(struct cpsw_ale *ale, u16 vid)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx >= 0)
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ return cpsw_ale_get_vlan_untag_force(ale_entry, ale->vlan_field_bits);
+}
+
+/* returns mask of current members for specificed vlan */
+static int cpsw_ale_read_vlan_members(struct cpsw_ale *ale, u16 vid)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx >= 0)
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ return cpsw_ale_get_vlan_member_list(ale_entry, ale->vlan_field_bits);
+}
+
+/* returns mask of registered/unregistered multicast registration */
+static int cpsw_ale_read_reg_unreg_mc(struct cpsw_ale *ale, u16 vid, bool unreg)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+ int ret;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx >= 0)
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ if (unreg)
+ ret = cpsw_ale_get_vlan_unreg_mcast(ale_entry,
+ ale->vlan_field_bits);
+ else
+ ret = cpsw_ale_get_vlan_reg_mcast(ale_entry,
+ ale->vlan_field_bits);
+
+ return ret;
+}
+
int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
int reg_mcast, int unreg_mcast)
{
@@ -462,6 +551,11 @@ EXPORT_SYMBOL_GPL(cpsw_ale_add_vlan);
int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
{
+ int reg_mcast =
+ cpsw_ale_read_reg_unreg_mc(ale, vid, 0) & port_mask;
+ int unreg_mcast =
+ cpsw_ale_read_reg_unreg_mc(ale, vid, 1) & port_mask;
+ int untag = cpsw_ale_read_untagged(ale, vid) & port_mask;
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
@@ -471,17 +565,105 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
cpsw_ale_read(ale, idx, ale_entry);
- if (port_mask)
+ if (port_mask) {
+ cpsw_ale_set_vlan_untag_force(ale_entry, untag,
+ ale->vlan_field_bits);
+ if (!ale->params.nu_switch_ale) {
+ cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast,
+ ale->vlan_field_bits);
+ cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
+ ale->vlan_field_bits);
+ } else {
+ cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast,
+ unreg_mcast);
+ }
cpsw_ale_set_vlan_member_list(ale_entry, port_mask,
ale->vlan_field_bits);
- else
+ } else {
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+ }
cpsw_ale_write(ale, idx, ale_entry);
+
return 0;
}
EXPORT_SYMBOL_GPL(cpsw_ale_del_vlan);
+int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
+ int untag_mask, int reg_mask, int unreg_mask)
+{
+ int ret = 0;
+ int vlan_members = cpsw_ale_read_vlan_members(ale, vid) & ~port_mask;
+ int reg_mcast_members =
+ cpsw_ale_read_reg_unreg_mc(ale, vid, 0) & ~port_mask;
+ int unreg_mcast_members =
+ cpsw_ale_read_reg_unreg_mc(ale, vid, 1) & ~port_mask;
+ int untag_members = cpsw_ale_read_untagged(ale, vid) & ~port_mask;
+
+ vlan_members |= port_mask;
+ untag_members |= untag_mask;
+ reg_mcast_members |= reg_mask;
+ unreg_mcast_members |= unreg_mask;
+
+ ret = cpsw_ale_add_vlan(ale, vid, vlan_members, untag_members,
+ reg_mcast_members, unreg_mcast_members);
+ if (ret) {
+ dev_err(ale->params.dev, "Unable to add vlan\n");
+ return ret;
+ }
+ dev_dbg(ale->params.dev, "port mask 0x%x untag 0x%x\n", vlan_members,
+ untag_mask);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpsw_ale_vlan_add_modify);
+
+int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask)
+{
+ int ret = 0;
+ int vlan_members;
+
+ vlan_members = cpsw_ale_read_vlan_members(ale, vid);
+ vlan_members &= ~port_mask;
+
+ ret = cpsw_ale_del_vlan(ale, vid, vlan_members);
+ if (ret) {
+ dev_err(ale->params.dev, "Unable to del vlan\n");
+ return ret;
+ }
+ dev_dbg(ale->params.dev, "port mask 0x%x\n", port_mask);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpsw_ale_vlan_del_modify);
+
+void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
+ bool add)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS];
+ int unreg_members = 0;
+ int type, idx;
+
+ for (idx = 0; idx < ale->params.ale_entries; idx++) {
+ cpsw_ale_read(ale, idx, ale_entry);
+ type = cpsw_ale_get_entry_type(ale_entry);
+ if (type != ALE_TYPE_VLAN)
+ continue;
+
+ unreg_members =
+ cpsw_ale_get_vlan_unreg_mcast(ale_entry,
+ ale->vlan_field_bits);
+ if (add)
+ unreg_members |= unreg_mcast_mask;
+ else
+ unreg_members &= ~unreg_mcast_mask;
+ cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_members,
+ ale->vlan_field_bits);
+ cpsw_ale_write(ale, idx, ale_entry);
+ }
+}
+EXPORT_SYMBOL_GPL(cpsw_ale_set_unreg_mcast);
+
void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti)
{
u32 ale_entry[ALE_ENTRY_WORDS];
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index d4fe901..1eef640 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -123,4 +123,14 @@ int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
int control, int value);
void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data);
+int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
+ int untag_mask, int reg_mcast, int unreg_mcast);
+int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask);
+int cpsw_ale_mcast_add_modify(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid, int mcast_state);
+int cpsw_ale_mcast_del_modify(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid);
+void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
+ bool add);
+
#endif
--
2.7.4
^ permalink raw reply related
* [RFC v2, net-next, PATCH 1/4] net/cpsw: move common headers definitions to cpsw_priv.h
From: Ilias Apalodimas @ 2018-06-14 11:11 UTC (permalink / raw)
To: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, jiri,
ivecera, andrew, f.fainelli
Cc: francois.ozog, yogeshs, spatton, Jose.Abreu, Ilias Apalodimas
In-Reply-To: <1528974690-31600-1-git-send-email-ilias.apalodimas@linaro.org>
A following patch introduces switchdev functionality. Move common
definitions to a private header file
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
drivers/net/ethernet/ti/cpsw.c | 111 +---------------------------
drivers/net/ethernet/ti/cpsw_priv.h | 141 ++++++++++++++++++++++++++++++++++++
2 files changed, 142 insertions(+), 110 deletions(-)
create mode 100644 drivers/net/ethernet/ti/cpsw_priv.h
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 534596c..d13b57f 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -42,6 +42,7 @@
#include "cpsw.h"
#include "cpsw_ale.h"
+#include "cpsw_priv.h"
#include "cpts.h"
#include "davinci_cpdma.h"
@@ -89,7 +90,6 @@ do { \
#define CPSW_VERSION_3 0x19010f
#define CPSW_VERSION_4 0x190112
-#define HOST_PORT_NUM 0
#define CPSW_ALE_PORTS_NUM 3
#define SLIVER_SIZE 0x40
@@ -310,16 +310,6 @@ struct cpsw_ss_regs {
#define CPSW_MAX_BLKS_TX_SHIFT 4
#define CPSW_MAX_BLKS_RX 5
-struct cpsw_host_regs {
- u32 max_blks;
- u32 blk_cnt;
- u32 tx_in_ctl;
- u32 port_vlan;
- u32 tx_pri_map;
- u32 cpdma_tx_pri_map;
- u32 cpdma_rx_chan_map;
-};
-
struct cpsw_sliver_regs {
u32 id_ver;
u32 mac_control;
@@ -371,105 +361,6 @@ struct cpsw_hw_stats {
u32 rxdmaoverruns;
};
-struct cpsw_slave_data {
- struct device_node *phy_node;
- char phy_id[MII_BUS_ID_SIZE];
- int phy_if;
- u8 mac_addr[ETH_ALEN];
- u16 dual_emac_res_vlan; /* Reserved VLAN for DualEMAC */
-};
-
-struct cpsw_platform_data {
- struct cpsw_slave_data *slave_data;
- u32 ss_reg_ofs; /* Subsystem control register offset */
- u32 channels; /* number of cpdma channels (symmetric) */
- u32 slaves; /* number of slave cpgmac ports */
- u32 active_slave; /* time stamping, ethtool and SIOCGMIIPHY slave */
- u32 ale_entries; /* ale table size */
- u32 bd_ram_size; /*buffer descriptor ram size */
- u32 mac_control; /* Mac control register */
- u16 default_vlan; /* Def VLAN for ALE lookup in VLAN aware mode*/
- bool dual_emac; /* Enable Dual EMAC mode */
-};
-
-struct cpsw_slave {
- void __iomem *regs;
- struct cpsw_sliver_regs __iomem *sliver;
- int slave_num;
- u32 mac_control;
- struct cpsw_slave_data *data;
- struct phy_device *phy;
- struct net_device *ndev;
- u32 port_vlan;
-};
-
-static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
-{
- return readl_relaxed(slave->regs + offset);
-}
-
-static inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset)
-{
- writel_relaxed(val, slave->regs + offset);
-}
-
-struct cpsw_vector {
- struct cpdma_chan *ch;
- int budget;
-};
-
-struct cpsw_common {
- struct device *dev;
- struct cpsw_platform_data data;
- struct napi_struct napi_rx;
- struct napi_struct napi_tx;
- struct cpsw_ss_regs __iomem *regs;
- struct cpsw_wr_regs __iomem *wr_regs;
- u8 __iomem *hw_stats;
- struct cpsw_host_regs __iomem *host_port_regs;
- u32 version;
- u32 coal_intvl;
- u32 bus_freq_mhz;
- int rx_packet_max;
- struct cpsw_slave *slaves;
- struct cpdma_ctlr *dma;
- struct cpsw_vector txv[CPSW_MAX_QUEUES];
- struct cpsw_vector rxv[CPSW_MAX_QUEUES];
- struct cpsw_ale *ale;
- bool quirk_irq;
- bool rx_irq_disabled;
- bool tx_irq_disabled;
- u32 irqs_table[IRQ_NUM];
- struct cpts *cpts;
- int rx_ch_num, tx_ch_num;
- int speed;
- int usage_count;
-};
-
-struct cpsw_priv {
- struct net_device *ndev;
- struct device *dev;
- u32 msg_enable;
- u8 mac_addr[ETH_ALEN];
- bool rx_pause;
- bool tx_pause;
- u32 emac_port;
- struct cpsw_common *cpsw;
-};
-
-struct cpsw_stats {
- char stat_string[ETH_GSTRING_LEN];
- int type;
- int sizeof_stat;
- int stat_offset;
-};
-
-enum {
- CPSW_STATS,
- CPDMA_RX_STATS,
- CPDMA_TX_STATS,
-};
-
#define CPSW_STAT(m) CPSW_STATS, \
sizeof(((struct cpsw_hw_stats *)0)->m), \
offsetof(struct cpsw_hw_stats, m)
diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h
new file mode 100644
index 0000000..3b02a83
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpsw_priv.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+
+#define HOST_PORT_NUM 0
+#define IRQ_NUM 2
+#define CPSW_MAX_QUEUES 8
+
+#define CPSW_VERSION_1 0x19010a
+#define CPSW_VERSION_2 0x19010c
+#define CPSW_VERSION_3 0x19010f
+#define CPSW_VERSION_4 0x190112
+
+/* CPSW_PORT_V1 */
+#define CPSW1_MAX_BLKS 0x00 /* Maximum FIFO Blocks */
+#define CPSW1_BLK_CNT 0x04 /* FIFO Block Usage Count (Read Only) */
+#define CPSW1_TX_IN_CTL 0x08 /* Transmit FIFO Control */
+#define CPSW1_PORT_VLAN 0x0c /* VLAN Register */
+#define CPSW1_TX_PRI_MAP 0x10 /* Tx Header Priority to Switch Pri Mapping */
+#define CPSW1_TS_CTL 0x14 /* Time Sync Control */
+#define CPSW1_TS_SEQ_LTYPE 0x18 /* Time Sync Sequence ID Offset and Msg Type */
+#define CPSW1_TS_VLAN 0x1c /* Time Sync VLAN1 and VLAN2 */
+
+/* CPSW_PORT_V2 */
+#define CPSW2_CONTROL 0x00 /* Control Register */
+#define CPSW2_MAX_BLKS 0x08 /* Maximum FIFO Blocks */
+#define CPSW2_BLK_CNT 0x0c /* FIFO Block Usage Count (Read Only) */
+#define CPSW2_TX_IN_CTL 0x10 /* Transmit FIFO Control */
+#define CPSW2_PORT_VLAN 0x14 /* VLAN Register */
+#define CPSW2_TX_PRI_MAP 0x18 /* Tx Header Priority to Switch Pri Mapping */
+#define CPSW2_TS_SEQ_MTYPE 0x1c /* Time Sync Sequence ID Offset and Msg Type */
+
+struct cpsw_slave_data {
+ struct device_node *phy_node;
+ char phy_id[MII_BUS_ID_SIZE];
+ int phy_if;
+ u8 mac_addr[ETH_ALEN];
+ u16 dual_emac_res_vlan; /* Reserved VLAN for DualEMAC */
+};
+
+struct cpsw_platform_data {
+ struct cpsw_slave_data *slave_data;
+ u32 ss_reg_ofs; /* Subsystem control register offset */
+ u32 channels; /* number of cpdma channels (symmetric) */
+ u32 slaves; /* number of slave cpgmac ports */
+ u32 active_slave; /* time stamping, ethtool and SIOCGMIIPHY slave */
+ u32 ale_entries; /* ale table size */
+ u32 bd_ram_size; /*buffer descriptor ram size */
+ u32 mac_control; /* Mac control register */
+ u16 default_vlan; /* Def VLAN for ALE lookup in VLAN aware mode*/
+ bool dual_emac; /* Enable Dual EMAC mode */
+};
+
+struct cpsw_slave {
+ void __iomem *regs;
+ struct cpsw_sliver_regs __iomem *sliver;
+ int slave_num;
+ u32 mac_control;
+ struct cpsw_slave_data *data;
+ struct phy_device *phy;
+ struct net_device *ndev;
+ u32 port_vlan;
+};
+
+struct cpsw_vector {
+ struct cpdma_chan *ch;
+ int budget;
+};
+
+struct cpsw_common {
+ struct device *dev;
+ struct cpsw_platform_data data;
+ struct napi_struct napi_rx;
+ struct napi_struct napi_tx;
+ struct cpsw_ss_regs __iomem *regs;
+ struct cpsw_wr_regs __iomem *wr_regs;
+ u8 __iomem *hw_stats;
+ struct cpsw_host_regs __iomem *host_port_regs;
+ u32 version;
+ u32 coal_intvl;
+ u32 bus_freq_mhz;
+ int rx_packet_max;
+ struct cpsw_slave *slaves;
+ struct cpdma_ctlr *dma;
+ struct cpsw_vector txv[CPSW_MAX_QUEUES];
+ struct cpsw_vector rxv[CPSW_MAX_QUEUES];
+ struct cpsw_ale *ale;
+ bool quirk_irq;
+ bool rx_irq_disabled;
+ bool tx_irq_disabled;
+ u32 irqs_table[IRQ_NUM];
+ struct cpts *cpts;
+ int rx_ch_num, tx_ch_num;
+ int speed;
+ int usage_count;
+};
+
+struct cpsw_priv {
+ struct net_device *ndev;
+ struct device *dev;
+ u32 msg_enable;
+ u8 mac_addr[ETH_ALEN];
+ bool rx_pause;
+ bool tx_pause;
+ u8 port_state[3];
+ u32 emac_port;
+ struct cpsw_common *cpsw;
+};
+
+struct cpsw_stats {
+ char stat_string[ETH_GSTRING_LEN];
+ int type;
+ int sizeof_stat;
+ int stat_offset;
+};
+
+enum {
+ CPSW_STATS,
+ CPDMA_RX_STATS,
+ CPDMA_TX_STATS,
+};
+
+struct cpsw_host_regs {
+ u32 max_blks;
+ u32 blk_cnt;
+ u32 tx_in_ctl;
+ u32 port_vlan;
+ u32 tx_pri_map;
+ u32 cpdma_tx_pri_map;
+ u32 cpdma_rx_chan_map;
+};
+
+static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
+{
+ return readl_relaxed(slave->regs + offset);
+}
+
+static inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset)
+{
+ writel_relaxed(val, slave->regs + offset);
+}
--
2.7.4
^ permalink raw reply related
* [RFC v2, net-next, PATCH 0/4] Add switchdev on TI-CPSW
From: Ilias Apalodimas @ 2018-06-14 11:11 UTC (permalink / raw)
To: netdev, grygorii.strashko, ivan.khoronzhuk, nsekhar, jiri,
ivecera, andrew, f.fainelli
Cc: francois.ozog, yogeshs, spatton, Jose.Abreu, Ilias Apalodimas
Hello,
This the RFC v2 which does not register the CPU port based on net-next.
I didn't manage to rewrite the driver and splitting it to
common library-old-new but, i did reorganize the patches a bit based
on Andrew's suggestions. Hopefully it's easier to read.
patch #1: Prepares headers files and move common code to cpsw_priv.h.
patch #2: Adds functions to ALE for modifying VLANs/MDBs.
patch #3: Prepares cpsw driver for switchdev mode, without changing any
of the funtionality.
patch #4: Adds new mode of operation based on switchdev.
In order to enable this you need enable CONFIG_NET_SWITCHDEV,
CONFIG_BRIDGE_VLAN_FILTERING, CONFIG_TI_CPSW_SWITCHDEV
and add this to udev config:
SUBSYSTEM=="net", ACTION=="add", ATTR{phys_switch_id}=="0f011900", \
ATTR{phys_port_name}!="", NAME="sw0$attr{phys_port_name}"
Since the phys_switch_id is based on cpsw version, users with different
version will need to do 'ip -d link show dev sw0p1 | grep switchid' and
replace with the correct value.
This patch creates 2 ports, sw0p1 and sw0p2 both connected to PHYs.
Bridge setup:
ip link add name br0 type bridge
ip link set dev br0 type bridge ageing_time 1000
ip link set dev br0 type bridge vlan_filtering 1
ip link set dev sw0p1 up
ip link set dev sw0p2 up
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
ifconfig br0 up
- VLAN config:
untagged:
bridge vlan add dev sw0p1 vid 100 pvid untagged master
bridge vlan add dev sw0p2 vid 100 pvid untagged master
tagged:
bridge vlan add dev sw0p1 vid 100 master
bridge vlan add dev sw0p2 vid 100 master
IP address on br0:
This will add VLAN 100 on the cpu port.
bridge vlan add dev br0 vid 100 pvid untagged self
udhcpc -i br0
- FDBs:
FDBs are automatically added on the appropriate switch port uppon detection
Manually adding FDBs:
bridge fdb add aa:bb:cc:dd:ee:ff dev sw0p1 master vlan 100
bridge fdb add aa:bb:cc:dd:ee:fe dev sw0p2 master
- MDBs:
MDBs are automatically added on the appropriate switch port uppon detection
Manually adding MDBs:
bridge mdb add dev br0 port sw0p1 grp 239.1.1.1 permanent vid 100
- Multicast testing client-port1(tagged on vlan 100) server-port1
switch-config is provided by TI (https://git.ti.com/switch-config)
and is used to verify correct switch configuration.
1. switch-config output
- type: vlan , vid = 100, untag_force = 0x4, reg_mcast = 0x6,
unreg_mcast = 0x0, member_list = 0x6
Server running on sw0p2: iperf -s -u -B 239.1.1.1 -i 1
Client running on sw0p1: iperf -c 239.1.1.1 -u -b 990m -f m -i 5 -t 3600
No IGMP reaches the CPU port to add MDBs(since CPU does not receive
unregistered multicast as programmed).
If the MDB is added manually via:
bridge mdb add dev br0 port sw0p2 grp 239.1.1.1 permanent vid 100
or unregistered flooding is enabled via:
bridge link set dev sw0p2 mcast_flood on
Multicast traffic is offloaded as expected.
2. switch-config output
- type: vlan , vid = 100, untag_force = 0x7, reg_mcast = 0x7,
unreg_mcast = 0x1, member_list = 0x7
In this case CPU port receives the IGMP message and programs the
switch accordingly.
tcpdump on br0 shows no packets. If the MDB entry is removed with
"bridge mdb del dev br0 port sw0p1 grp 239.1.1.1 permanent"
br0 is flooded with multicast packets correctly(since unreg multicast is
set for the CPU port).
If the the mdb entry is manually added tcpdump shows no packets and
multicast offloading starts working again.
root@ti:~# bridge mdb show
dev br0 port sw0p1 grp ff02::fb temp offload vid 100
dev br0 port sw0p1 grp 239.1.1.1 temp offload vid 100
root@ti:~# switch-config -d
type: mcast, vid = 100, addr = 01:00:5e:01:01:01, mcast_state = f, \
no super, port_mask = 0x2
- Multicast testing server-port0 client-port1
CPU port(port 0) does not show on bridge mdb show
Using ti's switch-config to dump the switch status shows that the MDB is
installed correctly.
root@ti:~# switch-config -d
type: mcast, vid = 100, addr = 01:00:5e:01:01:01, mcast_state = f, \
no super, port_mask = 0x1
- registered multicast:
Setting on/off and IFF_MULTICAST (on eth0/eth1/br0) will affect registered
multicast masks programmed in the switch(for port1, port2, cpu port
respectively).
This muct occur before adding VLANs on the interfaces. If you change the
flag after the VLAN configuration you need to re-issue the VLAN config
commands.
If CPU port is participating the proper VLANs MDBs/FDBs will be
offloaded by the switch as described in switchdev API. This will also be
reflected on "bridge vlan/fdb/mdb show" command(in case the host sends
the join the mdb entry won't show there, but ALE status confirms that
it's added).
- NFS:
The only way for NFS to work is by chrooting to a minimal environment when
switch configuration that will affect connectivity is needed.
Assuming you are booting NFS with eth1 interface(the script is hacky and
it's just there to prove NFS is doable).
setup.sh:
#!/bin/sh
mkdir proc
mount -t proc none /proc
ifconfig br0 > /dev/null
if [ $? -ne 0 ]; then
echo "Setting up bridge"
ip link add name br0 type bridge
ip link set dev br0 type bridge ageing_time 1000
ip link set dev br0 type bridge vlan_filtering 1
ip link set eth1 down
ip link set eth1 name sw0p1
ip link set dev sw0p1 up
ip link set dev sw0p2 up
ip link set dev sw0p2 master br0
ip link set dev sw0p1 master br0
bridge vlan add dev br0 vid 1 pvid untagged self
ifconfig sw0p1 0.0.0.0
udhchc -i br0
fi
umount /proc
run_nfs.sh:
#!/bin/sh
mkdir /tmp/root/bin -p
mkdir /tmp/root/lib -p
cp -r /lib/ /tmp/root/
cp -r /bin/ /tmp/root/
cp /sbin/ip /tmp/root/bin
cp /sbin/bridge /tmp/root/bin
cp /sbin/ifconfig /tmp/root/bin
cp /sbin/udhcpc /tmp/root/bin
cp /path/to/setup.sh /tmp/root/bin
chroot /tmp/root/ busybox sh /bin/run_nfs.sh
run ./run_nfs.sh
- Current issues/future work:
1. For this hardware and it's applications it's essential to control the
CPU port individually. After removing the CPU port we lost the ability
to control unregistered multicast traffic flags.
This code unconditionally(if it participates on that VLAN) adds CPU port
on the unregistered multicast mask, while for ports 1 and 2 this is
configurable via:
"bridge link set dev eth1 mcast_flood on/off"
Petr Machata introduced a funtionality on
VLANs(9c86ce2c1ae337fc10568a12aea812ed03de8319) where the command
"bridge vlan add dev br0 vid 100 pvid untagged self" is propagated to the
driver and allows us to configure the CPU port.
Adding something similar for MDBs i.e
"bridge link set dev br0 mcast_flood on self" that reaches the driver
is an idea on how to control the CPU port independently and removing the
need to add/remove the CPU port on the vlan group for this to happen.
2. VLAN CoS is always set to 0
3. Add support for ageing configuration
4. ALE_P0_UNI_FLOOD can be controlled via:
"bridge link set dev br0 flood on self" if this propagates to the driver
as well.
5. Add documentation for CPSW configuration on the patch
- Changes since RFC v1:
- Removed CPU port registration. User can now add CPU port VLANs with
"bridge vlan add/del dev br0 vid 100 pvid untagged self".
- Removing VLANs will modify registered/unregistered multicast port masks
properly.
- ALE_P0_UNI_FLOOD is controlled from bridge members. As long as the
bridge has members(switch interfaces) this will be enabled.
- added management for SWITCHDEV_OBJ_ID_HOST_MDB to control MDBs for the
CPU port.
- Added STP support.
- Added multicast flood support. CPU port is always enabled for now.
Ilias Apalodimas (4):
net/cpsw: move common headers definitions to cpsw_priv.h
net/cpsw_ale: add functions to modify VLANs/MDBs
net/cpsw: prepare cpsw for switchdev support
net/cpsw_switchdev: add switchdev mode of operation on cpsw driver
drivers/net/ethernet/ti/Kconfig | 9 +
drivers/net/ethernet/ti/Makefile | 1 +
drivers/net/ethernet/ti/cpsw.c | 555 ++++++++++++++++++++++---------
drivers/net/ethernet/ti/cpsw_ale.c | 188 ++++++++++-
drivers/net/ethernet/ti/cpsw_ale.h | 10 +
drivers/net/ethernet/ti/cpsw_priv.h | 148 +++++++++
drivers/net/ethernet/ti/cpsw_switchdev.c | 418 +++++++++++++++++++++++
drivers/net/ethernet/ti/cpsw_switchdev.h | 4 +
8 files changed, 1167 insertions(+), 166 deletions(-)
create mode 100644 drivers/net/ethernet/ti/cpsw_priv.h
create mode 100644 drivers/net/ethernet/ti/cpsw_switchdev.c
create mode 100644 drivers/net/ethernet/ti/cpsw_switchdev.h
--
2.7.4
^ permalink raw reply
* Re: [PATCH] selftests: bpf: config: add config fragments
From: William Tu @ 2018-06-14 11:06 UTC (permalink / raw)
To: Daniel Borkmann
Cc: Anders Roxell, Alexei Starovoitov, Shuah Khan,
Linux Kernel Network Developers, LKML, linux-kselftest
In-Reply-To: <d6851756-ae3b-09ec-f487-1eeece6bd4c6@iogearbox.net>
On Tue, Jun 12, 2018 at 5:08 PM, Daniel Borkmann <daniel@iogearbox.net> wrote:
> On 06/12/2018 01:05 PM, Anders Roxell wrote:
>> Tests test_tunnel.sh fails due to config fragments ins't enabled.
>>
>> Fixes: 933a741e3b82 ("selftests/bpf: bpf tunnel test.")
>> Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
>> ---
>>
>> All tests passes except ip6gretap that still fails. I'm unsure why.
>> Ideas?
Hi Anders,
ip6erspan is based on ip6gretap, does ip6erspan pass?
Regards,
William
^ 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