mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
Merge pull request #909 from kernelkit/update-kernel
Update kernel to latest LTS (6.12.11)
This commit is contained in:
@@ -27,7 +27,7 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.3"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.11"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
|
||||
@@ -27,7 +27,7 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.3"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.11"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
|
||||
@@ -26,7 +26,7 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INF
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.3"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.11"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
|
||||
@@ -26,7 +26,7 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INF
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.3"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.11"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
|
||||
+2
-1
@@ -12,7 +12,8 @@ All notable changes to the project are documented in this file.
|
||||
- Add support for more mDNS settings: allow/deny interfaces, acting
|
||||
as "reflector" and filtering of reflected services. Issue #678
|
||||
- Review of default `sysctl` settings, issue #829
|
||||
- Upgrade Linux kernel to 6.12.3 (LTS)
|
||||
- Upgrade Linux kernel to 6.12.11 (LTS)
|
||||
- Upgrade Buildroot to 2024.02.10 (LTS)
|
||||
- Add the possibility to change the boot order for the system with a
|
||||
RPC and add boot order to operational datastore.
|
||||
- SSH Server is now configurable, issue #441
|
||||
|
||||
+6
-3
@@ -1,15 +1,18 @@
|
||||
From 71fe6d55812e13fcbcbc703b925a3be5789fa360 Mon Sep 17 00:00:00 2001
|
||||
From 998f0e99f2bd7ab54e1d25acac4227335c8caaec Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 12 Mar 2024 10:27:24 +0100
|
||||
Subject: [PATCH 01/24] [FIX] net: dsa: mv88e6xxx: Fix timeout on waiting for
|
||||
Subject: [PATCH 01/25] [FIX] net: dsa: mv88e6xxx: Fix timeout on waiting for
|
||||
PPU on 6393X
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
In a multi-chip setup, delays of up to 750ms are observed before the
|
||||
device (6393X) signals completion of PPU initialization (Global 1,
|
||||
register 0, bit 15). Therefore, increase the timeout threshold to 1s.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From b1ebd0aa174cae173c09772ff465eee20bfb8cf1 Mon Sep 17 00:00:00 2001
|
||||
From 3002b9e08272f3d740c2b582cf9b01fa1fde46b8 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 27 Mar 2024 15:52:43 +0100
|
||||
Subject: [PATCH 02/24] net: dsa: mv88e6xxx: Improve indirect register access
|
||||
Subject: [PATCH 02/25] net: dsa: mv88e6xxx: Improve indirect register access
|
||||
perf on 6393
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
When operating in multi-chip mode, the 6393 family maps a subset of
|
||||
@@ -14,7 +17,7 @@ Therefore, add a new set of SMI operations which remaps accesses to
|
||||
such registers to the corresponding directly addressable register. All
|
||||
other accesses use the regular indirect interface.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 7 +++
|
||||
drivers/net/dsa/mv88e6xxx/global1.h | 3 ++
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From 178f00dd84b9c76f065edba012d51d82cda89188 Mon Sep 17 00:00:00 2001
|
||||
From 6bad36ecd3bb8f9b97c51f8ee2409f250344c1fc Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Mon, 22 Apr 2024 23:18:01 +0200
|
||||
Subject: [PATCH 03/24] net: dsa: mv88e6xxx: Honor ports being managed via
|
||||
Subject: [PATCH 03/25] net: dsa: mv88e6xxx: Honor ports being managed via
|
||||
in-band-status
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Keep all link parameters in their unforced states when the port is
|
||||
@@ -14,7 +17,7 @@ This state is the default set up by mv88e6xxx_port_setup_mac(), so all
|
||||
we have to do is to make the phylink MAC callbacks no-ops in cases
|
||||
when in-band-status is being used.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From 41c8514d46aed546dae97817b582966aec19ac19 Mon Sep 17 00:00:00 2001
|
||||
From 980366a1f8709fdfe643edb666c86a916c681a6c Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 24 Apr 2024 22:41:04 +0200
|
||||
Subject: [PATCH 04/24] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user
|
||||
Subject: [PATCH 04/25] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user
|
||||
ports on 6393X
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
For packets with a DA in the IEEE reserved L2 group range, originating
|
||||
@@ -30,7 +33,7 @@ switch would try to trap it back to the CPU. Given that the CPU is
|
||||
trusted, instead assume that it indeed meant for the packet to be
|
||||
forwarded like any other.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/port.c | 31 +++++++++++++++++++++++++------
|
||||
1 file changed, 25 insertions(+), 6 deletions(-)
|
||||
+6
-3
@@ -1,13 +1,16 @@
|
||||
From a78a31711dcb661b1b0f4d2a6e692112b53ee1d3 Mon Sep 17 00:00:00 2001
|
||||
From cfc55d98057160753158b7c5357c94ac24d918fe Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 16 Nov 2023 19:44:32 +0100
|
||||
Subject: [PATCH 05/24] net: dsa: mv88e6xxx: Add LED infrastructure
|
||||
Subject: [PATCH 05/25] net: dsa: mv88e6xxx: Add LED infrastructure
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Parse DT for LEDs and register them for devices that support it,
|
||||
though no actual implementations exist yet.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 5 +-
|
||||
+6
-3
@@ -1,7 +1,10 @@
|
||||
From 759f9f0a451dc0c3bc8e268ab2609e911f05e472 Mon Sep 17 00:00:00 2001
|
||||
From 180f2b90c73bc9fdfb27335327571daf8507f9c8 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 16 Nov 2023 21:59:35 +0100
|
||||
Subject: [PATCH 06/24] net: dsa: mv88e6xxx: Add LED support for 6393X
|
||||
Subject: [PATCH 06/25] net: dsa: mv88e6xxx: Add LED support for 6393X
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Trigger support:
|
||||
@@ -9,7 +12,7 @@ Trigger support:
|
||||
- "timer"
|
||||
- "netdev"
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 1 +
|
||||
drivers/net/dsa/mv88e6xxx/leds.c | 229 +++++++++++++++++++++++++++++++
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From 18e2a5f297ee800b2c51adbf9958bc2b96e2370d Mon Sep 17 00:00:00 2001
|
||||
From 2e42839d4edb250b298f7683975382e9ec97c9a9 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 28 May 2024 10:38:42 +0200
|
||||
Subject: [PATCH 07/24] net: dsa: tag_dsa: Use tag priority as initial
|
||||
Subject: [PATCH 07/25] net: dsa: tag_dsa: Use tag priority as initial
|
||||
skb->priority
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Use the 3-bit priority field from the DSA tag as the initial packet
|
||||
@@ -20,7 +23,7 @@ can do with an "ingress-qos-map" on VLAN interfaces. Until that is
|
||||
implemented, support the setup that is likely to be the most common; a
|
||||
1:1 mapping from FPri to skb->priority.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
net/dsa/tag_dsa.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From 6fc99a4c2e4a263acf2ba3fb9e8a85f12661ba60 Mon Sep 17 00:00:00 2001
|
||||
From 681fc63548bae02cd286042a3470011617ff78fd Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 16 Jan 2024 16:00:55 +0100
|
||||
Subject: [PATCH 08/24] net: dsa: Support MDB memberships whose L2 addresses
|
||||
Subject: [PATCH 08/25] net: dsa: Support MDB memberships whose L2 addresses
|
||||
overlap
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Multiple IP multicast groups (32 for v4, 2^80 for v6) map to the same
|
||||
@@ -30,7 +33,7 @@ needed to do this is already in place, since it is also needed on CPU
|
||||
and DSA ports. Thus, "implement" this by simply removing the guards
|
||||
which previously skipped reference countung on user ports.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
net/dsa/switch.c | 16 ----------------
|
||||
1 file changed, 16 deletions(-)
|
||||
+6
-3
@@ -1,10 +1,13 @@
|
||||
From 7b546aa81ea913bf3795dc4c843992c84c29d3b7 Mon Sep 17 00:00:00 2001
|
||||
From d1c7aeac75ffe6e1350d8a08ee9ba99209636df5 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 21 Mar 2024 19:12:15 +0100
|
||||
Subject: [PATCH 09/24] net: dsa: Support EtherType based priority overrides
|
||||
Subject: [PATCH 09/25] net: dsa: Support EtherType based priority overrides
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
include/net/dsa.h | 4 ++++
|
||||
net/dsa/user.c | 56 +++++++++++++++++++++++++++++++++++++++++++++--
|
||||
+6
-3
@@ -1,11 +1,14 @@
|
||||
From 98a469ebd1c7a90aa3ab7dffcd58515d0b18376a Mon Sep 17 00:00:00 2001
|
||||
From 79d68d69f6cd6cf57ef5ed4bcba45134ff8ba174 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Fri, 22 Mar 2024 16:15:43 +0100
|
||||
Subject: [PATCH 10/24] net: dsa: mv88e6xxx: Support EtherType based priority
|
||||
Subject: [PATCH 10/25] net: dsa: mv88e6xxx: Support EtherType based priority
|
||||
overrides
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 64 +++++++++++++++++++++++++++++
|
||||
drivers/net/dsa/mv88e6xxx/chip.h | 21 ++++++++++
|
||||
+6
-3
@@ -1,7 +1,10 @@
|
||||
From f96b11cbcdf0cfaa60ed9be75f5b2e32c5d6c036 Mon Sep 17 00:00:00 2001
|
||||
From 57eabbff1169a5641c59fc698d7b122d17733d49 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 28 May 2024 11:04:22 +0200
|
||||
Subject: [PATCH 11/24] net: dsa: mv88e6xxx: Add mqprio qdisc support
|
||||
Subject: [PATCH 11/25] net: dsa: mv88e6xxx: Add mqprio qdisc support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Add support for attaching mqprio qdisc's to mv88e6xxx ports and use
|
||||
@@ -25,7 +28,7 @@ Since FPri is always a 3-bit field, even on older chips with only 4
|
||||
physical queues, always report 8 queues and let the chip's policy
|
||||
handle the mapping down to the "real" number.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 70 ++++++++++++++++++++++++++++++++
|
||||
net/dsa/tag_dsa.c | 4 +-
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From 0dea11bbeb08eab148807853626061591e5b8a7c Mon Sep 17 00:00:00 2001
|
||||
From 752cce791dfe31525e3974d6f6419e4be0535343 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 29 May 2024 13:20:41 +0200
|
||||
Subject: [PATCH 12/24] net: dsa: mv88e6xxx: Use VLAN prio over IP when both
|
||||
Subject: [PATCH 12/25] net: dsa: mv88e6xxx: Use VLAN prio over IP when both
|
||||
are available
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Switch the priority sourcing precdence to prefer VLAN PCP over IP
|
||||
@@ -23,7 +26,7 @@ main reasons for choosing the new default:
|
||||
core over trusted VLAN trunks, the packet should keep its original
|
||||
priority, independent of what inner protocol fields may indicate.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From 15d0f3332c1253f90d47e4a949baa3bba42601d0 Mon Sep 17 00:00:00 2001
|
||||
From b3b9b97cbe4eebd6cd3d68744e11a1bde5b98a47 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 26 Nov 2024 19:45:59 +0100
|
||||
Subject: [PATCH 13/24] [FIX] net: dsa: mv88e6xxx: Trap locally terminated
|
||||
Subject: [PATCH 13/25] [FIX] net: dsa: mv88e6xxx: Trap locally terminated
|
||||
VLANs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Before this change, in a setup like the following, packets assigned to
|
||||
@@ -25,7 +28,7 @@ marked as policy entries. As the VTU policy of user ports is already
|
||||
set to TRAP (to ensure proper standalone port operation), this will
|
||||
cause all packets assigned to these VLANs to properly terminated.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 33 ++++++++++++++++++--------------
|
||||
include/net/switchdev.h | 4 ++++
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From f07acc439e8e803cb16528db21f0dfa11029caf4 Mon Sep 17 00:00:00 2001
|
||||
From 1e19f28f4f44973f349ad8bbb2fe0f4624e3c0f3 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 19 Sep 2023 18:38:10 +0200
|
||||
Subject: [PATCH 14/24] net: phy: marvell10g: Support firmware loading on
|
||||
Subject: [PATCH 14/25] net: phy: marvell10g: Support firmware loading on
|
||||
88X3310
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
When probing, if a device is waiting for firmware to be loaded into
|
||||
@@ -12,7 +15,7 @@ We have no choice but to bail out of the probe if firmware is not
|
||||
available, as the device does not have any built-in image on which to
|
||||
fall back.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 161 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 161 insertions(+)
|
||||
+6
-3
@@ -1,15 +1,18 @@
|
||||
From 5fece876f73fadd87c9de33fbe4d5472679474bd Mon Sep 17 00:00:00 2001
|
||||
From 95ff23729224c6c08801c2dba8830b18c177431b Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 21 Nov 2023 20:15:24 +0100
|
||||
Subject: [PATCH 15/24] net: phy: marvell10g: Fix power-up when strapped to
|
||||
Subject: [PATCH 15/25] net: phy: marvell10g: Fix power-up when strapped to
|
||||
start powered down
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
On devices which are hardware strapped to start powered down (PDSTATE
|
||||
== 1), make sure that we clear the power-down bit on all units
|
||||
affected by this setting.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 18 +++++++++++++++---
|
||||
1 file changed, 15 insertions(+), 3 deletions(-)
|
||||
+6
-3
@@ -1,7 +1,10 @@
|
||||
From 5f54194131bd332054da0a9143efc4423dac32b7 Mon Sep 17 00:00:00 2001
|
||||
From ecdfc7324dd50d79c81af453699467023d72e2bf Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 15 Nov 2023 20:58:42 +0100
|
||||
Subject: [PATCH 16/24] net: phy: marvell10g: Add LED support for 88X3310
|
||||
Subject: [PATCH 16/25] net: phy: marvell10g: Add LED support for 88X3310
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Pickup the LEDs from the state in which the hardware reset or
|
||||
@@ -18,7 +21,7 @@ Trigger support:
|
||||
- "netdev": Offload link or duplex information to the solid behavior;
|
||||
tx and/or rx activity to blink behavior.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 422 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 422 insertions(+)
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From 5a82579e304de13e3590cc7ff8c212781a82253e Mon Sep 17 00:00:00 2001
|
||||
From df3d8aede0c04a0ae93e0dc02ba6b471e3791500 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 12 Dec 2023 09:51:05 +0100
|
||||
Subject: [PATCH 17/24] net: phy: marvell10g: Support LEDs tied to a single
|
||||
Subject: [PATCH 17/25] net: phy: marvell10g: Support LEDs tied to a single
|
||||
media side
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
In a combo-port setup, i.e. where both the copper and fiber interface
|
||||
@@ -15,7 +18,7 @@ the offloading of the "netdev" trigger, such that LEDs attached to the
|
||||
RJ45 jack only lights up when a copper link is established, and vice
|
||||
versa for the SFP cage.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 23 ++++++++++++++++++++++-
|
||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
||||
+6
-3
@@ -1,7 +1,10 @@
|
||||
From 3d5cf4c863ab9bb4d72ac8e1f1f9fc48733e43c5 Mon Sep 17 00:00:00 2001
|
||||
From f76443118313f681a62cf34a6f8b38f743832dff Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 27 Mar 2024 10:10:19 +0100
|
||||
Subject: [PATCH 18/24] net: phy: Do not resume PHY when attaching
|
||||
Subject: [PATCH 18/25] net: phy: Do not resume PHY when attaching
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
The PHY should not start negotiating with its link-partner until
|
||||
@@ -16,7 +19,7 @@ probing (e.g. DSA) would end up with a physical link being
|
||||
established, even though the corresponding interface was still
|
||||
administratively down.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/phy/phy_device.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From 70f0a5d1576e4218af1f507c442f4317947ba992 Mon Sep 17 00:00:00 2001
|
||||
From cd73e20a5c51dc26ab6a768a813ab805ad8b0689 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 4 Mar 2024 16:47:28 +0100
|
||||
Subject: [PATCH 19/24] net: bridge: avoid classifying unknown multicast as
|
||||
Subject: [PATCH 19/25] net: bridge: avoid classifying unknown multicast as
|
||||
mrouters_only
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Unknown multicast, MAC/IPv4/IPv6, should always be flooded according to
|
||||
@@ -16,7 +19,7 @@ Because a multicast router should always receive both known and unknown
|
||||
multicast.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
include/uapi/linux/if_bridge.h | 1 +
|
||||
net/bridge/br.c | 5 +++++
|
||||
+6
-2
@@ -1,8 +1,11 @@
|
||||
From f8dc202bdbe82e84d141c955c463aea6a871db37 Mon Sep 17 00:00:00 2001
|
||||
From ed61171f9f5d42000b7315d8af12691bb02dac35 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Tue, 5 Mar 2024 06:44:41 +0100
|
||||
Subject: [PATCH 20/24] net: bridge: Ignore router ports when forwarding L2
|
||||
Subject: [PATCH 20/25] net: bridge: Ignore router ports when forwarding L2
|
||||
multicast
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Multicast router ports are either statically configured or learned from
|
||||
@@ -12,6 +15,7 @@ of unknown multicast or using permanent MDB entries.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
net/bridge/br_private.h | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From abc00ff91772830a68abdcb4135ab5bd674599a8 Mon Sep 17 00:00:00 2001
|
||||
From 73702e1c0331ef8644f326f2dc155a73749cb1c5 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Thu, 4 Apr 2024 16:36:30 +0200
|
||||
Subject: [PATCH 21/24] net: bridge: drop delay for applying strict multicast
|
||||
Subject: [PATCH 21/25] net: bridge: drop delay for applying strict multicast
|
||||
filtering
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
This *local* patch drops the initial delay before applying strict multicast
|
||||
@@ -19,7 +22,7 @@ A proper fix for upstreaming could be to add a knob to disable the delay.
|
||||
[2]: https://lore.kernel.org/netdev/20240127175033.9640-1-linus.luessing@c0d3.blue/
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
net/bridge/br_multicast.c | 42 +++++++--------------------------------
|
||||
net/bridge/br_private.h | 4 +---
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From b2976eada955720555702d3ec70d381acc415adf Mon Sep 17 00:00:00 2001
|
||||
From a48795ef7dbcfd7f1921753ad943144b933020b0 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 16 May 2024 14:51:54 +0200
|
||||
Subject: [PATCH 22/24] net: bridge: Differentiate MDB additions from
|
||||
Subject: [PATCH 22/25] net: bridge: Differentiate MDB additions from
|
||||
modifications
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Before this change, the reception of an IGMPv3 report (and analogously
|
||||
@@ -22,7 +25,7 @@ generated.
|
||||
Therefore, discriminate new groups from changes to existing groups by
|
||||
introducing a RTM_SETMDB events to be used in the latter scenario.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
include/uapi/linux/rtnetlink.h | 2 ++
|
||||
net/bridge/br_mdb.c | 4 ++--
|
||||
+6
-3
@@ -1,8 +1,11 @@
|
||||
From a449d4073cf045a8dbaa4d134f483c7c479a4fcb Mon Sep 17 00:00:00 2001
|
||||
From f0bbef0a94ed2e00475036b25dac8746e061c114 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Fri, 24 Nov 2023 23:29:55 +0100
|
||||
Subject: [PATCH 23/24] nvmem: layouts: onie-tlv: Let device probe even when
|
||||
Subject: [PATCH 23/25] nvmem: layouts: onie-tlv: Let device probe even when
|
||||
TLV is invalid
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Before this change, probing an NVMEM device, expected to contain a
|
||||
@@ -14,7 +17,7 @@ be successfully probed.
|
||||
Therefore, settle for reporting data corruption issues in the log, and
|
||||
simply refrain from registering any cells in those cases.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/nvmem/layouts/onie-tlv.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
+6
-3
@@ -1,7 +1,10 @@
|
||||
From 3166577344620658f8aae9b9af765401fecff87a Mon Sep 17 00:00:00 2001
|
||||
From 7135f0ab4f04b5cea7a0b67df0fe91f925ef19df Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 29 Apr 2024 15:14:51 +0200
|
||||
Subject: [PATCH 24/24] usb: core: adjust log level for unauthorized devices
|
||||
Subject: [PATCH 24/25] usb: core: adjust log level for unauthorized devices
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
The fact that a USB device currently is not authorized is not an error,
|
||||
@@ -9,7 +12,7 @@ so let's adjust the log level so these messages slip below radar for the
|
||||
commonly used 'quiet' log level.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/usb/core/driver.c | 4 ++--
|
||||
drivers/usb/core/generic.c | 2 +-
|
||||
@@ -0,0 +1,44 @@
|
||||
From 733067c41391c3b9f10d0bf62b1097dce9996df1 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Thu, 16 Jan 2025 12:35:12 +0100
|
||||
Subject: [PATCH 25/25] net: dsa: mv88e6xxx: collapse disabled state into
|
||||
blocking
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
This patch changes the behavior of switchcore ports wrt. the port state.
|
||||
Instead of disabling the port, the driver now treats the disabled state
|
||||
the same as the blocking and listening state.
|
||||
|
||||
On this particular type of device the disabled state means no traffic is
|
||||
passed in or out. This interferes with protocols that perform any type
|
||||
of link qualification. E.g., an LACP link aggregate (bond) used as a
|
||||
bridge port with member ports from an mv88e6xxx switch core. Without
|
||||
this patch, the bond is set to 'state disabled'. which is offloaded to
|
||||
each member port, preventing LACPDUs from passing through to qualify the
|
||||
link and become active.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/port.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
index 84900814c456..91e58297594c 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/port.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
@@ -791,8 +791,6 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
|
||||
|
||||
switch (state) {
|
||||
case BR_STATE_DISABLED:
|
||||
- state = MV88E6XXX_PORT_CTL0_STATE_DISABLED;
|
||||
- break;
|
||||
case BR_STATE_BLOCKING:
|
||||
case BR_STATE_LISTENING:
|
||||
state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
From 4be3e500b670f7b98e3dd6696b8e51e83f122c65 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Thu, 25 Jan 2024 21:36:59 +0100
|
||||
Subject: [PATCH 01/35] net: phy: add support for PHY LEDs polarity modes
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Add support for PHY LEDs polarity modes. Some PHY require LED to be set
|
||||
to active low to be turned ON. Adds support for this by declaring
|
||||
active-low property in DT.
|
||||
|
||||
PHY driver needs to declare .led_polarity_set() to configure LED
|
||||
polarity modes. Function will pass the index with the LED index and a
|
||||
bitmap with all the required modes to set.
|
||||
|
||||
Current supported modes are:
|
||||
- active-low with the flag PHY_LED_ACTIVE_LOW. LED is set to active-low
|
||||
to turn it ON.
|
||||
- inactive-high-impedance with the flag PHY_LED_INACTIVE_HIGH_IMPEDANCE.
|
||||
LED is set to high impedance to turn it OFF.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Link: https://lore.kernel.org/r/20240125203702.4552-4-ansuelsmth@gmail.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/phy_device.c | 16 ++++++++++++++++
|
||||
include/linux/phy.h | 22 ++++++++++++++++++++++
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
|
||||
index 2e4bff6055e2..1b144e23911c 100644
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -3095,6 +3095,7 @@ static int of_phy_led(struct phy_device *phydev,
|
||||
struct device *dev = &phydev->mdio.dev;
|
||||
struct led_init_data init_data = {};
|
||||
struct led_classdev *cdev;
|
||||
+ unsigned long modes = 0;
|
||||
struct phy_led *phyled;
|
||||
u32 index;
|
||||
int err;
|
||||
@@ -3112,6 +3113,21 @@ static int of_phy_led(struct phy_device *phydev,
|
||||
if (index > U8_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
+ if (of_property_read_bool(led, "active-low"))
|
||||
+ set_bit(PHY_LED_ACTIVE_LOW, &modes);
|
||||
+ if (of_property_read_bool(led, "inactive-high-impedance"))
|
||||
+ set_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes);
|
||||
+
|
||||
+ if (modes) {
|
||||
+ /* Return error if asked to set polarity modes but not supported */
|
||||
+ if (!phydev->drv->led_polarity_set)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ err = phydev->drv->led_polarity_set(phydev, index, modes);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
phyled->index = index;
|
||||
if (phydev->drv->led_brightness_set)
|
||||
cdev->brightness_set_blocking = phy_led_set_brightness;
|
||||
diff --git a/include/linux/phy.h b/include/linux/phy.h
|
||||
index 5aa30ee99810..6783d175f518 100644
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -849,6 +849,15 @@ struct phy_plca_status {
|
||||
bool pst;
|
||||
};
|
||||
|
||||
+/* Modes for PHY LED configuration */
|
||||
+enum phy_led_modes {
|
||||
+ PHY_LED_ACTIVE_LOW = 0,
|
||||
+ PHY_LED_INACTIVE_HIGH_IMPEDANCE = 1,
|
||||
+
|
||||
+ /* keep it last */
|
||||
+ __PHY_LED_MODES_NUM,
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct phy_led: An LED driven by the PHY
|
||||
*
|
||||
@@ -1142,6 +1151,19 @@ struct phy_driver {
|
||||
int (*led_hw_control_get)(struct phy_device *dev, u8 index,
|
||||
unsigned long *rules);
|
||||
|
||||
+ /**
|
||||
+ * @led_polarity_set: Set the LED polarity modes
|
||||
+ * @dev: PHY device which has the LED
|
||||
+ * @index: Which LED of the PHY device
|
||||
+ * @modes: bitmap of LED polarity modes
|
||||
+ *
|
||||
+ * Configure LED with all the required polarity modes in @modes
|
||||
+ * to make it correctly turn ON or OFF.
|
||||
+ *
|
||||
+ * Returns 0, or an error code.
|
||||
+ */
|
||||
+ int (*led_polarity_set)(struct phy_device *dev, int index,
|
||||
+ unsigned long modes);
|
||||
};
|
||||
#define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
|
||||
struct phy_driver, mdiodrv)
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
From 4833b140cd11a57dd9f59754cdacfd71bc564c8f Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Mon, 4 Dec 2023 11:08:11 +0100
|
||||
Subject: [PATCH 02/35] net: mvmdio: Support setting the MDC frequency on XSMI
|
||||
controllers
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Support the standard "clock-frequency" attribute to set the generated
|
||||
MDC frequency. If not specified, the driver will leave the divisor
|
||||
untouched.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Tested-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Link: https://lore.kernel.org/r/20231204100811.2708884-4-tobias@waldekranz.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/marvell/mvmdio.c | 44 +++++++++++++++++++++++++++
|
||||
1 file changed, 44 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
|
||||
index 2ef613a237d8..11f564e88a7d 100644
|
||||
--- a/drivers/net/ethernet/marvell/mvmdio.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvmdio.c
|
||||
@@ -53,6 +53,13 @@
|
||||
#define MVMDIO_XSMI_BUSY BIT(30)
|
||||
#define MVMDIO_XSMI_ADDR_REG 0x8
|
||||
|
||||
+#define MVMDIO_XSMI_CFG_REG 0xc
|
||||
+#define MVMDIO_XSMI_CLKDIV_MASK 0x3
|
||||
+#define MVMDIO_XSMI_CLKDIV_256 0x0
|
||||
+#define MVMDIO_XSMI_CLKDIV_64 0x1
|
||||
+#define MVMDIO_XSMI_CLKDIV_32 0x2
|
||||
+#define MVMDIO_XSMI_CLKDIV_8 0x3
|
||||
+
|
||||
/*
|
||||
* SMI Timeout measurements:
|
||||
* - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt)
|
||||
@@ -225,6 +232,40 @@ static int orion_mdio_xsmi_write_c45(struct mii_bus *bus, int mii_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void orion_mdio_xsmi_set_mdc_freq(struct mii_bus *bus)
|
||||
+{
|
||||
+ struct orion_mdio_dev *dev = bus->priv;
|
||||
+ struct clk *mg_core;
|
||||
+ u32 div, freq, cfg;
|
||||
+
|
||||
+ if (device_property_read_u32(bus->parent, "clock-frequency", &freq))
|
||||
+ return;
|
||||
+
|
||||
+ mg_core = of_clk_get_by_name(bus->parent->of_node, "mg_core_clk");
|
||||
+ if (IS_ERR(mg_core)) {
|
||||
+ dev_err(bus->parent,
|
||||
+ "MG core clock unknown, not changing MDC frequency");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ div = clk_get_rate(mg_core) / (freq + 1) + 1;
|
||||
+ clk_put(mg_core);
|
||||
+
|
||||
+ if (div <= 8)
|
||||
+ div = MVMDIO_XSMI_CLKDIV_8;
|
||||
+ else if (div <= 32)
|
||||
+ div = MVMDIO_XSMI_CLKDIV_32;
|
||||
+ else if (div <= 64)
|
||||
+ div = MVMDIO_XSMI_CLKDIV_64;
|
||||
+ else
|
||||
+ div = MVMDIO_XSMI_CLKDIV_256;
|
||||
+
|
||||
+ cfg = readl(dev->regs + MVMDIO_XSMI_CFG_REG);
|
||||
+ cfg &= ~MVMDIO_XSMI_CLKDIV_MASK;
|
||||
+ cfg |= div;
|
||||
+ writel(cfg, dev->regs + MVMDIO_XSMI_CFG_REG);
|
||||
+}
|
||||
+
|
||||
static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct orion_mdio_dev *dev = dev_id;
|
||||
@@ -303,6 +344,9 @@ static int orion_mdio_probe(struct platform_device *pdev)
|
||||
dev_warn(&pdev->dev,
|
||||
"unsupported number of clocks, limiting to the first "
|
||||
__stringify(ARRAY_SIZE(dev->clk)) "\n");
|
||||
+
|
||||
+ if (type == BUS_TYPE_XSMI)
|
||||
+ orion_mdio_xsmi_set_mdc_freq(bus);
|
||||
} else {
|
||||
dev->clk[0] = clk_get(&pdev->dev, NULL);
|
||||
if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) {
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,477 +0,0 @@
|
||||
From 50a2973e8a520a82e9f9ec15a1f69e059ce7a334 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:23 +0100
|
||||
Subject: [PATCH 03/35] net: dsa: mv88e6xxx: Create API to read a single stat
|
||||
counter
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
This change contains no functional change. We simply push the hardware
|
||||
specific stats logic to a function reading a single counter, rather
|
||||
than the whole set.
|
||||
|
||||
This is a preparatory change for the upcoming standard ethtool
|
||||
statistics support (i.e. "eth-mac", "eth-ctrl" etc.).
|
||||
|
||||
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 162 ++++++++++++++++++-------------
|
||||
drivers/net/dsa/mv88e6xxx/chip.h | 27 +++---
|
||||
2 files changed, 106 insertions(+), 83 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 3877744193e2..14a9bba5ed0b 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -1072,7 +1072,7 @@ static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
|
||||
};
|
||||
|
||||
static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
|
||||
- struct mv88e6xxx_hw_stat *s,
|
||||
+ const struct mv88e6xxx_hw_stat *s,
|
||||
int port, u16 bank1_select,
|
||||
u16 histogram)
|
||||
{
|
||||
@@ -1255,59 +1255,82 @@ static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset)
|
||||
return count;
|
||||
}
|
||||
|
||||
-static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
- uint64_t *data, int types,
|
||||
- u16 bank1_select, u16 histogram)
|
||||
+static size_t mv88e6095_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
+ const struct mv88e6xxx_hw_stat *stat,
|
||||
+ uint64_t *data)
|
||||
{
|
||||
- struct mv88e6xxx_hw_stat *stat;
|
||||
- int i, j;
|
||||
+ if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_PORT)))
|
||||
+ return 0;
|
||||
|
||||
- for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
|
||||
- stat = &mv88e6xxx_hw_stats[i];
|
||||
- if (stat->type & types) {
|
||||
- mv88e6xxx_reg_lock(chip);
|
||||
- data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
|
||||
- bank1_select,
|
||||
- histogram);
|
||||
- mv88e6xxx_reg_unlock(chip);
|
||||
+ *data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
|
||||
+ MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
|
||||
+ return 1;
|
||||
+}
|
||||
|
||||
- j++;
|
||||
- }
|
||||
- }
|
||||
- return j;
|
||||
+static size_t mv88e6250_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
+ const struct mv88e6xxx_hw_stat *stat,
|
||||
+ uint64_t *data)
|
||||
+{
|
||||
+ if (!(stat->type & STATS_TYPE_BANK0))
|
||||
+ return 0;
|
||||
+
|
||||
+ *data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
|
||||
+ MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
-static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
- uint64_t *data)
|
||||
+static size_t mv88e6320_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
+ const struct mv88e6xxx_hw_stat *stat,
|
||||
+ uint64_t *data)
|
||||
{
|
||||
- return mv88e6xxx_stats_get_stats(chip, port, data,
|
||||
- STATS_TYPE_BANK0 | STATS_TYPE_PORT,
|
||||
- 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
|
||||
+ if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1)))
|
||||
+ return 0;
|
||||
+
|
||||
+ *data = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
|
||||
+ MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
|
||||
+ MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
-static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
- uint64_t *data)
|
||||
+static size_t mv88e6390_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
+ const struct mv88e6xxx_hw_stat *stat,
|
||||
+ uint64_t *data)
|
||||
{
|
||||
- return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0,
|
||||
- 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
|
||||
+ if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1)))
|
||||
+ return 0;
|
||||
+
|
||||
+ *data = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
|
||||
+ MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
|
||||
+ 0);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
-static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
- uint64_t *data)
|
||||
+static size_t mv88e6xxx_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
+ const struct mv88e6xxx_hw_stat *stat,
|
||||
+ uint64_t *data)
|
||||
{
|
||||
- return mv88e6xxx_stats_get_stats(chip, port, data,
|
||||
- STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
- MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
|
||||
- MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (chip->info->ops->stats_get_stat) {
|
||||
+ mv88e6xxx_reg_lock(chip);
|
||||
+ ret = chip->info->ops->stats_get_stat(chip, port, stat, data);
|
||||
+ mv88e6xxx_reg_unlock(chip);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
-static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
- uint64_t *data)
|
||||
+static size_t mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
+ uint64_t *data)
|
||||
{
|
||||
- return mv88e6xxx_stats_get_stats(chip, port, data,
|
||||
- STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
|
||||
- MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
|
||||
- 0);
|
||||
+ struct mv88e6xxx_hw_stat *stat;
|
||||
+ size_t i, j;
|
||||
+
|
||||
+ for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
|
||||
+ stat = &mv88e6xxx_hw_stats[i];
|
||||
+ j += mv88e6xxx_stats_get_stat(chip, port, stat, &data[j]);
|
||||
+ }
|
||||
+ return j;
|
||||
}
|
||||
|
||||
static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
@@ -1323,10 +1346,9 @@ static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
uint64_t *data)
|
||||
{
|
||||
- int count = 0;
|
||||
+ size_t count;
|
||||
|
||||
- if (chip->info->ops->stats_get_stats)
|
||||
- count = chip->info->ops->stats_get_stats(chip, port, data);
|
||||
+ count = mv88e6xxx_stats_get_stats(chip, port, data);
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
if (chip->info->ops->serdes_get_stats) {
|
||||
@@ -4058,7 +4080,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4096,7 +4118,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
|
||||
.ppu_enable = mv88e6185_g1_ppu_enable,
|
||||
.ppu_disable = mv88e6185_g1_ppu_disable,
|
||||
@@ -4137,7 +4159,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4179,7 +4201,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4222,7 +4244,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4271,7 +4293,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
|
||||
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6390_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6390_stats_get_stat,
|
||||
.set_cpu_port = mv88e6390_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6390_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -4328,7 +4350,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4366,7 +4388,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4414,7 +4436,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4463,7 +4485,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4516,7 +4538,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4565,7 +4587,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4612,7 +4634,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4661,7 +4683,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
|
||||
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6390_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6390_stats_get_stat,
|
||||
.set_cpu_port = mv88e6390_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6390_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -4721,7 +4743,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
|
||||
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6390_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6390_stats_get_stat,
|
||||
.set_cpu_port = mv88e6390_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6390_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -4779,7 +4801,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
|
||||
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6390_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6390_stats_get_stat,
|
||||
.set_cpu_port = mv88e6390_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6390_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -4840,7 +4862,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -4895,7 +4917,7 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6250_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6250_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6250_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6250_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6250_watchdog_ops,
|
||||
@@ -4944,7 +4966,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
|
||||
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6390_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6390_stats_get_stat,
|
||||
.set_cpu_port = mv88e6390_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6390_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -5005,7 +5027,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6320_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6320_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -5054,7 +5076,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6320_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6320_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -5105,7 +5127,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
|
||||
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6390_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6390_stats_get_stat,
|
||||
.set_cpu_port = mv88e6390_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6390_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -5165,7 +5187,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -5211,7 +5233,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -5262,7 +5284,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
|
||||
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6095_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6095_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6095_stats_get_stat,
|
||||
.set_cpu_port = mv88e6095_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6095_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6097_watchdog_ops,
|
||||
@@ -5326,7 +5348,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
|
||||
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6390_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6390_stats_get_stat,
|
||||
.set_cpu_port = mv88e6390_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6390_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -5390,7 +5412,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
|
||||
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6390_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6390_stats_get_stat,
|
||||
.set_cpu_port = mv88e6390_g1_set_cpu_port,
|
||||
.set_egress_port = mv88e6390_g1_set_egress_port,
|
||||
.watchdog_ops = &mv88e6390_watchdog_ops,
|
||||
@@ -5454,7 +5476,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
|
||||
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
|
||||
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
|
||||
.stats_get_strings = mv88e6320_stats_get_strings,
|
||||
- .stats_get_stats = mv88e6390_stats_get_stats,
|
||||
+ .stats_get_stat = mv88e6390_stats_get_stat,
|
||||
/* .set_cpu_port is missing because this family does not support a global
|
||||
* CPU port, only per port CPU port which is set via
|
||||
* .port_set_upstream_port method.
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
|
||||
index f48a3c0ac7f9..c34caf9815c5 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
|
||||
@@ -318,6 +318,17 @@ struct mv88e6xxx_mst {
|
||||
struct mv88e6xxx_stu_entry stu;
|
||||
};
|
||||
|
||||
+#define STATS_TYPE_PORT BIT(0)
|
||||
+#define STATS_TYPE_BANK0 BIT(1)
|
||||
+#define STATS_TYPE_BANK1 BIT(2)
|
||||
+
|
||||
+struct mv88e6xxx_hw_stat {
|
||||
+ char string[ETH_GSTRING_LEN];
|
||||
+ size_t size;
|
||||
+ int reg;
|
||||
+ int type;
|
||||
+};
|
||||
+
|
||||
struct mv88e6xxx_chip {
|
||||
const struct mv88e6xxx_info *info;
|
||||
|
||||
@@ -580,8 +591,9 @@ struct mv88e6xxx_ops {
|
||||
/* Return the number of strings describing statistics */
|
||||
int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
|
||||
int (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
|
||||
- int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
|
||||
- uint64_t *data);
|
||||
+ size_t (*stats_get_stat)(struct mv88e6xxx_chip *chip, int port,
|
||||
+ const struct mv88e6xxx_hw_stat *stat,
|
||||
+ uint64_t *data);
|
||||
int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
|
||||
int (*set_egress_port)(struct mv88e6xxx_chip *chip,
|
||||
enum mv88e6xxx_egress_direction direction,
|
||||
@@ -733,17 +745,6 @@ struct mv88e6xxx_pcs_ops {
|
||||
|
||||
};
|
||||
|
||||
-#define STATS_TYPE_PORT BIT(0)
|
||||
-#define STATS_TYPE_BANK0 BIT(1)
|
||||
-#define STATS_TYPE_BANK1 BIT(2)
|
||||
-
|
||||
-struct mv88e6xxx_hw_stat {
|
||||
- char string[ETH_GSTRING_LEN];
|
||||
- size_t size;
|
||||
- int reg;
|
||||
- int type;
|
||||
-};
|
||||
-
|
||||
static inline bool mv88e6xxx_has_stu(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
return chip->info->max_sid > 0 &&
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
From 5916503e23e7f85796c1f927747e66b9535bac53 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:25 +0100
|
||||
Subject: [PATCH 04/35] net: dsa: mv88e6xxx: Give each hw stat an ID
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
With the upcoming standard counter group support, we are no longer
|
||||
reading out the whole set of counters, but rather mapping a subset to
|
||||
the requested group.
|
||||
|
||||
Therefore, create an enum with an ID for each stat, such that
|
||||
mv88e6xxx_hw_stats[] can be subscripted with a human-readable ID
|
||||
corresponding to the counter's name.
|
||||
|
||||
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 138 +++++++++++++++++--------------
|
||||
1 file changed, 75 insertions(+), 63 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 14a9bba5ed0b..f6efd0bad710 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -1009,66 +1009,78 @@ static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
|
||||
return chip->info->ops->stats_snapshot(chip, port);
|
||||
}
|
||||
|
||||
-static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
|
||||
- { "in_good_octets", 8, 0x00, STATS_TYPE_BANK0, },
|
||||
- { "in_bad_octets", 4, 0x02, STATS_TYPE_BANK0, },
|
||||
- { "in_unicast", 4, 0x04, STATS_TYPE_BANK0, },
|
||||
- { "in_broadcasts", 4, 0x06, STATS_TYPE_BANK0, },
|
||||
- { "in_multicasts", 4, 0x07, STATS_TYPE_BANK0, },
|
||||
- { "in_pause", 4, 0x16, STATS_TYPE_BANK0, },
|
||||
- { "in_undersize", 4, 0x18, STATS_TYPE_BANK0, },
|
||||
- { "in_fragments", 4, 0x19, STATS_TYPE_BANK0, },
|
||||
- { "in_oversize", 4, 0x1a, STATS_TYPE_BANK0, },
|
||||
- { "in_jabber", 4, 0x1b, STATS_TYPE_BANK0, },
|
||||
- { "in_rx_error", 4, 0x1c, STATS_TYPE_BANK0, },
|
||||
- { "in_fcs_error", 4, 0x1d, STATS_TYPE_BANK0, },
|
||||
- { "out_octets", 8, 0x0e, STATS_TYPE_BANK0, },
|
||||
- { "out_unicast", 4, 0x10, STATS_TYPE_BANK0, },
|
||||
- { "out_broadcasts", 4, 0x13, STATS_TYPE_BANK0, },
|
||||
- { "out_multicasts", 4, 0x12, STATS_TYPE_BANK0, },
|
||||
- { "out_pause", 4, 0x15, STATS_TYPE_BANK0, },
|
||||
- { "excessive", 4, 0x11, STATS_TYPE_BANK0, },
|
||||
- { "collisions", 4, 0x1e, STATS_TYPE_BANK0, },
|
||||
- { "deferred", 4, 0x05, STATS_TYPE_BANK0, },
|
||||
- { "single", 4, 0x14, STATS_TYPE_BANK0, },
|
||||
- { "multiple", 4, 0x17, STATS_TYPE_BANK0, },
|
||||
- { "out_fcs_error", 4, 0x03, STATS_TYPE_BANK0, },
|
||||
- { "late", 4, 0x1f, STATS_TYPE_BANK0, },
|
||||
- { "hist_64bytes", 4, 0x08, STATS_TYPE_BANK0, },
|
||||
- { "hist_65_127bytes", 4, 0x09, STATS_TYPE_BANK0, },
|
||||
- { "hist_128_255bytes", 4, 0x0a, STATS_TYPE_BANK0, },
|
||||
- { "hist_256_511bytes", 4, 0x0b, STATS_TYPE_BANK0, },
|
||||
- { "hist_512_1023bytes", 4, 0x0c, STATS_TYPE_BANK0, },
|
||||
- { "hist_1024_max_bytes", 4, 0x0d, STATS_TYPE_BANK0, },
|
||||
- { "sw_in_discards", 4, 0x10, STATS_TYPE_PORT, },
|
||||
- { "sw_in_filtered", 2, 0x12, STATS_TYPE_PORT, },
|
||||
- { "sw_out_filtered", 2, 0x13, STATS_TYPE_PORT, },
|
||||
- { "in_discards", 4, 0x00, STATS_TYPE_BANK1, },
|
||||
- { "in_filtered", 4, 0x01, STATS_TYPE_BANK1, },
|
||||
- { "in_accepted", 4, 0x02, STATS_TYPE_BANK1, },
|
||||
- { "in_bad_accepted", 4, 0x03, STATS_TYPE_BANK1, },
|
||||
- { "in_good_avb_class_a", 4, 0x04, STATS_TYPE_BANK1, },
|
||||
- { "in_good_avb_class_b", 4, 0x05, STATS_TYPE_BANK1, },
|
||||
- { "in_bad_avb_class_a", 4, 0x06, STATS_TYPE_BANK1, },
|
||||
- { "in_bad_avb_class_b", 4, 0x07, STATS_TYPE_BANK1, },
|
||||
- { "tcam_counter_0", 4, 0x08, STATS_TYPE_BANK1, },
|
||||
- { "tcam_counter_1", 4, 0x09, STATS_TYPE_BANK1, },
|
||||
- { "tcam_counter_2", 4, 0x0a, STATS_TYPE_BANK1, },
|
||||
- { "tcam_counter_3", 4, 0x0b, STATS_TYPE_BANK1, },
|
||||
- { "in_da_unknown", 4, 0x0e, STATS_TYPE_BANK1, },
|
||||
- { "in_management", 4, 0x0f, STATS_TYPE_BANK1, },
|
||||
- { "out_queue_0", 4, 0x10, STATS_TYPE_BANK1, },
|
||||
- { "out_queue_1", 4, 0x11, STATS_TYPE_BANK1, },
|
||||
- { "out_queue_2", 4, 0x12, STATS_TYPE_BANK1, },
|
||||
- { "out_queue_3", 4, 0x13, STATS_TYPE_BANK1, },
|
||||
- { "out_queue_4", 4, 0x14, STATS_TYPE_BANK1, },
|
||||
- { "out_queue_5", 4, 0x15, STATS_TYPE_BANK1, },
|
||||
- { "out_queue_6", 4, 0x16, STATS_TYPE_BANK1, },
|
||||
- { "out_queue_7", 4, 0x17, STATS_TYPE_BANK1, },
|
||||
- { "out_cut_through", 4, 0x18, STATS_TYPE_BANK1, },
|
||||
- { "out_octets_a", 4, 0x1a, STATS_TYPE_BANK1, },
|
||||
- { "out_octets_b", 4, 0x1b, STATS_TYPE_BANK1, },
|
||||
- { "out_management", 4, 0x1f, STATS_TYPE_BANK1, },
|
||||
+#define MV88E6XXX_HW_STAT_MAPPER(_fn) \
|
||||
+ _fn(in_good_octets, 8, 0x00, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_bad_octets, 4, 0x02, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_unicast, 4, 0x04, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_broadcasts, 4, 0x06, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_multicasts, 4, 0x07, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_pause, 4, 0x16, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_undersize, 4, 0x18, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_fragments, 4, 0x19, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_oversize, 4, 0x1a, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_jabber, 4, 0x1b, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_rx_error, 4, 0x1c, STATS_TYPE_BANK0), \
|
||||
+ _fn(in_fcs_error, 4, 0x1d, STATS_TYPE_BANK0), \
|
||||
+ _fn(out_octets, 8, 0x0e, STATS_TYPE_BANK0), \
|
||||
+ _fn(out_unicast, 4, 0x10, STATS_TYPE_BANK0), \
|
||||
+ _fn(out_broadcasts, 4, 0x13, STATS_TYPE_BANK0), \
|
||||
+ _fn(out_multicasts, 4, 0x12, STATS_TYPE_BANK0), \
|
||||
+ _fn(out_pause, 4, 0x15, STATS_TYPE_BANK0), \
|
||||
+ _fn(excessive, 4, 0x11, STATS_TYPE_BANK0), \
|
||||
+ _fn(collisions, 4, 0x1e, STATS_TYPE_BANK0), \
|
||||
+ _fn(deferred, 4, 0x05, STATS_TYPE_BANK0), \
|
||||
+ _fn(single, 4, 0x14, STATS_TYPE_BANK0), \
|
||||
+ _fn(multiple, 4, 0x17, STATS_TYPE_BANK0), \
|
||||
+ _fn(out_fcs_error, 4, 0x03, STATS_TYPE_BANK0), \
|
||||
+ _fn(late, 4, 0x1f, STATS_TYPE_BANK0), \
|
||||
+ _fn(hist_64bytes, 4, 0x08, STATS_TYPE_BANK0), \
|
||||
+ _fn(hist_65_127bytes, 4, 0x09, STATS_TYPE_BANK0), \
|
||||
+ _fn(hist_128_255bytes, 4, 0x0a, STATS_TYPE_BANK0), \
|
||||
+ _fn(hist_256_511bytes, 4, 0x0b, STATS_TYPE_BANK0), \
|
||||
+ _fn(hist_512_1023bytes, 4, 0x0c, STATS_TYPE_BANK0), \
|
||||
+ _fn(hist_1024_max_bytes, 4, 0x0d, STATS_TYPE_BANK0), \
|
||||
+ _fn(sw_in_discards, 4, 0x10, STATS_TYPE_PORT), \
|
||||
+ _fn(sw_in_filtered, 2, 0x12, STATS_TYPE_PORT), \
|
||||
+ _fn(sw_out_filtered, 2, 0x13, STATS_TYPE_PORT), \
|
||||
+ _fn(in_discards, 4, 0x00, STATS_TYPE_BANK1), \
|
||||
+ _fn(in_filtered, 4, 0x01, STATS_TYPE_BANK1), \
|
||||
+ _fn(in_accepted, 4, 0x02, STATS_TYPE_BANK1), \
|
||||
+ _fn(in_bad_accepted, 4, 0x03, STATS_TYPE_BANK1), \
|
||||
+ _fn(in_good_avb_class_a, 4, 0x04, STATS_TYPE_BANK1), \
|
||||
+ _fn(in_good_avb_class_b, 4, 0x05, STATS_TYPE_BANK1), \
|
||||
+ _fn(in_bad_avb_class_a, 4, 0x06, STATS_TYPE_BANK1), \
|
||||
+ _fn(in_bad_avb_class_b, 4, 0x07, STATS_TYPE_BANK1), \
|
||||
+ _fn(tcam_counter_0, 4, 0x08, STATS_TYPE_BANK1), \
|
||||
+ _fn(tcam_counter_1, 4, 0x09, STATS_TYPE_BANK1), \
|
||||
+ _fn(tcam_counter_2, 4, 0x0a, STATS_TYPE_BANK1), \
|
||||
+ _fn(tcam_counter_3, 4, 0x0b, STATS_TYPE_BANK1), \
|
||||
+ _fn(in_da_unknown, 4, 0x0e, STATS_TYPE_BANK1), \
|
||||
+ _fn(in_management, 4, 0x0f, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_queue_0, 4, 0x10, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_queue_1, 4, 0x11, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_queue_2, 4, 0x12, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_queue_3, 4, 0x13, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_queue_4, 4, 0x14, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_queue_5, 4, 0x15, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_queue_6, 4, 0x16, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_queue_7, 4, 0x17, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_cut_through, 4, 0x18, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_octets_a, 4, 0x1a, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_octets_b, 4, 0x1b, STATS_TYPE_BANK1), \
|
||||
+ _fn(out_management, 4, 0x1f, STATS_TYPE_BANK1), \
|
||||
+ /* */
|
||||
+
|
||||
+#define MV88E6XXX_HW_STAT_ENTRY(_string, _size, _reg, _type) \
|
||||
+ { #_string, _size, _reg, _type }
|
||||
+static const struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
|
||||
+ MV88E6XXX_HW_STAT_MAPPER(MV88E6XXX_HW_STAT_ENTRY)
|
||||
+};
|
||||
+
|
||||
+#define MV88E6XXX_HW_STAT_ENUM(_string, _size, _reg, _type) \
|
||||
+ MV88E6XXX_HW_STAT_ID_ ## _string
|
||||
+enum mv88e6xxx_hw_stat_id {
|
||||
+ MV88E6XXX_HW_STAT_MAPPER(MV88E6XXX_HW_STAT_ENUM)
|
||||
};
|
||||
|
||||
static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
|
||||
@@ -1115,7 +1127,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
|
||||
static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
|
||||
uint8_t *data, int types)
|
||||
{
|
||||
- struct mv88e6xxx_hw_stat *stat;
|
||||
+ const struct mv88e6xxx_hw_stat *stat;
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
|
||||
@@ -1196,7 +1208,7 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
|
||||
static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
|
||||
int types)
|
||||
{
|
||||
- struct mv88e6xxx_hw_stat *stat;
|
||||
+ const struct mv88e6xxx_hw_stat *stat;
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
|
||||
@@ -1323,7 +1335,7 @@ static size_t mv88e6xxx_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
static size_t mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
|
||||
uint64_t *data)
|
||||
{
|
||||
- struct mv88e6xxx_hw_stat *stat;
|
||||
+ const struct mv88e6xxx_hw_stat *stat;
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
From 32dda6562734ec8ee667bc546f3ef56794d5bf82 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:26 +0100
|
||||
Subject: [PATCH 05/35] net: dsa: mv88e6xxx: Add "eth-mac" counter group
|
||||
support
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Report the applicable subset of an mv88e6xxx port's counters using
|
||||
ethtool's standardized "eth-mac" counter group.
|
||||
|
||||
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 39 ++++++++++++++++++++++++++++++++
|
||||
1 file changed, 39 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index f6efd0bad710..695688defda5 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -1390,6 +1390,44 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
|
||||
|
||||
}
|
||||
|
||||
+static void mv88e6xxx_get_eth_mac_stats(struct dsa_switch *ds, int port,
|
||||
+ struct ethtool_eth_mac_stats *mac_stats)
|
||||
+{
|
||||
+ struct mv88e6xxx_chip *chip = ds->priv;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = mv88e6xxx_stats_snapshot(chip, port);
|
||||
+ if (ret < 0)
|
||||
+ return;
|
||||
+
|
||||
+#define MV88E6XXX_ETH_MAC_STAT_MAP(_id, _member) \
|
||||
+ mv88e6xxx_stats_get_stat(chip, port, \
|
||||
+ &mv88e6xxx_hw_stats[MV88E6XXX_HW_STAT_ID_ ## _id], \
|
||||
+ &mac_stats->stats._member)
|
||||
+
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(out_unicast, FramesTransmittedOK);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(single, SingleCollisionFrames);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(multiple, MultipleCollisionFrames);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(in_unicast, FramesReceivedOK);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(in_fcs_error, FrameCheckSequenceErrors);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(out_octets, OctetsTransmittedOK);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(deferred, FramesWithDeferredXmissions);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(late, LateCollisions);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(in_good_octets, OctetsReceivedOK);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(out_multicasts, MulticastFramesXmittedOK);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(out_broadcasts, BroadcastFramesXmittedOK);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(excessive, FramesWithExcessiveDeferral);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(in_multicasts, MulticastFramesReceivedOK);
|
||||
+ MV88E6XXX_ETH_MAC_STAT_MAP(in_broadcasts, BroadcastFramesReceivedOK);
|
||||
+
|
||||
+#undef MV88E6XXX_ETH_MAC_STAT_MAP
|
||||
+
|
||||
+ mac_stats->stats.FramesTransmittedOK += mac_stats->stats.MulticastFramesXmittedOK;
|
||||
+ mac_stats->stats.FramesTransmittedOK += mac_stats->stats.BroadcastFramesXmittedOK;
|
||||
+ mac_stats->stats.FramesReceivedOK += mac_stats->stats.MulticastFramesReceivedOK;
|
||||
+ mac_stats->stats.FramesReceivedOK += mac_stats->stats.BroadcastFramesReceivedOK;
|
||||
+}
|
||||
+
|
||||
static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
@@ -6958,6 +6996,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.phylink_mac_link_up = mv88e6xxx_mac_link_up,
|
||||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
+ .get_eth_mac_stats = mv88e6xxx_get_eth_mac_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
.port_max_mtu = mv88e6xxx_get_max_mtu,
|
||||
.port_change_mtu = mv88e6xxx_change_mtu,
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
From 36adbdd466ec550cab8b2ae54177f674c02cf631 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:27 +0100
|
||||
Subject: [PATCH 06/35] net: dsa: mv88e6xxx: Limit histogram counters to
|
||||
ingress traffic
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Chips in this family only have one set of histogram counters, which
|
||||
can be used to count ingressing and/or egressing traffic. mv88e6xxx
|
||||
has, up until this point, kept the hardware default of counting both
|
||||
directions.
|
||||
|
||||
In the mean time, standard counter group support has been added to
|
||||
ethtool. Via that interface, drivers may report ingress-only and
|
||||
egress-only histograms separately - but not combined.
|
||||
|
||||
In order for mv88e6xxx to maximize amount of diagnostic information
|
||||
that can be exported via standard interfaces, we opt to limit the
|
||||
histogram counters to ingress traffic only. Which will allow us to
|
||||
export them via the standard "rmon" group in an upcoming commit.
|
||||
|
||||
The reason for choosing ingress-only over egress-only, is to be
|
||||
compatible with RFC2819 (RMON MIB).
|
||||
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 6 +++---
|
||||
drivers/net/dsa/mv88e6xxx/global1.c | 7 +++----
|
||||
2 files changed, 6 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 695688defda5..08ff05000515 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -1275,7 +1275,7 @@ static size_t mv88e6095_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
return 0;
|
||||
|
||||
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
|
||||
- MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
|
||||
+ MV88E6XXX_G1_STATS_OP_HIST_RX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1287,7 +1287,7 @@ static size_t mv88e6250_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
return 0;
|
||||
|
||||
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
|
||||
- MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
|
||||
+ MV88E6XXX_G1_STATS_OP_HIST_RX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1300,7 +1300,7 @@ static size_t mv88e6320_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
|
||||
|
||||
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
|
||||
MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
|
||||
- MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
|
||||
+ MV88E6XXX_G1_STATS_OP_HIST_RX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c
|
||||
index 7ef0f4426ad7..9820cd596757 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/global1.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/global1.c
|
||||
@@ -551,8 +551,7 @@ int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip)
|
||||
int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_HIST_MODE_MASK,
|
||||
- MV88E6390_G1_CTL2_HIST_MODE_RX |
|
||||
- MV88E6390_G1_CTL2_HIST_MODE_TX);
|
||||
+ MV88E6390_G1_CTL2_HIST_MODE_RX);
|
||||
}
|
||||
|
||||
int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index)
|
||||
@@ -580,7 +579,7 @@ int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- val |= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;
|
||||
+ val |= MV88E6XXX_G1_STATS_OP_HIST_RX;
|
||||
|
||||
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
|
||||
|
||||
@@ -595,7 +594,7 @@ int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
|
||||
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
|
||||
MV88E6XXX_G1_STATS_OP_BUSY |
|
||||
MV88E6XXX_G1_STATS_OP_CAPTURE_PORT |
|
||||
- MV88E6XXX_G1_STATS_OP_HIST_RX_TX | port);
|
||||
+ MV88E6XXX_G1_STATS_OP_HIST_RX | port);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
From abfa532c1149525b128b8c76d80965f55e208240 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 14 Dec 2023 14:50:28 +0100
|
||||
Subject: [PATCH 07/35] net: dsa: mv88e6xxx: Add "rmon" counter group support
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Report the applicable subset of an mv88e6xxx port's counters using
|
||||
ethtool's standardized "rmon" counter group.
|
||||
|
||||
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 42 ++++++++++++++++++++++++++++++++
|
||||
1 file changed, 42 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 08ff05000515..1fd4fc9ace61 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -1428,6 +1428,47 @@ static void mv88e6xxx_get_eth_mac_stats(struct dsa_switch *ds, int port,
|
||||
mac_stats->stats.FramesReceivedOK += mac_stats->stats.BroadcastFramesReceivedOK;
|
||||
}
|
||||
|
||||
+static void mv88e6xxx_get_rmon_stats(struct dsa_switch *ds, int port,
|
||||
+ struct ethtool_rmon_stats *rmon_stats,
|
||||
+ const struct ethtool_rmon_hist_range **ranges)
|
||||
+{
|
||||
+ static const struct ethtool_rmon_hist_range rmon_ranges[] = {
|
||||
+ { 64, 64 },
|
||||
+ { 65, 127 },
|
||||
+ { 128, 255 },
|
||||
+ { 256, 511 },
|
||||
+ { 512, 1023 },
|
||||
+ { 1024, 65535 },
|
||||
+ {}
|
||||
+ };
|
||||
+ struct mv88e6xxx_chip *chip = ds->priv;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = mv88e6xxx_stats_snapshot(chip, port);
|
||||
+ if (ret < 0)
|
||||
+ return;
|
||||
+
|
||||
+#define MV88E6XXX_RMON_STAT_MAP(_id, _member) \
|
||||
+ mv88e6xxx_stats_get_stat(chip, port, \
|
||||
+ &mv88e6xxx_hw_stats[MV88E6XXX_HW_STAT_ID_ ## _id], \
|
||||
+ &rmon_stats->stats._member)
|
||||
+
|
||||
+ MV88E6XXX_RMON_STAT_MAP(in_undersize, undersize_pkts);
|
||||
+ MV88E6XXX_RMON_STAT_MAP(in_oversize, oversize_pkts);
|
||||
+ MV88E6XXX_RMON_STAT_MAP(in_fragments, fragments);
|
||||
+ MV88E6XXX_RMON_STAT_MAP(in_jabber, jabbers);
|
||||
+ MV88E6XXX_RMON_STAT_MAP(hist_64bytes, hist[0]);
|
||||
+ MV88E6XXX_RMON_STAT_MAP(hist_65_127bytes, hist[1]);
|
||||
+ MV88E6XXX_RMON_STAT_MAP(hist_128_255bytes, hist[2]);
|
||||
+ MV88E6XXX_RMON_STAT_MAP(hist_256_511bytes, hist[3]);
|
||||
+ MV88E6XXX_RMON_STAT_MAP(hist_512_1023bytes, hist[4]);
|
||||
+ MV88E6XXX_RMON_STAT_MAP(hist_1024_max_bytes, hist[5]);
|
||||
+
|
||||
+#undef MV88E6XXX_RMON_STAT_MAP
|
||||
+
|
||||
+ *ranges = rmon_ranges;
|
||||
+}
|
||||
+
|
||||
static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
@@ -6997,6 +7038,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_eth_mac_stats = mv88e6xxx_get_eth_mac_stats,
|
||||
+ .get_rmon_stats = mv88e6xxx_get_rmon_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
.port_max_mtu = mv88e6xxx_get_max_mtu,
|
||||
.port_change_mtu = mv88e6xxx_change_mtu,
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,315 +0,0 @@
|
||||
From 4407b94b4a08536fccb6eea2826955ff12d63ec2 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 16 Nov 2023 19:44:32 +0100
|
||||
Subject: [PATCH 09/35] net: dsa: mv88e6xxx: Add LED infrastructure
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Parse DT for LEDs and register them for devices that support it,
|
||||
though no actual implementations exist yet.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 5 +-
|
||||
drivers/net/dsa/mv88e6xxx/chip.h | 16 +++
|
||||
drivers/net/dsa/mv88e6xxx/leds.c | 184 +++++++++++++++++++++++++++++
|
||||
drivers/net/dsa/mv88e6xxx/leds.h | 12 ++
|
||||
5 files changed, 217 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/net/dsa/mv88e6xxx/leds.c
|
||||
create mode 100644 drivers/net/dsa/mv88e6xxx/leds.h
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile
|
||||
index a9a9651187db..6720d9303914 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/Makefile
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/Makefile
|
||||
@@ -9,6 +9,7 @@ mv88e6xxx-objs += global2.o
|
||||
mv88e6xxx-objs += global2_avb.o
|
||||
mv88e6xxx-objs += global2_scratch.o
|
||||
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o
|
||||
+mv88e6xxx-objs += leds.o
|
||||
mv88e6xxx-objs += pcs-6185.o
|
||||
mv88e6xxx-objs += pcs-6352.o
|
||||
mv88e6xxx-objs += pcs-639x.o
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 1fd4fc9ace61..bf26941e4e31 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "global1.h"
|
||||
#include "global2.h"
|
||||
#include "hwtstamp.h"
|
||||
+#include "leds.h"
|
||||
#include "phy.h"
|
||||
#include "port.h"
|
||||
#include "ptp.h"
|
||||
@@ -4083,7 +4084,9 @@ static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port)
|
||||
return err;
|
||||
}
|
||||
|
||||
- return mv88e6xxx_setup_devlink_regions_port(ds, port);
|
||||
+ err = err ? : mv88e6xxx_setup_devlink_regions_port(ds, port);
|
||||
+ err = err ? : mv88e6xxx_port_setup_leds(ds, port);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port)
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
|
||||
index c34caf9815c5..f8796cbeefa5 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
|
||||
@@ -206,6 +206,7 @@ struct mv88e6xxx_gpio_ops;
|
||||
struct mv88e6xxx_avb_ops;
|
||||
struct mv88e6xxx_ptp_ops;
|
||||
struct mv88e6xxx_pcs_ops;
|
||||
+struct mv88e6xxx_led_ops;
|
||||
|
||||
struct mv88e6xxx_irq {
|
||||
u16 masked;
|
||||
@@ -329,6 +330,8 @@ struct mv88e6xxx_hw_stat {
|
||||
int type;
|
||||
};
|
||||
|
||||
+struct mv88e6xxx_led;
|
||||
+
|
||||
struct mv88e6xxx_chip {
|
||||
const struct mv88e6xxx_info *info;
|
||||
|
||||
@@ -659,6 +662,9 @@ struct mv88e6xxx_ops {
|
||||
/* Precision Time Protocol operations */
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops;
|
||||
|
||||
+ /* LED operations */
|
||||
+ const struct mv88e6xxx_led_ops *led_ops;
|
||||
+
|
||||
/* Phylink */
|
||||
void (*phylink_get_caps)(struct mv88e6xxx_chip *chip, int port,
|
||||
struct phylink_config *config);
|
||||
@@ -742,7 +748,17 @@ struct mv88e6xxx_pcs_ops {
|
||||
void (*pcs_teardown)(struct mv88e6xxx_chip *chip, int port);
|
||||
struct phylink_pcs *(*pcs_select)(struct mv88e6xxx_chip *chip, int port,
|
||||
phy_interface_t mode);
|
||||
+};
|
||||
|
||||
+struct mv88e6xxx_led_ops {
|
||||
+ int (*brightness_set)(struct mv88e6xxx_led *led,
|
||||
+ enum led_brightness brightness);
|
||||
+ int (*blink_set)(struct mv88e6xxx_led *led,
|
||||
+ unsigned long *delay_on, unsigned long *delay_off);
|
||||
+ int (*hw_control_is_supported)(struct mv88e6xxx_led *led,
|
||||
+ unsigned long flags);
|
||||
+ int (*hw_control_set)(struct mv88e6xxx_led *led, unsigned long flags);
|
||||
+ int (*hw_control_get)(struct mv88e6xxx_led *led, unsigned long *flags);
|
||||
};
|
||||
|
||||
static inline bool mv88e6xxx_has_stu(struct mv88e6xxx_chip *chip)
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/leds.c b/drivers/net/dsa/mv88e6xxx/leds.c
|
||||
new file mode 100644
|
||||
index 000000000000..42e1661e1f47
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/leds.c
|
||||
@@ -0,0 +1,184 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+#include <net/dsa.h>
|
||||
+
|
||||
+#include "chip.h"
|
||||
+#include "port.h"
|
||||
+
|
||||
+struct mv88e6xxx_led {
|
||||
+ struct mv88e6xxx_chip *chip;
|
||||
+ int port;
|
||||
+ u8 index;
|
||||
+
|
||||
+ struct led_classdev ldev;
|
||||
+};
|
||||
+
|
||||
+static int mv88e6xxx_led_brightness_set(struct led_classdev *ldev,
|
||||
+ enum led_brightness brightness)
|
||||
+{
|
||||
+ const struct mv88e6xxx_led_ops *ops;
|
||||
+ struct mv88e6xxx_led *led;
|
||||
+
|
||||
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
|
||||
+ ops = led->chip->info->ops->led_ops;
|
||||
+
|
||||
+ if (!ops->brightness_set)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return ops->brightness_set(led, brightness);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_led_blink_set(struct led_classdev *ldev,
|
||||
+ unsigned long *delay_on,
|
||||
+ unsigned long *delay_off)
|
||||
+{
|
||||
+ const struct mv88e6xxx_led_ops *ops;
|
||||
+ struct mv88e6xxx_led *led;
|
||||
+
|
||||
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
|
||||
+ ops = led->chip->info->ops->led_ops;
|
||||
+
|
||||
+ if (!ops->blink_set)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return ops->blink_set(led, delay_on, delay_off);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_led_hw_control_is_supported(struct led_classdev *ldev,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ const struct mv88e6xxx_led_ops *ops;
|
||||
+ struct mv88e6xxx_led *led;
|
||||
+
|
||||
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
|
||||
+ ops = led->chip->info->ops->led_ops;
|
||||
+
|
||||
+ if (!ops->hw_control_is_supported)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return ops->hw_control_is_supported(led, flags);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_led_hw_control_set(struct led_classdev *ldev,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ const struct mv88e6xxx_led_ops *ops;
|
||||
+ struct mv88e6xxx_led *led;
|
||||
+
|
||||
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
|
||||
+ ops = led->chip->info->ops->led_ops;
|
||||
+
|
||||
+ if (!ops->hw_control_set)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return ops->hw_control_set(led, flags);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_led_hw_control_get(struct led_classdev *ldev,
|
||||
+ unsigned long *flags)
|
||||
+{
|
||||
+ const struct mv88e6xxx_led_ops *ops;
|
||||
+ struct mv88e6xxx_led *led;
|
||||
+
|
||||
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
|
||||
+ ops = led->chip->info->ops->led_ops;
|
||||
+
|
||||
+ if (!ops->hw_control_get)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return ops->hw_control_get(led, flags);
|
||||
+}
|
||||
+
|
||||
+static struct device *mv88e6xxx_led_hw_control_get_device(struct led_classdev *ldev)
|
||||
+{
|
||||
+ struct mv88e6xxx_led *led;
|
||||
+ struct dsa_port *dp;
|
||||
+
|
||||
+ led = container_of(ldev, struct mv88e6xxx_led, ldev);
|
||||
+ dp = dsa_to_port(led->chip->ds, led->port);
|
||||
+
|
||||
+ if (dp && dp->slave)
|
||||
+ return &dp->slave->dev;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_port_setup_led(struct mv88e6xxx_chip *chip, int port,
|
||||
+ struct device_node *np)
|
||||
+{
|
||||
+ struct led_init_data init_data = {};
|
||||
+ struct mv88e6xxx_led *led;
|
||||
+ char *devname;
|
||||
+ u32 index;
|
||||
+ int err;
|
||||
+
|
||||
+ err = of_property_read_u32(np, "reg", &index);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (index >= 2)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ led = devm_kzalloc(chip->dev, sizeof(*led), GFP_KERNEL);
|
||||
+ if (!led)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ *led = (struct mv88e6xxx_led) {
|
||||
+ .chip = chip,
|
||||
+ .port = port,
|
||||
+ .index = index,
|
||||
+
|
||||
+ .ldev = {
|
||||
+ .max_brightness = 1,
|
||||
+ .brightness_set_blocking = mv88e6xxx_led_brightness_set,
|
||||
+ .blink_set = mv88e6xxx_led_blink_set,
|
||||
+
|
||||
+#ifdef CONFIG_LEDS_TRIGGERS
|
||||
+ .hw_control_trigger = "netdev",
|
||||
+ .hw_control_get_device = mv88e6xxx_led_hw_control_get_device,
|
||||
+
|
||||
+ .hw_control_is_supported = mv88e6xxx_led_hw_control_is_supported,
|
||||
+ .hw_control_set = mv88e6xxx_led_hw_control_set,
|
||||
+ .hw_control_get = mv88e6xxx_led_hw_control_get,
|
||||
+#endif
|
||||
+ },
|
||||
+ };
|
||||
+
|
||||
+ devname = devm_kasprintf(chip->dev, GFP_KERNEL, "%s.%d",
|
||||
+ dev_name(chip->dev), port);
|
||||
+ if (!devname)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ init_data = (struct led_init_data) {
|
||||
+ .fwnode = of_fwnode_handle(np),
|
||||
+ .devname_mandatory = true,
|
||||
+ .devicename = devname,
|
||||
+ };
|
||||
+
|
||||
+ return devm_led_classdev_register_ext(chip->dev, &led->ldev, &init_data);
|
||||
+}
|
||||
+
|
||||
+int mv88e6xxx_port_setup_leds(struct dsa_switch *ds, int port)
|
||||
+{
|
||||
+ struct dsa_port *dp = dsa_to_port(ds, port);
|
||||
+ struct mv88e6xxx_chip *chip = ds->priv;
|
||||
+ struct device_node *pnp, *np;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!chip->info->ops->led_ops)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!dp->dn)
|
||||
+ return 0;
|
||||
+
|
||||
+ pnp = of_get_child_by_name(dp->dn, "leds");
|
||||
+ if (!pnp)
|
||||
+ return 0;
|
||||
+
|
||||
+ for_each_available_child_of_node(pnp, np) {
|
||||
+ err = mv88e6xxx_port_setup_led(chip, port, np);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/leds.h b/drivers/net/dsa/mv88e6xxx/leds.h
|
||||
new file mode 100644
|
||||
index 000000000000..8afa2a0c0527
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/leds.h
|
||||
@@ -0,0 +1,12 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+
|
||||
+/* Marvell 88E6xxx Switch leds support. */
|
||||
+
|
||||
+#ifndef _MV88E6XXX_LEDS_H
|
||||
+#define _MV88E6XXX_LEDS_H
|
||||
+
|
||||
+#include "chip.h"
|
||||
+
|
||||
+int mv88e6xxx_port_setup_leds(struct dsa_switch *ds, int port);
|
||||
+
|
||||
+#endif /* _MV88E6XXX_LEDS_H */
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,361 +0,0 @@
|
||||
From a5cf5c0353db07e74d7a29dd4d5c2cb7775d5bec Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 16 Nov 2023 21:59:35 +0100
|
||||
Subject: [PATCH 10/35] net: dsa: mv88e6xxx: Add LED support for 6393X
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Trigger support:
|
||||
- "none"
|
||||
- "timer"
|
||||
- "netdev"
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 1 +
|
||||
drivers/net/dsa/mv88e6xxx/leds.c | 226 +++++++++++++++++++++++++++++++
|
||||
drivers/net/dsa/mv88e6xxx/leds.h | 2 +
|
||||
drivers/net/dsa/mv88e6xxx/port.c | 33 +++++
|
||||
drivers/net/dsa/mv88e6xxx/port.h | 7 +
|
||||
5 files changed, 269 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index bf26941e4e31..24c5663b5944 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -5595,6 +5595,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
|
||||
.gpio_ops = &mv88e6352_gpio_ops,
|
||||
.avb_ops = &mv88e6390_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
+ .led_ops = &mv88e6393x_led_ops,
|
||||
.phylink_get_caps = mv88e6393x_phylink_get_caps,
|
||||
.pcs_ops = &mv88e6393x_pcs_ops,
|
||||
};
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/leds.c b/drivers/net/dsa/mv88e6xxx/leds.c
|
||||
index 42e1661e1f47..b2a55d96b506 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/leds.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/leds.c
|
||||
@@ -4,6 +4,13 @@
|
||||
#include "chip.h"
|
||||
#include "port.h"
|
||||
|
||||
+#define FLAG_ACT (BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX))
|
||||
+#define FLAG_LINK BIT(TRIGGER_NETDEV_LINK)
|
||||
+#define FLAG_LINK_10 BIT(TRIGGER_NETDEV_LINK_10)
|
||||
+#define FLAG_LINK_100 BIT(TRIGGER_NETDEV_LINK_100)
|
||||
+#define FLAG_LINK_1G BIT(TRIGGER_NETDEV_LINK_1000)
|
||||
+#define FLAG_FULL BIT(TRIGGER_NETDEV_FULL_DUPLEX)
|
||||
+
|
||||
struct mv88e6xxx_led {
|
||||
struct mv88e6xxx_chip *chip;
|
||||
int port;
|
||||
@@ -12,6 +19,225 @@ struct mv88e6xxx_led {
|
||||
struct led_classdev ldev;
|
||||
};
|
||||
|
||||
+enum mv88e6393x_led_mode {
|
||||
+ MV88E6393X_LED_MODE_BLINK = 0xd,
|
||||
+ MV88E6393X_LED_MODE_OFF = 0xe,
|
||||
+ MV88E6393X_LED_MODE_ON = 0xf,
|
||||
+
|
||||
+ MV88E6393X_LED_MODES = 0x10
|
||||
+};
|
||||
+
|
||||
+static const unsigned long mv88e6393x_led_map_p1_p8[2][MV88E6393X_LED_MODES] = {
|
||||
+ {
|
||||
+ [0x1] = FLAG_ACT | FLAG_LINK_100 | FLAG_LINK_1G,
|
||||
+ [0x2] = FLAG_ACT | FLAG_LINK_1G,
|
||||
+ [0x3] = FLAG_ACT | FLAG_LINK,
|
||||
+ [0x6] = FLAG_FULL,
|
||||
+ [0x7] = FLAG_ACT | FLAG_LINK_10 | FLAG_LINK_1G,
|
||||
+ [0x8] = FLAG_LINK,
|
||||
+ [0x9] = FLAG_LINK_10,
|
||||
+ [0xa] = FLAG_ACT | FLAG_LINK_10,
|
||||
+ [0xb] = FLAG_LINK_100 | FLAG_LINK_1G,
|
||||
+ },
|
||||
+ {
|
||||
+ [0x1] = FLAG_ACT,
|
||||
+ [0x2] = FLAG_ACT | FLAG_LINK_10 | FLAG_LINK_100,
|
||||
+ [0x3] = FLAG_LINK_1G,
|
||||
+ [0x5] = FLAG_ACT | FLAG_LINK,
|
||||
+ [0x6] = FLAG_ACT | FLAG_LINK_10 | FLAG_LINK_1G,
|
||||
+ [0x7] = FLAG_LINK_10 | FLAG_LINK_1G,
|
||||
+ [0x9] = FLAG_LINK_100,
|
||||
+ [0xa] = FLAG_ACT | FLAG_LINK_100,
|
||||
+ [0xb] = FLAG_LINK_10 | FLAG_LINK_100,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static const unsigned long mv88e6393x_led_map_p9_p10[2][MV88E6393X_LED_MODES] = {
|
||||
+ {
|
||||
+ [0x1] = FLAG_ACT | FLAG_LINK,
|
||||
+ },
|
||||
+ {
|
||||
+ [0x6] = FLAG_FULL,
|
||||
+ [0x7] = FLAG_ACT | FLAG_LINK,
|
||||
+ [0x8] = FLAG_LINK,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+const unsigned long *mv88e6393x_led_map(struct mv88e6xxx_led *led)
|
||||
+{
|
||||
+ switch (led->port) {
|
||||
+ case 1:
|
||||
+ case 2:
|
||||
+ case 3:
|
||||
+ case 4:
|
||||
+ case 5:
|
||||
+ case 6:
|
||||
+ case 7:
|
||||
+ case 8:
|
||||
+ return mv88e6393x_led_map_p1_p8[led->index];
|
||||
+ case 9:
|
||||
+ case 10:
|
||||
+ return mv88e6393x_led_map_p9_p10[led->index];
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393x_led_flags_to_mode(struct mv88e6xxx_led *led, unsigned long flags)
|
||||
+{
|
||||
+ const unsigned long *map = mv88e6393x_led_map(led);
|
||||
+ int i;
|
||||
+
|
||||
+ if (!map)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (!flags)
|
||||
+ return MV88E6393X_LED_MODE_OFF;
|
||||
+
|
||||
+ for (i = 0; i < MV88E6393X_LED_MODES; i++) {
|
||||
+ if (map[i] == flags)
|
||||
+ return i;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393x_led_mode_to_flags(struct mv88e6xxx_led *led, u8 mode,
|
||||
+ unsigned long *flags)
|
||||
+{
|
||||
+ const unsigned long *map = mv88e6393x_led_map(led);
|
||||
+
|
||||
+ if (!map)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (mode == MV88E6393X_LED_MODE_OFF) {
|
||||
+ *flags = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (map[mode]) {
|
||||
+ *flags = map[mode];
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393x_led_set(struct mv88e6xxx_led *led, int mode)
|
||||
+{
|
||||
+ u16 ctrl;
|
||||
+ int err;
|
||||
+
|
||||
+ if (mode < 0)
|
||||
+ return mode;
|
||||
+
|
||||
+ mv88e6xxx_reg_lock(led->chip);
|
||||
+
|
||||
+ err = mv88e6393x_port_led_read(led->chip, led->port, 0, &ctrl);
|
||||
+ if (err)
|
||||
+ goto out;
|
||||
+
|
||||
+ switch (led->index) {
|
||||
+ case 0:
|
||||
+ ctrl &= ~0x0f;
|
||||
+ ctrl |= mode;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ ctrl &= ~0xf0;
|
||||
+ ctrl |= mode << 4;
|
||||
+ }
|
||||
+
|
||||
+ err = mv88e6393x_port_led_write(led->chip, led->port, 0, ctrl);
|
||||
+out:
|
||||
+ mv88e6xxx_reg_unlock(led->chip);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393x_led_get(struct mv88e6xxx_led *led)
|
||||
+{
|
||||
+ u16 ctrl;
|
||||
+ int err;
|
||||
+
|
||||
+ mv88e6xxx_reg_lock(led->chip);
|
||||
+ err = mv88e6393x_port_led_read(led->chip, led->port, 0, &ctrl);
|
||||
+ mv88e6xxx_reg_unlock(led->chip);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ switch (led->index) {
|
||||
+ case 0:
|
||||
+ return ctrl & 0xf;
|
||||
+ case 1:
|
||||
+ return (ctrl >> 4) & 0xf;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393x_led_brightness_set(struct mv88e6xxx_led *led,
|
||||
+ enum led_brightness brightness)
|
||||
+{
|
||||
+ if (brightness == LED_OFF)
|
||||
+ return mv88e6393x_led_set(led, MV88E6393X_LED_MODE_OFF);
|
||||
+
|
||||
+ return mv88e6393x_led_set(led, MV88E6393X_LED_MODE_ON);
|
||||
+}
|
||||
+static int mv88e6393x_led_blink_set(struct mv88e6xxx_led *led,
|
||||
+ unsigned long *delay_on,
|
||||
+ unsigned long *delay_off)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ /* Defer anything other than 50% duty cycles to software */
|
||||
+ if (*delay_on != *delay_off)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Reject values outside ~20% of our default rate (84ms) */
|
||||
+ if (*delay_on && ((*delay_on < 30) || (*delay_on > 50)))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ err = mv88e6393x_led_set(led, MV88E6393X_LED_MODE_BLINK);
|
||||
+ if (!err)
|
||||
+ *delay_on = *delay_off = 42;
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393x_led_hw_control_is_supported(struct mv88e6xxx_led *led,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ int mode = mv88e6393x_led_flags_to_mode(led, flags);
|
||||
+
|
||||
+ return (mode < 0) ? mode : 0;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393x_led_hw_control_set(struct mv88e6xxx_led *led,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ int mode = mv88e6393x_led_flags_to_mode(led, flags);
|
||||
+
|
||||
+ return mv88e6393x_led_set(led, mode);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393x_led_hw_control_get(struct mv88e6xxx_led *led,
|
||||
+ unsigned long *flags)
|
||||
+{
|
||||
+ int mode = mv88e6393x_led_get(led);
|
||||
+
|
||||
+ if (mode < 0)
|
||||
+ return mode;
|
||||
+
|
||||
+ return mv88e6393x_led_mode_to_flags(led, mode, flags);
|
||||
+}
|
||||
+
|
||||
+const struct mv88e6xxx_led_ops mv88e6393x_led_ops = {
|
||||
+ .brightness_set = mv88e6393x_led_brightness_set,
|
||||
+ .blink_set = mv88e6393x_led_blink_set,
|
||||
+ .hw_control_is_supported = mv88e6393x_led_hw_control_is_supported,
|
||||
+ .hw_control_set = mv88e6393x_led_hw_control_set,
|
||||
+ .hw_control_get = mv88e6393x_led_hw_control_get,
|
||||
+};
|
||||
+
|
||||
static int mv88e6xxx_led_brightness_set(struct led_classdev *ldev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/leds.h b/drivers/net/dsa/mv88e6xxx/leds.h
|
||||
index 8afa2a0c0527..542345d23dc5 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/leds.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/leds.h
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
+extern const struct mv88e6xxx_led_ops mv88e6393x_led_ops;
|
||||
+
|
||||
int mv88e6xxx_port_setup_leds(struct dsa_switch *ds, int port);
|
||||
|
||||
#endif /* _MV88E6XXX_LEDS_H */
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
index 5394a8cf7bf1..66073a1ef260 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/port.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
@@ -1539,6 +1539,39 @@ int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
|
||||
return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
|
||||
}
|
||||
|
||||
+/* Offset 0x16: LED Control Register */
|
||||
+
|
||||
+int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port,
|
||||
+ unsigned int pointer, u16 data)
|
||||
+{
|
||||
+ u16 cmd = BIT(15) | ((pointer & 0x7) << 12) | (data & 0x7ff);
|
||||
+ int err;
|
||||
+
|
||||
+ err = mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_LED_CONTROL, cmd);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ return mv88e6xxx_port_wait_bit(chip, port, MV88E6393X_PORT_LED_CONTROL, 15, 0);
|
||||
+}
|
||||
+
|
||||
+int mv88e6393x_port_led_read(struct mv88e6xxx_chip *chip, int port,
|
||||
+ unsigned int pointer, u16 *data)
|
||||
+{
|
||||
+ u16 cmd = (pointer & 0x7) << 12;
|
||||
+ int err;
|
||||
+
|
||||
+ err = mv88e6xxx_port_write(chip, port, MV88E6393X_PORT_LED_CONTROL, cmd);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = mv88e6xxx_port_read(chip, port, MV88E6393X_PORT_LED_CONTROL, &cmd);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ *data = cmd & 0x7ff;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
|
||||
* Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
|
||||
*/
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
|
||||
index ddadeb9bfdae..7157864dc20f 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/port.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/port.h
|
||||
@@ -309,6 +309,9 @@
|
||||
/* Offset 0x13: OutFiltered Counter */
|
||||
#define MV88E6XXX_PORT_OUT_FILTERED 0x13
|
||||
|
||||
+/* Offset 0x16: LED Control Register */
|
||||
+#define MV88E6393X_PORT_LED_CONTROL 0x16
|
||||
+
|
||||
/* Offset 0x18: IEEE Priority Mapping Table */
|
||||
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
|
||||
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000
|
||||
@@ -425,6 +428,10 @@ int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port,
|
||||
enum mv88e6xxx_policy_action action);
|
||||
int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
|
||||
u16 etype);
|
||||
+int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port,
|
||||
+ unsigned int pointer, u16 data);
|
||||
+int mv88e6393x_port_led_read(struct mv88e6xxx_chip *chip, int port,
|
||||
+ unsigned int pointer, u16 *data);
|
||||
int mv88e6393x_set_egress_port(struct mv88e6xxx_chip *chip,
|
||||
enum mv88e6xxx_egress_direction direction,
|
||||
int port);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
From be94ec851dbb8e55c3f5e82f197b2dc59566aea2 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 12 Mar 2024 10:27:24 +0100
|
||||
Subject: [PATCH 11/35] net: dsa: mv88e6xxx: Fix timeout on waiting for PPU on
|
||||
6393X
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
In a multi-chip setup, delays of up to 750ms are observed before the
|
||||
device (6393X) signals completion of PPU initialization (Global 1,
|
||||
register 0, bit 15). Therefore, increase the timeout threshold to 1s.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 24c5663b5944..bd3ef8deb23d 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -87,7 +87,7 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
|
||||
int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
|
||||
u16 mask, u16 val)
|
||||
{
|
||||
- const unsigned long timeout = jiffies + msecs_to_jiffies(50);
|
||||
+ const unsigned long timeout = jiffies + msecs_to_jiffies(1000);
|
||||
u16 data;
|
||||
int err;
|
||||
int i;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
From 69092f83541e6539ab82eec3052325c403675de4 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 16 Jan 2024 16:00:55 +0100
|
||||
Subject: [PATCH 12/35] net: dsa: Support MDB memberships whose L2 addresses
|
||||
overlap
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Multiple IP multicast groups (32 for v4, 2^80 for v6) map to the same
|
||||
L2 address. This means that switchdev drivers may receive multiple MDB
|
||||
additions for a particular L2 group on the same port. Since these were
|
||||
not reference counted before this change, removing a group membership
|
||||
after two overlapping memberships had been added would result in the
|
||||
membership being removed from hardware, even though one reference to
|
||||
the address still remained.
|
||||
|
||||
Steps to reproduce:
|
||||
|
||||
root@infix:~# mvls atu | grep 01:02:03
|
||||
root@infix:~# bridge mdb add dev br0 port e8 grp 238.1.2.3 permanent
|
||||
root@infix:~# bridge mdb add dev br0 port e8 grp 239.1.2.3 permanent
|
||||
root@infix:~# mvls atu | grep 01:02:03
|
||||
01:00:5e:01:02:03 1 static - - . . . . . . . . 8 . .
|
||||
root@infix:~# bridge mdb del dev br0 port e8 grp 239.1.2.3
|
||||
root@infix:~# mvls atu | grep 01:02:03
|
||||
root@infix:~#
|
||||
|
||||
Therefore, reference count MDB memberships and keep them in hardware
|
||||
as long as the count is positive. Fortunately, all the infrastructure
|
||||
needed to do this is already in place, since it is also needed on CPU
|
||||
and DSA ports. Thus, "implement" this by simply removing the guards
|
||||
which previously skipped reference countung on user ports.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
net/dsa/switch.c | 16 ----------------
|
||||
1 file changed, 16 deletions(-)
|
||||
|
||||
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
|
||||
index 1a42f9317334..2ad13e23635e 100644
|
||||
--- a/net/dsa/switch.c
|
||||
+++ b/net/dsa/switch.c
|
||||
@@ -164,14 +164,6 @@ static int dsa_port_do_mdb_add(struct dsa_port *dp,
|
||||
int port = dp->index;
|
||||
int err = 0;
|
||||
|
||||
- /* No need to bother with refcounting for user ports */
|
||||
- if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
|
||||
- err = ds->ops->port_mdb_add(ds, port, mdb, db);
|
||||
- trace_dsa_mdb_add_hw(dp, mdb->addr, mdb->vid, &db, err);
|
||||
-
|
||||
- return err;
|
||||
- }
|
||||
-
|
||||
mutex_lock(&dp->addr_lists_lock);
|
||||
|
||||
a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db);
|
||||
@@ -216,14 +208,6 @@ static int dsa_port_do_mdb_del(struct dsa_port *dp,
|
||||
int port = dp->index;
|
||||
int err = 0;
|
||||
|
||||
- /* No need to bother with refcounting for user ports */
|
||||
- if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
|
||||
- err = ds->ops->port_mdb_del(ds, port, mdb, db);
|
||||
- trace_dsa_mdb_del_hw(dp, mdb->addr, mdb->vid, &db, err);
|
||||
-
|
||||
- return err;
|
||||
- }
|
||||
-
|
||||
mutex_lock(&dp->addr_lists_lock);
|
||||
|
||||
a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
From 7c19df77212d0728874515e97cf297863a6ff2cd Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 19 Sep 2023 18:38:10 +0200
|
||||
Subject: [PATCH 13/35] net: phy: marvell10g: Support firmware loading on
|
||||
88X3310
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
When probing, if a device is waiting for firmware to be loaded into
|
||||
its RAM, ask userspace for the binary and load it over XMDIO.
|
||||
|
||||
We have no choice but to bail out of the probe if firmware is not
|
||||
available, as the device does not have any built-in image on which to
|
||||
fall back.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 161 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 161 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
|
||||
index d4bb90d76881..ec9ea5e947f9 100644
|
||||
--- a/drivers/net/phy/marvell10g.c
|
||||
+++ b/drivers/net/phy/marvell10g.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/delay.h>
|
||||
+#include <linux/firmware.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/marvell_phy.h>
|
||||
#include <linux/phy.h>
|
||||
@@ -50,6 +51,10 @@ enum {
|
||||
MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,
|
||||
MV_PMA_BOOT = 0xc050,
|
||||
MV_PMA_BOOT_FATAL = BIT(0),
|
||||
+ MV_PMA_BOOT_PRGS_MASK = 0x0006,
|
||||
+ MV_PMA_BOOT_PRGS_WAIT = 0x0002,
|
||||
+ MV_PMA_BOOT_APP_STARTED = BIT(4),
|
||||
+ MV_PMA_BOOT_APP_LOADED = BIT(6),
|
||||
|
||||
MV_PCS_BASE_T = 0x0000,
|
||||
MV_PCS_BASE_R = 0x1000,
|
||||
@@ -96,6 +101,12 @@ enum {
|
||||
MV_PCS_PORT_INFO_NPORTS_MASK = 0x0380,
|
||||
MV_PCS_PORT_INFO_NPORTS_SHIFT = 7,
|
||||
|
||||
+ /* Firmware downloading */
|
||||
+ MV_PCS_FW_ADDR_LOW = 0xd0f0,
|
||||
+ MV_PCS_FW_ADDR_HIGH = 0xd0f1,
|
||||
+ MV_PCS_FW_DATA = 0xd0f2,
|
||||
+ MV_PCS_FW_CSUM = 0xd0f3,
|
||||
+
|
||||
/* SerDes reinitialization 88E21X0 */
|
||||
MV_AN_21X0_SERDES_CTRL2 = 0x800f,
|
||||
MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS = BIT(13),
|
||||
@@ -149,6 +160,8 @@ struct mv3310_chip {
|
||||
int (*select_mactype)(unsigned long *interfaces);
|
||||
int (*init_interface)(struct phy_device *phydev, int mactype);
|
||||
|
||||
+ const char *firmware_path;
|
||||
+
|
||||
#ifdef CONFIG_HWMON
|
||||
int (*hwmon_read_temp_reg)(struct phy_device *phydev);
|
||||
#endif
|
||||
@@ -499,6 +512,145 @@ static const struct sfp_upstream_ops mv3310_sfp_ops = {
|
||||
.module_insert = mv3310_sfp_insert,
|
||||
};
|
||||
|
||||
+struct mv3310_fw_hdr {
|
||||
+ __le32 data_size;
|
||||
+ __le32 data_addr;
|
||||
+ __le16 data_csum;
|
||||
+ __le16 flags;
|
||||
+#define MV3310_FW_HDR_DATA_ONLY BIT(6)
|
||||
+ __le32 next_hdr;
|
||||
+ __le16 csum;
|
||||
+
|
||||
+ u8 pad[14];
|
||||
+} __packed;
|
||||
+
|
||||
+struct mv3310_fw_sect_info {
|
||||
+ const u8 *data;
|
||||
+ u32 size;
|
||||
+ u32 addr;
|
||||
+ u16 csum;
|
||||
+};
|
||||
+
|
||||
+static int mv3310_load_fw_sect(struct phy_device *phydev,
|
||||
+ const struct mv3310_fw_sect_info *si)
|
||||
+{
|
||||
+ size_t i;
|
||||
+ u16 csum;
|
||||
+
|
||||
+ dev_dbg(&phydev->mdio.dev, "Loading %u byte section at 0x%08x\n",
|
||||
+ si->size, si->addr);
|
||||
+
|
||||
+ for (i = 0, csum = 0; i < si->size; i++)
|
||||
+ csum += si->data[i];
|
||||
+
|
||||
+ if ((u16)~csum != si->csum) {
|
||||
+ dev_err(&phydev->mdio.dev, "Corrupt section data\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* Any existing checksum is cleared by a read */
|
||||
+ __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM);
|
||||
+
|
||||
+ __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_LOW, si->addr & 0xffff);
|
||||
+ __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_HIGH, si->addr >> 16);
|
||||
+
|
||||
+ for (i = 0; i < si->size; i += 2) {
|
||||
+ __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_DATA,
|
||||
+ (si->data[i + 1] << 8) | si->data[i]);
|
||||
+ }
|
||||
+
|
||||
+ csum = __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM);
|
||||
+ if ((u16)~csum != si->csum) {
|
||||
+ dev_err(&phydev->mdio.dev, "Download failed\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mv3310_load_fw(struct phy_device *phydev)
|
||||
+{
|
||||
+ const struct mv3310_chip *chip = to_mv3310_chip(phydev);
|
||||
+ struct mv3310_fw_sect_info si;
|
||||
+ const struct firmware *fw;
|
||||
+ struct mv3310_fw_hdr hdr;
|
||||
+ bool need_boot = false;
|
||||
+ const u8 *sect;
|
||||
+ size_t i;
|
||||
+ u32 next;
|
||||
+ u16 csum;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!chip->firmware_path)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ err = request_firmware(&fw, chip->firmware_path, &phydev->mdio.dev);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (fw->size & 1) {
|
||||
+ err = -EINVAL;
|
||||
+ goto release;
|
||||
+ }
|
||||
+
|
||||
+ phy_lock_mdio_bus(phydev);
|
||||
+
|
||||
+ for (sect = fw->data; (sect + sizeof(hdr)) < (fw->data + fw->size);) {
|
||||
+ memcpy(&hdr, sect, sizeof(hdr));
|
||||
+
|
||||
+ for (i = 0, csum = 0; i < offsetof(struct mv3310_fw_hdr, csum); i++)
|
||||
+ csum += sect[i];
|
||||
+
|
||||
+ if ((u16)~csum != le16_to_cpu(hdr.csum)) {
|
||||
+ dev_err(&phydev->mdio.dev, "Corrupt section header\n");
|
||||
+ err = -EINVAL;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
+ si.data = sect + sizeof(hdr);
|
||||
+ si.size = le32_to_cpu(hdr.data_size);
|
||||
+ si.addr = le32_to_cpu(hdr.data_addr);
|
||||
+ si.csum = le16_to_cpu(hdr.data_csum);
|
||||
+
|
||||
+ if ((si.data + si.size) > (fw->data + fw->size)) {
|
||||
+ dev_err(&phydev->mdio.dev, "Invalid section length\n");
|
||||
+ err = -EINVAL;
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
+ err = mv3310_load_fw_sect(phydev, &si);
|
||||
+ if (err)
|
||||
+ goto unlock;
|
||||
+
|
||||
+ if (!(le16_to_cpu(hdr.flags) & MV3310_FW_HDR_DATA_ONLY))
|
||||
+ need_boot = true;
|
||||
+
|
||||
+ next = le32_to_cpu(hdr.next_hdr);
|
||||
+ if (!next)
|
||||
+ break;
|
||||
+
|
||||
+ sect = fw->data + next;
|
||||
+ }
|
||||
+
|
||||
+ if (need_boot) {
|
||||
+ __phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT, 0,
|
||||
+ MV_PMA_BOOT_APP_LOADED);
|
||||
+ mdelay(200);
|
||||
+ if (!(__phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT) &
|
||||
+ MV_PMA_BOOT_APP_STARTED)) {
|
||||
+ dev_err(&phydev->mdio.dev, "Firmware boot failed\n");
|
||||
+ err = -ENODEV;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+unlock:
|
||||
+ phy_unlock_mdio_bus(phydev);
|
||||
+
|
||||
+release:
|
||||
+ release_firmware(fw);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
static int mv3310_probe(struct phy_device *phydev)
|
||||
{
|
||||
const struct mv3310_chip *chip = to_mv3310_chip(phydev);
|
||||
@@ -520,6 +672,12 @@ static int mv3310_probe(struct phy_device *phydev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
+ if ((ret & MV_PMA_BOOT_PRGS_MASK) == MV_PMA_BOOT_PRGS_WAIT) {
|
||||
+ ret = mv3310_load_fw(phydev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
@@ -1165,6 +1323,8 @@ static const struct mv3310_chip mv3310_type = {
|
||||
.select_mactype = mv3310_select_mactype,
|
||||
.init_interface = mv3310_init_interface,
|
||||
|
||||
+ .firmware_path = "mrvl/x3310fw.hdr",
|
||||
+
|
||||
#ifdef CONFIG_HWMON
|
||||
.hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg,
|
||||
#endif
|
||||
@@ -1428,4 +1588,5 @@ static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
|
||||
MODULE_DESCRIPTION("Marvell Alaska X/M multi-gigabit Ethernet PHY driver");
|
||||
+MODULE_FIRMWARE("mrvl/x3310fw.hdr");
|
||||
MODULE_LICENSE("GPL");
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
From 0c34b42b7a72ddf1af6f3534870d647801e493fa Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 21 Nov 2023 20:15:24 +0100
|
||||
Subject: [PATCH 14/35] net: phy: marvell10g: Fix power-up when strapped to
|
||||
start powered down
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
On devices which are hardware strapped to start powered down (PDSTATE
|
||||
== 1), make sure that we clear the power-down bit on all units
|
||||
affected by this setting.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 18 +++++++++++++++---
|
||||
1 file changed, 15 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
|
||||
index ec9ea5e947f9..5a1e89d3fbeb 100644
|
||||
--- a/drivers/net/phy/marvell10g.c
|
||||
+++ b/drivers/net/phy/marvell10g.c
|
||||
@@ -335,11 +335,23 @@ static int mv3310_power_down(struct phy_device *phydev)
|
||||
|
||||
static int mv3310_power_up(struct phy_device *phydev)
|
||||
{
|
||||
+ static const u16 resets[][2] = {
|
||||
+ { MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1 },
|
||||
+ { MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1 },
|
||||
+ { MDIO_MMD_PMAPMD, MDIO_CTRL1 },
|
||||
+ };
|
||||
struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
- int ret;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(resets); i++) {
|
||||
+ ret = phy_clear_bits_mmd(phydev, resets[i][0], resets[i][1],
|
||||
+ MDIO_CTRL1_LPOWER);
|
||||
+ if (ret)
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
- ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
|
||||
- MV_V2_PORT_CTRL_PWRDOWN);
|
||||
+ ret = ret ? : phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
|
||||
+ MV_V2_PORT_CTRL_PWRDOWN);
|
||||
|
||||
/* Sometimes, the power down bit doesn't clear immediately, and
|
||||
* a read of this register causes the bit not to clear. Delay
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,517 +0,0 @@
|
||||
From 6576918d3348f8e20802379d568d7632228af4d7 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 15 Nov 2023 20:58:42 +0100
|
||||
Subject: [PATCH 15/35] net: phy: marvell10g: Add LED support for 88X3310
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Pickup the LEDs from the state in which the hardware reset or
|
||||
bootloader left them, but also support further configuration via
|
||||
device tree. This is primarily needed because the electrical polarity
|
||||
and drive behavior is software controlled and not possible to set via
|
||||
hardware strapping.
|
||||
|
||||
Trigger support:
|
||||
- "none"
|
||||
- "timer": Map 60-100 ms periods to the fast rate (81ms) and 1000-1600
|
||||
ms periods to the slow rate (1300ms). Defer everything else to
|
||||
software blinking
|
||||
- "netdev": Offload link or duplex information to the solid behavior;
|
||||
tx and/or rx activity to blink behavior.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 422 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 422 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
|
||||
index 5a1e89d3fbeb..745aeb367ef8 100644
|
||||
--- a/drivers/net/phy/marvell10g.c
|
||||
+++ b/drivers/net/phy/marvell10g.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/marvell_phy.h>
|
||||
+#include <linux/of.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/sfp.h>
|
||||
#include <linux/netdevice.h>
|
||||
@@ -133,6 +134,16 @@ enum {
|
||||
MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN = 0x5,
|
||||
MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,
|
||||
MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII = 0x7,
|
||||
+ MV_V2_LED0_CONTROL = 0xf020,
|
||||
+ MV_V2_LED_CONTROL_POLARITY_MASK = 0x0003,
|
||||
+ MV_V2_LED_CONTROL_POLARITY_SHIFT = 0,
|
||||
+ MV_V2_LED_CONTROL_ACTIVE_HIGH = BIT(0),
|
||||
+ MV_V2_LED_CONTROL_TRISTATE = BIT(1),
|
||||
+ MV_V2_LED_CONTROL_BLINK_RATE = BIT(2),
|
||||
+ MV_V2_LED_CONTROL_SOLID_FUNC_MASK = 0x00f8,
|
||||
+ MV_V2_LED_CONTROL_SOLID_FUNC_SHIFT = 3,
|
||||
+ MV_V2_LED_CONTROL_BLINK_FUNC_MASK = 0x1f00,
|
||||
+ MV_V2_LED_CONTROL_BLINK_FUNC_SHIFT = 8,
|
||||
MV_V2_PORT_INTR_STS = 0xf040,
|
||||
MV_V2_PORT_INTR_MASK = 0xf043,
|
||||
MV_V2_PORT_INTR_STS_WOL_EN = BIT(8),
|
||||
@@ -155,6 +166,7 @@ enum {
|
||||
struct mv3310_chip {
|
||||
bool (*has_downshift)(struct phy_device *phydev);
|
||||
void (*init_supported_interfaces)(unsigned long *mask);
|
||||
+ int (*leds_probe)(struct phy_device *phydev);
|
||||
int (*get_mactype)(struct phy_device *phydev);
|
||||
int (*set_mactype)(struct phy_device *phydev, int mactype);
|
||||
int (*select_mactype)(unsigned long *interfaces);
|
||||
@@ -167,6 +179,13 @@ struct mv3310_chip {
|
||||
#endif
|
||||
};
|
||||
|
||||
+#define MV3310_N_LEDS 4
|
||||
+
|
||||
+struct mv3310_led {
|
||||
+ u8 index;
|
||||
+ u16 ctrl;
|
||||
+};
|
||||
+
|
||||
struct mv3310_priv {
|
||||
DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX);
|
||||
|
||||
@@ -177,6 +196,8 @@ struct mv3310_priv {
|
||||
|
||||
struct device *hwmon_dev;
|
||||
char *hwmon_name;
|
||||
+
|
||||
+ struct mv3310_led led[MV3310_N_LEDS];
|
||||
};
|
||||
|
||||
static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
|
||||
@@ -184,6 +205,396 @@ static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
|
||||
return phydev->drv->driver_data;
|
||||
}
|
||||
|
||||
+enum mv3310_led_func {
|
||||
+ MV3310_LED_FUNC_OFF = 0x00,
|
||||
+ MV3310_LED_FUNC_TX_RX = 0x01,
|
||||
+ MV3310_LED_FUNC_TX = 0x02,
|
||||
+ MV3310_LED_FUNC_RX = 0x03,
|
||||
+ MV3310_LED_FUNC_COLLISION = 0x04,
|
||||
+ MV3310_LED_FUNC_LINK_COPPER = 0x05,
|
||||
+ MV3310_LED_FUNC_LINK_FIBER = 0x06,
|
||||
+ MV3310_LED_FUNC_LINK = 0x07,
|
||||
+ MV3310_LED_FUNC_10M_LINK = 0x08,
|
||||
+ MV3310_LED_FUNC_100M_LINK = 0x09,
|
||||
+ MV3310_LED_FUNC_1G_LINK = 0x0a,
|
||||
+ MV3310_LED_FUNC_10G_LINK = 0x0b,
|
||||
+ MV3310_LED_FUNC_10M_100M_LINK = 0x0c,
|
||||
+ MV3310_LED_FUNC_10M_100M_1G_LINK = 0x0d,
|
||||
+ MV3310_LED_FUNC_100M_10G_LINK = 0x0e,
|
||||
+ MV3310_LED_FUNC_1G_10G_LINK = 0x0f,
|
||||
+ MV3310_LED_FUNC_1G_10G_SLAVE = 0x10,
|
||||
+ MV3310_LED_FUNC_1G_10G_MASTER = 0x11,
|
||||
+ MV3310_LED_FUNC_HALF_DUPLEX = 0x12,
|
||||
+ MV3310_LED_FUNC_FULL_DUPLEX = 0x13,
|
||||
+ MV3310_LED_FUNC_LINK_EEE = 0x14,
|
||||
+ MV3310_LED_FUNC_2G5_LINK = 0x15,
|
||||
+ MV3310_LED_FUNC_5G_LINK = 0x16,
|
||||
+ MV3310_LED_FUNC_ON = 0x17,
|
||||
+ MV3310_LED_FUNC_2G5_5G_SLAVE = 0x18,
|
||||
+ MV3310_LED_FUNC_2G5_5G_MASTER = 0x19,
|
||||
+
|
||||
+ MV3310_LED_FUNC_SPEED_BLINK = 0x1f
|
||||
+};
|
||||
+
|
||||
+static int mv3310_led_flags_from_funcs(struct mv3310_led *led,
|
||||
+ enum mv3310_led_func solid,
|
||||
+ enum mv3310_led_func blink,
|
||||
+ unsigned long *flagsp)
|
||||
+{
|
||||
+ unsigned long flags = 0;
|
||||
+
|
||||
+ switch (solid) {
|
||||
+ case MV3310_LED_FUNC_OFF:
|
||||
+ break;
|
||||
+ case MV3310_LED_FUNC_LINK_COPPER:
|
||||
+ case MV3310_LED_FUNC_LINK_FIBER:
|
||||
+ case MV3310_LED_FUNC_LINK:
|
||||
+ flags |= TRIGGER_NETDEV_LINK;
|
||||
+ break;
|
||||
+ case MV3310_LED_FUNC_HALF_DUPLEX:
|
||||
+ flags |= TRIGGER_NETDEV_HALF_DUPLEX;
|
||||
+ break;
|
||||
+ case MV3310_LED_FUNC_FULL_DUPLEX:
|
||||
+ flags |= TRIGGER_NETDEV_FULL_DUPLEX;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ switch (blink) {
|
||||
+ case MV3310_LED_FUNC_OFF:
|
||||
+ break;
|
||||
+ case MV3310_LED_FUNC_TX:
|
||||
+ flags |= TRIGGER_NETDEV_TX;
|
||||
+ break;
|
||||
+ case MV3310_LED_FUNC_RX:
|
||||
+ flags |= TRIGGER_NETDEV_RX;
|
||||
+ break;
|
||||
+ case MV3310_LED_FUNC_TX_RX:
|
||||
+ flags |= TRIGGER_NETDEV_TX | TRIGGER_NETDEV_RX;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ *flagsp = flags;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_funcs_from_flags(struct mv3310_led *led,
|
||||
+ unsigned long flags,
|
||||
+ enum mv3310_led_func *solid,
|
||||
+ enum mv3310_led_func *blink)
|
||||
+{
|
||||
+ unsigned long activity, duplex, link;
|
||||
+
|
||||
+ if (flags & ~(BIT(TRIGGER_NETDEV_LINK) |
|
||||
+ BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
|
||||
+ BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||
+ BIT(TRIGGER_NETDEV_TX) |
|
||||
+ BIT(TRIGGER_NETDEV_RX)))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ link = flags & BIT(TRIGGER_NETDEV_LINK);
|
||||
+
|
||||
+ duplex = flags & (BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
|
||||
+ BIT(TRIGGER_NETDEV_FULL_DUPLEX));
|
||||
+
|
||||
+ activity = flags & (BIT(TRIGGER_NETDEV_TX) |
|
||||
+ BIT(TRIGGER_NETDEV_RX));
|
||||
+
|
||||
+ if (link && duplex)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (solid) {
|
||||
+ if (link) {
|
||||
+ *solid = MV3310_LED_FUNC_LINK;
|
||||
+ } else if (duplex) {
|
||||
+ switch (duplex) {
|
||||
+ case BIT(TRIGGER_NETDEV_HALF_DUPLEX):
|
||||
+ *solid = MV3310_LED_FUNC_HALF_DUPLEX;
|
||||
+ break;
|
||||
+ case BIT(TRIGGER_NETDEV_FULL_DUPLEX):
|
||||
+ *solid = MV3310_LED_FUNC_FULL_DUPLEX;
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
+ *solid = MV3310_LED_FUNC_OFF;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (blink) {
|
||||
+ switch (activity) {
|
||||
+ case 0:
|
||||
+ *blink = MV3310_LED_FUNC_OFF;
|
||||
+ break;
|
||||
+ case BIT(TRIGGER_NETDEV_TX):
|
||||
+ *blink = MV3310_LED_FUNC_TX;
|
||||
+ break;
|
||||
+ case BIT(TRIGGER_NETDEV_RX):
|
||||
+ *blink = MV3310_LED_FUNC_RX;
|
||||
+ break;
|
||||
+ default:
|
||||
+ *blink = MV3310_LED_FUNC_TX_RX;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_get(struct phy_device *phydev,
|
||||
+ struct mv3310_led *led,
|
||||
+ enum mv3310_led_func *solid,
|
||||
+ enum mv3310_led_func *blink,
|
||||
+ bool *slow_blink)
|
||||
+{
|
||||
+ int ctrl;
|
||||
+
|
||||
+ ctrl = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
||||
+ MV_V2_LED0_CONTROL + led->index);
|
||||
+ if (ctrl < 0)
|
||||
+ return ctrl;
|
||||
+
|
||||
+ *solid = (ctrl & MV_V2_LED_CONTROL_SOLID_FUNC_MASK) >>
|
||||
+ MV_V2_LED_CONTROL_SOLID_FUNC_SHIFT;
|
||||
+ *blink = (ctrl & MV_V2_LED_CONTROL_BLINK_FUNC_MASK) >>
|
||||
+ MV_V2_LED_CONTROL_BLINK_FUNC_SHIFT;
|
||||
+
|
||||
+ *slow_blink = !!(ctrl & MV_V2_LED_CONTROL_BLINK_RATE);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_set(struct phy_device *phydev,
|
||||
+ struct mv3310_led *led,
|
||||
+ enum mv3310_led_func solid,
|
||||
+ enum mv3310_led_func blink,
|
||||
+ bool slow_blink)
|
||||
+{
|
||||
+ u16 ctrl = led->ctrl;
|
||||
+
|
||||
+ ctrl &= ~MV_V2_LED_CONTROL_SOLID_FUNC_MASK;
|
||||
+ ctrl &= ~MV_V2_LED_CONTROL_BLINK_FUNC_MASK;
|
||||
+ ctrl &= ~MV_V2_LED_CONTROL_BLINK_RATE;
|
||||
+
|
||||
+ ctrl |= solid << MV_V2_LED_CONTROL_SOLID_FUNC_SHIFT;
|
||||
+ ctrl |= blink << MV_V2_LED_CONTROL_BLINK_FUNC_SHIFT;
|
||||
+
|
||||
+ if (slow_blink)
|
||||
+ ctrl |= MV_V2_LED_CONTROL_BLINK_RATE;
|
||||
+
|
||||
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2,
|
||||
+ MV_V2_LED0_CONTROL + led->index, ctrl);
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_polarity_set(struct phy_device *phydev,
|
||||
+ int index, unsigned long modes)
|
||||
+{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+ struct mv3310_led *led;
|
||||
+ u16 ctrl;
|
||||
+ int err;
|
||||
+
|
||||
+ if (index < 0 || index >= MV3310_N_LEDS)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ led = &priv->led[index];
|
||||
+ ctrl = led->ctrl;
|
||||
+
|
||||
+ if (test_bit(PHY_LED_ACTIVE_LOW, &modes))
|
||||
+ ctrl &= ~MV_V2_LED_CONTROL_ACTIVE_HIGH;
|
||||
+ else
|
||||
+ ctrl |= MV_V2_LED_CONTROL_ACTIVE_HIGH;
|
||||
+
|
||||
+ if (test_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes))
|
||||
+ ctrl |= MV_V2_LED_CONTROL_TRISTATE;
|
||||
+ else
|
||||
+ ctrl &= ~MV_V2_LED_CONTROL_TRISTATE;
|
||||
+
|
||||
+ err = phy_write_mmd(phydev, MDIO_MMD_VEND2,
|
||||
+ MV_V2_LED0_CONTROL + index, ctrl);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ led->ctrl = ctrl;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_brightness_set(struct phy_device *phydev,
|
||||
+ u8 index, enum led_brightness value)
|
||||
+{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+ enum mv3310_led_func solid;
|
||||
+ struct mv3310_led *led;
|
||||
+
|
||||
+ if (index >= MV3310_N_LEDS)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ led = &priv->led[index];
|
||||
+
|
||||
+ if (value == LED_OFF)
|
||||
+ solid = MV3310_LED_FUNC_OFF;
|
||||
+ else
|
||||
+ solid = MV3310_LED_FUNC_ON;
|
||||
+
|
||||
+ return mv3310_led_set(phydev, led, solid, MV3310_LED_FUNC_OFF, false);
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_blink_set(struct phy_device *phydev, u8 index,
|
||||
+ unsigned long *delay_on,
|
||||
+ unsigned long *delay_off)
|
||||
+{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+ struct mv3310_led *led;
|
||||
+ bool slow_blink;
|
||||
+ int err;
|
||||
+
|
||||
+ if (index >= MV3310_N_LEDS)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ led = &priv->led[index];
|
||||
+
|
||||
+ if (*delay_on != *delay_off)
|
||||
+ /* Defer anything other than 50% duty cycles to
|
||||
+ * software.
|
||||
+ */
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Accept values within ~20% of our supported rates (80ms or
|
||||
+ * 1300ms periods).
|
||||
+ */
|
||||
+ if ((*delay_on >= 30) && (*delay_on <= 50))
|
||||
+ slow_blink = false;
|
||||
+ else if (((*delay_on >= 500) && (*delay_on <= 800)) || (*delay_on == 0))
|
||||
+ slow_blink = true;
|
||||
+ else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ err = mv3310_led_set(phydev, led, MV3310_LED_FUNC_OFF,
|
||||
+ MV3310_LED_FUNC_ON, slow_blink);
|
||||
+ if (!err)
|
||||
+ *delay_on = *delay_off = slow_blink ? 650 : 40;
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+ struct mv3310_led *led;
|
||||
+
|
||||
+ if (index >= MV3310_N_LEDS)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ led = &priv->led[index];
|
||||
+
|
||||
+ return mv3310_led_funcs_from_flags(led, flags, NULL, NULL);
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_hw_control_set(struct phy_device *phydev, u8 index,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+ enum mv3310_led_func solid, blink;
|
||||
+ struct mv3310_led *led;
|
||||
+ int err;
|
||||
+
|
||||
+ if (index >= MV3310_N_LEDS)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ led = &priv->led[index];
|
||||
+
|
||||
+ err = mv3310_led_funcs_from_flags(led, flags, &solid, &blink);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ return mv3310_led_set(phydev, led, solid, blink, false);
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_hw_control_get(struct phy_device *phydev, u8 index,
|
||||
+ unsigned long *flags)
|
||||
+{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+ enum mv3310_led_func solid, blink;
|
||||
+ struct mv3310_led *led;
|
||||
+ bool slow_blink;
|
||||
+ int err;
|
||||
+
|
||||
+ if (index >= MV3310_N_LEDS)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ led = &priv->led[index];
|
||||
+
|
||||
+ err = mv3310_led_get(phydev, led, &solid, &blink, &slow_blink);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ return mv3310_led_flags_from_funcs(led, solid, blink, flags);
|
||||
+}
|
||||
+
|
||||
+static int mv3310_led_probe_of(struct phy_device *phydev,
|
||||
+ struct device_node *np)
|
||||
+{
|
||||
+ u32 index;
|
||||
+ int err;
|
||||
+
|
||||
+ err = of_property_read_u32(np, "reg", &index);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (index >= MV3310_N_LEDS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* mv3310_led_polarity_set() will not be called unless the
|
||||
+ * device tree specifies a mode that of_phy_led() considers to
|
||||
+ * be a non-default configuration. I.e., something other than
|
||||
+ * (active-high, drive low on inactive). But the 3310's HW
|
||||
+ * default is (active-low, drive low on inactive). Therefore,
|
||||
+ * configure all LEDs defined in the DT with the kernel
|
||||
+ * defaults, and then let of_phy_led() set the final value if
|
||||
+ * the config deviates from that.
|
||||
+ */
|
||||
+ return mv3310_led_polarity_set(phydev, index, 0);
|
||||
+}
|
||||
+
|
||||
+static int mv3310_leds_probe(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+ struct device_node *node = phydev->mdio.dev.of_node;
|
||||
+ struct device_node *pnp, *np;
|
||||
+ int err, val, index;
|
||||
+
|
||||
+ for (index = 0; index < MV3310_N_LEDS; index++) {
|
||||
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
||||
+ MV_V2_LED0_CONTROL + index);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ priv->led[index] = (struct mv3310_led) {
|
||||
+ .index = index,
|
||||
+ .ctrl = val,
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ if (!node)
|
||||
+ return 0;
|
||||
+
|
||||
+ pnp = of_get_child_by_name(node, "leds");
|
||||
+ if (!pnp)
|
||||
+ return 0;
|
||||
+
|
||||
+ for_each_available_child_of_node(pnp, np) {
|
||||
+ err = mv3310_led_probe_of(phydev, np);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_HWMON
|
||||
static umode_t mv3310_hwmon_is_visible(const void *data,
|
||||
enum hwmon_sensor_types type,
|
||||
@@ -724,6 +1135,10 @@ static int mv3310_probe(struct phy_device *phydev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ ret = chip->leds_probe ? chip->leds_probe(phydev) : 0;
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
chip->init_supported_interfaces(priv->supported_interfaces);
|
||||
|
||||
return phy_sfp_probe(phydev, &mv3310_sfp_ops);
|
||||
@@ -1330,6 +1745,7 @@ static void mv2111_init_supported_interfaces(unsigned long *mask)
|
||||
static const struct mv3310_chip mv3310_type = {
|
||||
.has_downshift = mv3310_has_downshift,
|
||||
.init_supported_interfaces = mv3310_init_supported_interfaces,
|
||||
+ .leds_probe = mv3310_leds_probe,
|
||||
.get_mactype = mv3310_get_mactype,
|
||||
.set_mactype = mv3310_set_mactype,
|
||||
.select_mactype = mv3310_select_mactype,
|
||||
@@ -1531,6 +1947,12 @@ static struct phy_driver mv3310_drivers[] = {
|
||||
.set_loopback = genphy_c45_loopback,
|
||||
.get_wol = mv3110_get_wol,
|
||||
.set_wol = mv3110_set_wol,
|
||||
+ .led_polarity_set = mv3310_led_polarity_set,
|
||||
+ .led_brightness_set = mv3310_led_brightness_set,
|
||||
+ .led_blink_set = mv3310_led_blink_set,
|
||||
+ .led_hw_is_supported = mv3310_led_hw_is_supported,
|
||||
+ .led_hw_control_set = mv3310_led_hw_control_set,
|
||||
+ .led_hw_control_get = mv3310_led_hw_control_get,
|
||||
},
|
||||
{
|
||||
.phy_id = MARVELL_PHY_ID_88X3310,
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
From 1ad7f010e46133c725df5cab4d85f71f689ca191 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 12 Dec 2023 09:51:05 +0100
|
||||
Subject: [PATCH 16/35] net: phy: marvell10g: Support LEDs tied to a single
|
||||
media side
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
In a combo-port setup, i.e. where both the copper and fiber interface
|
||||
are available to the user, the LEDs may be physically located either
|
||||
by the RJ45 jack, or by an SFP cage.
|
||||
|
||||
For those scenarios, allow the device tree to indicate that an LED is
|
||||
tied to a particular media side, and use that information to refine
|
||||
the offloading of the "netdev" trigger, such that LEDs attached to the
|
||||
RJ45 jack only lights up when a copper link is established, and vice
|
||||
versa for the SFP cage.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 23 ++++++++++++++++++++++-
|
||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
|
||||
index 745aeb367ef8..58c2f9626ba3 100644
|
||||
--- a/drivers/net/phy/marvell10g.c
|
||||
+++ b/drivers/net/phy/marvell10g.c
|
||||
@@ -184,6 +184,9 @@ struct mv3310_chip {
|
||||
struct mv3310_led {
|
||||
u8 index;
|
||||
u16 ctrl;
|
||||
+
|
||||
+ unsigned copper:1;
|
||||
+ unsigned fiber:1;
|
||||
};
|
||||
|
||||
struct mv3310_priv {
|
||||
@@ -308,7 +311,12 @@ static int mv3310_led_funcs_from_flags(struct mv3310_led *led,
|
||||
|
||||
if (solid) {
|
||||
if (link) {
|
||||
- *solid = MV3310_LED_FUNC_LINK;
|
||||
+ if (led->copper)
|
||||
+ *solid = MV3310_LED_FUNC_LINK_COPPER;
|
||||
+ else if (led->fiber)
|
||||
+ *solid = MV3310_LED_FUNC_LINK_FIBER;
|
||||
+ else
|
||||
+ *solid = MV3310_LED_FUNC_LINK;
|
||||
} else if (duplex) {
|
||||
switch (duplex) {
|
||||
case BIT(TRIGGER_NETDEV_HALF_DUPLEX):
|
||||
@@ -538,6 +546,9 @@ static int mv3310_led_hw_control_get(struct phy_device *phydev, u8 index,
|
||||
static int mv3310_led_probe_of(struct phy_device *phydev,
|
||||
struct device_node *np)
|
||||
{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+ struct mv3310_led *led;
|
||||
+ const char *media;
|
||||
u32 index;
|
||||
int err;
|
||||
|
||||
@@ -548,6 +559,16 @@ static int mv3310_led_probe_of(struct phy_device *phydev,
|
||||
if (index >= MV3310_N_LEDS)
|
||||
return -EINVAL;
|
||||
|
||||
+ led = &priv->led[index];
|
||||
+
|
||||
+ err = of_property_read_string(np, "marvell,media", &media);
|
||||
+ if (!err) {
|
||||
+ if (!strcmp(media, "copper"))
|
||||
+ led->copper = 1;
|
||||
+ else if (!strcmp(media, "fiber"))
|
||||
+ led->fiber = 1;
|
||||
+ }
|
||||
+
|
||||
/* mv3310_led_polarity_set() will not be called unless the
|
||||
* device tree specifies a mode that of_phy_led() considers to
|
||||
* be a non-default configuration. I.e., something other than
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
From 11b9a3e328241edede03b6615bb9b0f1a40b9b7d Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Fri, 24 Nov 2023 23:29:55 +0100
|
||||
Subject: [PATCH 17/35] nvmem: layouts: onie-tlv: Let device probe even when
|
||||
TLV is invalid
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Before this change, probing an NVMEM device, expected to contain a
|
||||
valid TLV, would fail if it had not been provisioned yet. But an
|
||||
obvious way of provisioning is to write the TLV to the nvmem
|
||||
attribute, which would not be possible because the device would not
|
||||
be successfully probed.
|
||||
|
||||
Therefore, settle for reporting data corruption issues in the log, and
|
||||
simply refrain from registering any cells in those cases.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/nvmem/layouts/onie-tlv.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/nvmem/layouts/onie-tlv.c b/drivers/nvmem/layouts/onie-tlv.c
|
||||
index 59fc87ccfcff..834c46e46d0a 100644
|
||||
--- a/drivers/nvmem/layouts/onie-tlv.c
|
||||
+++ b/drivers/nvmem/layouts/onie-tlv.c
|
||||
@@ -196,7 +196,7 @@ static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem,
|
||||
|
||||
if (!onie_tlv_hdr_is_valid(dev, &hdr)) {
|
||||
dev_err(dev, "Invalid ONIE TLV header\n");
|
||||
- return -EINVAL;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len);
|
||||
@@ -204,7 +204,7 @@ static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem,
|
||||
table_len = hdr_len + data_len;
|
||||
if (table_len > ONIE_TLV_MAX_LEN) {
|
||||
dev_err(dev, "Invalid ONIE TLV data length\n");
|
||||
- return -EINVAL;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
table = devm_kmalloc(dev, table_len, GFP_KERNEL);
|
||||
@@ -216,7 +216,7 @@ static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem,
|
||||
return ret;
|
||||
|
||||
if (!onie_tlv_crc_is_valid(dev, table_len, table))
|
||||
- return -EINVAL;
|
||||
+ return 0;
|
||||
|
||||
data = table + hdr_len;
|
||||
ret = onie_tlv_add_cells(dev, nvmem, data_len, data);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
From ce1148b5c2e33541ad13ff2c4769d0b37d4e42b9 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 4 Mar 2024 16:47:28 +0100
|
||||
Subject: [PATCH 18/35] net: bridge: avoid classifying unknown multicast as
|
||||
mrouters_only
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Unknown multicast, MAC/IPv4/IPv6, should always be flooded according to
|
||||
the per-port mcast_flood setting, as well as to detected and configured
|
||||
mcast_router ports.
|
||||
|
||||
This patch drops the mrouters_only classifier of unknown IP multicast
|
||||
and moves the flow handling from br_multicast_flood() to br_flood().
|
||||
This in turn means br_flood() must know about multicast router ports.
|
||||
Because a multicast router should always receive both known and unknown
|
||||
multicast.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
include/uapi/linux/if_bridge.h | 1 +
|
||||
net/bridge/br.c | 5 +++++
|
||||
net/bridge/br_device.c | 10 ++++++----
|
||||
net/bridge/br_forward.c | 14 ++++++++++++--
|
||||
net/bridge/br_input.c | 2 +-
|
||||
net/bridge/br_multicast.c | 11 +++++++++--
|
||||
net/bridge/br_private.h | 18 ++++++++++++++++--
|
||||
7 files changed, 50 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
|
||||
index f95326fce6bb..2b1320025ec2 100644
|
||||
--- a/include/uapi/linux/if_bridge.h
|
||||
+++ b/include/uapi/linux/if_bridge.h
|
||||
@@ -811,6 +811,7 @@ enum br_boolopt_id {
|
||||
BR_BOOLOPT_NO_LL_LEARN,
|
||||
BR_BOOLOPT_MCAST_VLAN_SNOOPING,
|
||||
BR_BOOLOPT_MST_ENABLE,
|
||||
+ BR_BOOLOPT_MCAST_FLOOD_ALWAYS,
|
||||
BR_BOOLOPT_MAX
|
||||
};
|
||||
|
||||
diff --git a/net/bridge/br.c b/net/bridge/br.c
|
||||
index a6e94ceb7c9a..44c12cb210b5 100644
|
||||
--- a/net/bridge/br.c
|
||||
+++ b/net/bridge/br.c
|
||||
@@ -277,6 +277,9 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on,
|
||||
case BR_BOOLOPT_MST_ENABLE:
|
||||
err = br_mst_set_enabled(br, on, extack);
|
||||
break;
|
||||
+ case BR_BOOLOPT_MCAST_FLOOD_ALWAYS:
|
||||
+ br_opt_toggle(br, BROPT_MCAST_FLOOD_ALWAYS, on);
|
||||
+ break;
|
||||
default:
|
||||
/* shouldn't be called with unsupported options */
|
||||
WARN_ON(1);
|
||||
@@ -295,6 +298,8 @@ int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt)
|
||||
return br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED);
|
||||
case BR_BOOLOPT_MST_ENABLE:
|
||||
return br_opt_get(br, BROPT_MST_ENABLED);
|
||||
+ case BR_BOOLOPT_MCAST_FLOOD_ALWAYS:
|
||||
+ return br_opt_get(br, BROPT_MCAST_FLOOD_ALWAYS);
|
||||
default:
|
||||
/* shouldn't be called with unsupported options */
|
||||
WARN_ON(1);
|
||||
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
|
||||
index 42d4c3727bf7..d4c2fc34051f 100644
|
||||
--- a/net/bridge/br_device.c
|
||||
+++ b/net/bridge/br_device.c
|
||||
@@ -87,10 +87,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
dest = eth_hdr(skb)->h_dest;
|
||||
if (is_broadcast_ether_addr(dest)) {
|
||||
- br_flood(br, skb, BR_PKT_BROADCAST, false, true, vid);
|
||||
+ br_flood(br, skb, NULL, BR_PKT_BROADCAST, false, true, vid);
|
||||
} else if (is_multicast_ether_addr(dest)) {
|
||||
if (unlikely(netpoll_tx_running(dev))) {
|
||||
- br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid);
|
||||
+ br_flood(br, skb, brmctx, BR_PKT_MULTICAST, false, true, vid);
|
||||
goto out;
|
||||
}
|
||||
if (br_multicast_rcv(&brmctx, &pmctx_null, vlan, skb, vid)) {
|
||||
@@ -103,11 +103,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst))
|
||||
br_multicast_flood(mdst, skb, brmctx, false, true);
|
||||
else
|
||||
- br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid);
|
||||
+ br_flood(br, skb, brmctx, BR_PKT_MULTICAST, false, true, vid);
|
||||
} else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) {
|
||||
br_forward(dst->dst, skb, false, true);
|
||||
} else {
|
||||
- br_flood(br, skb, BR_PKT_UNICAST, false, true, vid);
|
||||
+ br_flood(br, skb, NULL, BR_PKT_UNICAST, false, true, vid);
|
||||
}
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
@@ -537,6 +537,8 @@ void br_dev_setup(struct net_device *dev)
|
||||
br->bridge_ageing_time = br->ageing_time = BR_DEFAULT_AGEING_TIME;
|
||||
dev->max_mtu = ETH_MAX_MTU;
|
||||
|
||||
+ br_opt_toggle(br, BROPT_MCAST_FLOOD_ALWAYS, false);
|
||||
+
|
||||
br_netfilter_rtable_init(br);
|
||||
br_stp_timer_init(br);
|
||||
br_multicast_init(br);
|
||||
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
|
||||
index e19b583ff2c6..1094364d96e0 100644
|
||||
--- a/net/bridge/br_forward.c
|
||||
+++ b/net/bridge/br_forward.c
|
||||
@@ -198,14 +198,19 @@ static struct net_bridge_port *maybe_deliver(
|
||||
|
||||
/* called under rcu_read_lock */
|
||||
void br_flood(struct net_bridge *br, struct sk_buff *skb,
|
||||
- enum br_pkt_type pkt_type, bool local_rcv, bool local_orig,
|
||||
- u16 vid)
|
||||
+ struct net_bridge_mcast *brmctx, enum br_pkt_type pkt_type,
|
||||
+ bool local_rcv, bool local_orig, u16 vid)
|
||||
{
|
||||
+ struct net_bridge_port *rport = NULL;
|
||||
struct net_bridge_port *prev = NULL;
|
||||
+ struct hlist_node *rp = NULL;
|
||||
struct net_bridge_port *p;
|
||||
|
||||
br_tc_skb_miss_set(skb, pkt_type != BR_PKT_BROADCAST);
|
||||
|
||||
+ if (pkt_type == BR_PKT_MULTICAST)
|
||||
+ rp = br_multicast_get_first_rport_node(brmctx, skb);
|
||||
+
|
||||
list_for_each_entry_rcu(p, &br->port_list, list) {
|
||||
/* Do not flood unicast traffic to ports that turn it off, nor
|
||||
* other traffic if flood off, except for traffic we originate
|
||||
@@ -216,6 +221,11 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
|
||||
continue;
|
||||
break;
|
||||
case BR_PKT_MULTICAST:
|
||||
+ rport = br_multicast_rport_from_node_skb(rp, skb);
|
||||
+ if (rport == p) {
|
||||
+ rp = rcu_dereference(hlist_next_rcu(rp));
|
||||
+ break;
|
||||
+ }
|
||||
if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev)
|
||||
continue;
|
||||
break;
|
||||
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
|
||||
index e09000e38d07..b3247bd4f8de 100644
|
||||
--- a/net/bridge/br_input.c
|
||||
+++ b/net/bridge/br_input.c
|
||||
@@ -212,7 +212,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
|
||||
br_forward(dst->dst, skb, local_rcv, false);
|
||||
} else {
|
||||
if (!mcast_hit)
|
||||
- br_flood(br, skb, pkt_type, local_rcv, false, vid);
|
||||
+ br_flood(br, skb, brmctx, pkt_type, local_rcv, false, vid);
|
||||
else
|
||||
br_multicast_flood(mdst, skb, brmctx, local_rcv, false);
|
||||
}
|
||||
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
|
||||
index c38244d60ff8..8de12a235095 100644
|
||||
--- a/net/bridge/br_multicast.c
|
||||
+++ b/net/bridge/br_multicast.c
|
||||
@@ -3773,6 +3773,11 @@ static void br_multicast_err_count(const struct net_bridge *br,
|
||||
u64_stats_update_end(&pstats->syncp);
|
||||
}
|
||||
|
||||
+static bool br_flood_mrouters(const struct net_bridge *br)
|
||||
+{
|
||||
+ return br_opt_get(br, BROPT_MCAST_FLOOD_ALWAYS) ? false : true;
|
||||
+}
|
||||
+
|
||||
static void br_multicast_pim(struct net_bridge_mcast *brmctx,
|
||||
struct net_bridge_mcast_port *pmctx,
|
||||
const struct sk_buff *skb)
|
||||
@@ -3819,7 +3824,8 @@ static int br_multicast_ipv4_rcv(struct net_bridge_mcast *brmctx,
|
||||
|
||||
if (err == -ENOMSG) {
|
||||
if (!ipv4_is_local_multicast(ip_hdr(skb)->daddr)) {
|
||||
- BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
|
||||
+ BR_INPUT_SKB_CB(skb)->mrouters_only =
|
||||
+ br_flood_mrouters(brmctx->br);
|
||||
} else if (pim_ipv4_all_pim_routers(ip_hdr(skb)->daddr)) {
|
||||
if (ip_hdr(skb)->protocol == IPPROTO_PIM)
|
||||
br_multicast_pim(brmctx, pmctx, skb);
|
||||
@@ -3888,7 +3894,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge_mcast *brmctx,
|
||||
|
||||
if (err == -ENOMSG || err == -ENODATA) {
|
||||
if (!ipv6_addr_is_ll_all_nodes(&ipv6_hdr(skb)->daddr))
|
||||
- BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
|
||||
+ BR_INPUT_SKB_CB(skb)->mrouters_only =
|
||||
+ br_flood_mrouters(brmctx->br);
|
||||
if (err == -ENODATA &&
|
||||
ipv6_addr_is_all_snoopers(&ipv6_hdr(skb)->daddr))
|
||||
br_ip6_multicast_mrd_rcv(brmctx, pmctx, skb);
|
||||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
|
||||
index e4f1a08322da..8e12efdba2e6 100644
|
||||
--- a/net/bridge/br_private.h
|
||||
+++ b/net/bridge/br_private.h
|
||||
@@ -480,6 +480,7 @@ enum net_bridge_opts {
|
||||
BROPT_VLAN_BRIDGE_BINDING,
|
||||
BROPT_MCAST_VLAN_SNOOPING_ENABLED,
|
||||
BROPT_MST_ENABLED,
|
||||
+ BROPT_MCAST_FLOOD_ALWAYS,
|
||||
};
|
||||
|
||||
struct net_bridge {
|
||||
@@ -881,8 +882,8 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb,
|
||||
bool local_rcv, bool local_orig);
|
||||
int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
|
||||
void br_flood(struct net_bridge *br, struct sk_buff *skb,
|
||||
- enum br_pkt_type pkt_type, bool local_rcv, bool local_orig,
|
||||
- u16 vid);
|
||||
+ struct net_bridge_mcast *brmctx, enum br_pkt_type pkt_type,
|
||||
+ bool local_rcv, bool local_orig, u16 vid);
|
||||
|
||||
/* return true if both source port and dest port are isolated */
|
||||
static inline bool br_skb_isolated(const struct net_bridge_port *to,
|
||||
@@ -1397,6 +1398,19 @@ static inline void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
|
||||
{
|
||||
}
|
||||
|
||||
+static inline struct hlist_node *
|
||||
+br_multicast_get_first_rport_node(struct net_bridge_mcast *brmctx,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static inline struct net_bridge_port *
|
||||
+br_multicast_rport_from_node_skb(struct hlist_node *rp, struct sk_buff *skb)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static inline bool br_multicast_is_router(struct net_bridge_mcast *brmctx,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
From ce74ee8c5461cc53851ca323b4dfc9937cab0e41 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Tue, 5 Mar 2024 06:44:41 +0100
|
||||
Subject: [PATCH 19/35] net: bridge: Ignore router ports when forwarding L2
|
||||
multicast
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Multicast router ports are either statically configured or learned from
|
||||
control protocol traffic (IGMP/MLD/PIM). These protocols regulate IP
|
||||
multicast -- MAC multicast should always be forwarded through flooding
|
||||
of unknown multicast or using permanent MDB entries.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
net/bridge/br_private.h | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
|
||||
index 8e12efdba2e6..5142decee8e7 100644
|
||||
--- a/net/bridge/br_private.h
|
||||
+++ b/net/bridge/br_private.h
|
||||
@@ -1076,7 +1076,10 @@ br_multicast_get_first_rport_node(struct net_bridge_mcast *brmctx,
|
||||
if (skb->protocol == htons(ETH_P_IPV6))
|
||||
return rcu_dereference(hlist_first_rcu(&brmctx->ip6_mc_router_list));
|
||||
#endif
|
||||
- return rcu_dereference(hlist_first_rcu(&brmctx->ip4_mc_router_list));
|
||||
+ if (skb->protocol == htons(ETH_P_IP))
|
||||
+ return rcu_dereference(hlist_first_rcu(&brmctx->ip4_mc_router_list));
|
||||
+
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
static inline struct net_bridge_port *
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
From 3c9b05198e0b7193f2dcddc1860cd77f0adbc3a2 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 21 Mar 2024 19:12:15 +0100
|
||||
Subject: [PATCH 20/35] net: dsa: Support EtherType based priority overrides
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
include/net/dsa.h | 4 ++++
|
||||
net/dsa/slave.c | 56 +++++++++++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 58 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/net/dsa.h b/include/net/dsa.h
|
||||
index 0b9c6aa27047..6c1f2d70cf84 100644
|
||||
--- a/include/net/dsa.h
|
||||
+++ b/include/net/dsa.h
|
||||
@@ -955,6 +955,10 @@ struct dsa_switch_ops {
|
||||
u8 prio);
|
||||
int (*port_del_dscp_prio)(struct dsa_switch *ds, int port, u8 dscp,
|
||||
u8 prio);
|
||||
+ int (*port_add_etype_prio)(struct dsa_switch *ds, int port, u16 etype,
|
||||
+ u8 prio);
|
||||
+ int (*port_del_etype_prio)(struct dsa_switch *ds, int port, u16 etype,
|
||||
+ u8 prio);
|
||||
|
||||
/*
|
||||
* Suspend and resume
|
||||
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
|
||||
index 48db91b33390..18d913bcd180 100644
|
||||
--- a/net/dsa/slave.c
|
||||
+++ b/net/dsa/slave.c
|
||||
@@ -2213,6 +2213,34 @@ dsa_slave_dcbnl_add_dscp_prio(struct net_device *dev, struct dcb_app *app)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int __maybe_unused
|
||||
+dsa_slave_dcbnl_set_etype_prio(struct net_device *dev, struct dcb_app *app)
|
||||
+{
|
||||
+ struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||
+ struct dsa_switch *ds = dp->ds;
|
||||
+ unsigned long mask, new_prio;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!ds->ops->port_add_etype_prio)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ err = dcb_ieee_setapp(dev, app);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ mask = dcb_ieee_getapp_mask(dev, app);
|
||||
+ new_prio = __fls(mask);
|
||||
+
|
||||
+ err = ds->ops->port_add_etype_prio(ds, dp->index,
|
||||
+ app->protocol, new_prio);
|
||||
+ if (err) {
|
||||
+ dcb_ieee_delapp(dev, app);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int __maybe_unused dsa_slave_dcbnl_ieee_setapp(struct net_device *dev,
|
||||
struct dcb_app *app)
|
||||
{
|
||||
@@ -2222,7 +2250,7 @@ static int __maybe_unused dsa_slave_dcbnl_ieee_setapp(struct net_device *dev,
|
||||
case 0:
|
||||
return dsa_slave_dcbnl_set_default_prio(dev, app);
|
||||
default:
|
||||
- return -EOPNOTSUPP;
|
||||
+ return dsa_slave_dcbnl_set_etype_prio(dev, app);
|
||||
}
|
||||
break;
|
||||
case IEEE_8021QAZ_APP_SEL_DSCP:
|
||||
@@ -2283,6 +2311,30 @@ dsa_slave_dcbnl_del_dscp_prio(struct net_device *dev, struct dcb_app *app)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int __maybe_unused
|
||||
+dsa_slave_dcbnl_del_etype_prio(struct net_device *dev, struct dcb_app *app)
|
||||
+{
|
||||
+ struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||
+ struct dsa_switch *ds = dp->ds;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!ds->ops->port_del_etype_prio)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ err = dcb_ieee_delapp(dev, app);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = ds->ops->port_del_etype_prio(ds, dp->index,
|
||||
+ app->protocol, app->priority);
|
||||
+ if (err) {
|
||||
+ dcb_ieee_setapp(dev, app);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int __maybe_unused dsa_slave_dcbnl_ieee_delapp(struct net_device *dev,
|
||||
struct dcb_app *app)
|
||||
{
|
||||
@@ -2292,7 +2344,7 @@ static int __maybe_unused dsa_slave_dcbnl_ieee_delapp(struct net_device *dev,
|
||||
case 0:
|
||||
return dsa_slave_dcbnl_del_default_prio(dev, app);
|
||||
default:
|
||||
- return -EOPNOTSUPP;
|
||||
+ return dsa_slave_dcbnl_del_etype_prio(dev, app);
|
||||
}
|
||||
break;
|
||||
case IEEE_8021QAZ_APP_SEL_DSCP:
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
From 333134a4ff2b8dd7fb00a75560254de96d1082ad Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Fri, 22 Mar 2024 16:15:43 +0100
|
||||
Subject: [PATCH 21/35] net: dsa: mv88e6xxx: Support EtherType based priority
|
||||
overrides
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 64 +++++++++++++++++++++++++++++
|
||||
drivers/net/dsa/mv88e6xxx/chip.h | 21 ++++++++++
|
||||
drivers/net/dsa/mv88e6xxx/global2.c | 56 ++++++++++++++++++++++++-
|
||||
drivers/net/dsa/mv88e6xxx/global2.h | 4 ++
|
||||
drivers/net/dsa/mv88e6xxx/port.c | 46 +++++++++++++++++++++
|
||||
drivers/net/dsa/mv88e6xxx/port.h | 20 +++++++--
|
||||
6 files changed, 207 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index bd3ef8deb23d..09b22a5a6e45 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -1686,6 +1686,11 @@ static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip)
|
||||
|
||||
static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(chip->qpri_po); i++)
|
||||
+ refcount_set(&chip->qpri_po[i].refcnt, 0);
|
||||
+
|
||||
if (chip->info->ops->pot_clear)
|
||||
return chip->info->ops->pot_clear(chip);
|
||||
|
||||
@@ -3357,6 +3362,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
||||
|
||||
chip->ports[port].chip = chip;
|
||||
chip->ports[port].port = port;
|
||||
+ refcount_set(&chip->ports[port].etype.refcnt, 0);
|
||||
|
||||
err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
|
||||
SPEED_UNFORCED, DUPLEX_UNFORCED,
|
||||
@@ -6493,6 +6499,7 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
|
||||
chip->dev = dev;
|
||||
|
||||
mutex_init(&chip->reg_lock);
|
||||
+ mutex_init(&chip->arb_lock);
|
||||
INIT_LIST_HEAD(&chip->mdios);
|
||||
idr_init(&chip->policies);
|
||||
INIT_LIST_HEAD(&chip->msts);
|
||||
@@ -7025,6 +7032,61 @@ static int mv88e6xxx_crosschip_lag_leave(struct dsa_switch *ds, int sw_index,
|
||||
return err_sync ? : err_pvt;
|
||||
}
|
||||
|
||||
+int mv88e6xxx_port_add_etype_prio(struct dsa_switch *ds, int port, u16 etype,
|
||||
+ u8 prio)
|
||||
+{
|
||||
+ struct mv88e6xxx_chip *chip = ds->priv;
|
||||
+ int err;
|
||||
+
|
||||
+ mv88e6xxx_reg_lock(chip);
|
||||
+ err = mv88e6xxx_port_claim_ether_type(chip, port, etype);
|
||||
+ if (err)
|
||||
+ goto err;
|
||||
+
|
||||
+ err = mv88e6xxx_g2_claim_qpri_po(chip,
|
||||
+ MV88E6XXX_G2_PRIO_OVERRIDE_PTR_ETYPE,
|
||||
+ prio);
|
||||
+ if (err)
|
||||
+ goto err_relinquish_etype;
|
||||
+
|
||||
+ mv88e6xxx_reg_unlock(chip);
|
||||
+ return 0;
|
||||
+
|
||||
+err_relinquish_etype:
|
||||
+ mv88e6xxx_port_relinquish_ether_type(chip, port);
|
||||
+err:
|
||||
+ mv88e6xxx_reg_unlock(chip);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+int mv88e6xxx_port_del_etype_prio(struct dsa_switch *ds, int port, u16 etype,
|
||||
+ u8 prio)
|
||||
+{
|
||||
+ struct mv88e6xxx_chip *chip = ds->priv;
|
||||
+ int err;
|
||||
+
|
||||
+ mv88e6xxx_reg_lock(chip);
|
||||
+ err = mv88e6xxx_g2_relinquish_qpri_po(chip,
|
||||
+ MV88E6XXX_G2_PRIO_OVERRIDE_PTR_ETYPE);
|
||||
+ if (err)
|
||||
+ goto err;
|
||||
+
|
||||
+ err = mv88e6xxx_port_relinquish_ether_type(chip, port);
|
||||
+ if (err)
|
||||
+ goto err_claim_po;
|
||||
+
|
||||
+ mv88e6xxx_reg_unlock(chip);
|
||||
+ return 0;
|
||||
+
|
||||
+err_claim_po:
|
||||
+ mv88e6xxx_g2_claim_qpri_po(chip,
|
||||
+ MV88E6XXX_G2_PRIO_OVERRIDE_PTR_ETYPE,
|
||||
+ prio);
|
||||
+err:
|
||||
+ mv88e6xxx_reg_unlock(chip);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.get_tag_protocol = mv88e6xxx_get_tag_protocol,
|
||||
.change_tag_protocol = mv88e6xxx_change_tag_protocol,
|
||||
@@ -7091,6 +7153,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.crosschip_lag_change = mv88e6xxx_crosschip_lag_change,
|
||||
.crosschip_lag_join = mv88e6xxx_crosschip_lag_join,
|
||||
.crosschip_lag_leave = mv88e6xxx_crosschip_lag_leave,
|
||||
+ .port_add_etype_prio = mv88e6xxx_port_add_etype_prio,
|
||||
+ .port_del_etype_prio = mv88e6xxx_port_del_etype_prio,
|
||||
};
|
||||
|
||||
static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
|
||||
index f8796cbeefa5..da92ec109416 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
|
||||
@@ -292,6 +292,11 @@ struct mv88e6xxx_port {
|
||||
|
||||
/* MacAuth Bypass control flag */
|
||||
bool mab;
|
||||
+
|
||||
+ struct {
|
||||
+ refcount_t refcnt;
|
||||
+ u16 proto;
|
||||
+ } etype;
|
||||
};
|
||||
|
||||
enum mv88e6xxx_region_id {
|
||||
@@ -330,6 +335,11 @@ struct mv88e6xxx_hw_stat {
|
||||
int type;
|
||||
};
|
||||
|
||||
+struct mv88e6xxx_po {
|
||||
+ refcount_t refcnt;
|
||||
+ u8 pri;
|
||||
+};
|
||||
+
|
||||
struct mv88e6xxx_led;
|
||||
|
||||
struct mv88e6xxx_chip {
|
||||
@@ -347,6 +357,14 @@ struct mv88e6xxx_chip {
|
||||
/* This mutex protects the access to the switch registers */
|
||||
struct mutex reg_lock;
|
||||
|
||||
+ /* This mutex protects arbitration of hardware resources which
|
||||
+ * may be allocated by multiple kernel consumers. As an
|
||||
+ * example, the dcb(8) facility manages priority overrides
|
||||
+ * independently per interface, whereas the hardware only
|
||||
+ * supports a single priority per chip.
|
||||
+ */
|
||||
+ struct mutex arb_lock;
|
||||
+
|
||||
/* The MII bus and the address on the bus that is used to
|
||||
* communication with the switch
|
||||
*/
|
||||
@@ -435,6 +453,9 @@ struct mv88e6xxx_chip {
|
||||
|
||||
/* Bridge MST to SID mappings */
|
||||
struct list_head msts;
|
||||
+
|
||||
+ /* Queue priority overrides */
|
||||
+ struct mv88e6xxx_po qpri_po[16];
|
||||
};
|
||||
|
||||
struct mv88e6xxx_bus_ops {
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
|
||||
index b2b5f6ba438f..2c52903e8992 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/global2.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
|
||||
@@ -315,7 +315,7 @@ int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats)
|
||||
static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
|
||||
u8 data)
|
||||
{
|
||||
- u16 val = (pointer << 8) | (data & 0x7);
|
||||
+ u16 val = (pointer << 8) | (data & 0xf);
|
||||
|
||||
return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PRIO_OVERRIDE,
|
||||
MV88E6XXX_G2_PRIO_OVERRIDE_UPDATE | val);
|
||||
@@ -335,6 +335,60 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
|
||||
return err;
|
||||
}
|
||||
|
||||
+int mv88e6xxx_g2_claim_qpri_po(struct mv88e6xxx_chip *chip, u8 pointer,
|
||||
+ u8 qpri)
|
||||
+{
|
||||
+ struct mv88e6xxx_po *po;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (pointer > ARRAY_SIZE(chip->qpri_po))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (qpri > 7)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ po = &chip->qpri_po[pointer];
|
||||
+
|
||||
+ mutex_lock(&chip->arb_lock);
|
||||
+ if (refcount_read(&po->refcnt)) {
|
||||
+ if (qpri == po->pri)
|
||||
+ refcount_inc(&po->refcnt);
|
||||
+ else
|
||||
+ err = -EBUSY;
|
||||
+ } else {
|
||||
+ err = mv88e6xxx_g2_pot_write(chip, pointer,
|
||||
+ MV88E6XXX_G2_PRIO_OVERRIDE_QFPRIEN | qpri);
|
||||
+ if (!err) {
|
||||
+ refcount_set(&po->refcnt, 1);
|
||||
+ po->pri = qpri;
|
||||
+ }
|
||||
+ }
|
||||
+ mutex_unlock(&chip->arb_lock);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+int mv88e6xxx_g2_relinquish_qpri_po(struct mv88e6xxx_chip *chip, u8 pointer)
|
||||
+{
|
||||
+ struct mv88e6xxx_po *po;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (pointer > ARRAY_SIZE(chip->qpri_po))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ po = &chip->qpri_po[pointer];
|
||||
+
|
||||
+ mutex_lock(&chip->arb_lock);
|
||||
+ if (refcount_dec_and_test(&po->refcnt)) {
|
||||
+ err = mv88e6xxx_g2_pot_write(chip, pointer, 0);
|
||||
+ if (err)
|
||||
+ refcount_set(&po->refcnt, 1);
|
||||
+ }
|
||||
+ mutex_unlock(&chip->arb_lock);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
/* Offset 0x14: EEPROM Command
|
||||
* Offset 0x15: EEPROM Data (for 16-bit data access)
|
||||
* Offset 0x15: EEPROM Addr (for 8-bit data access)
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
|
||||
index d9434f7cae53..22a2583a31d9 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/global2.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
|
||||
@@ -138,6 +138,7 @@
|
||||
#define MV88E6XXX_G2_PRIO_OVERRIDE_UPDATE 0x8000
|
||||
#define MV88E6XXX_G2_PRIO_OVERRIDE_FPRISET 0x1000
|
||||
#define MV88E6XXX_G2_PRIO_OVERRIDE_PTR_MASK 0x0f00
|
||||
+#define MV88E6XXX_G2_PRIO_OVERRIDE_PTR_ETYPE 0xc
|
||||
#define MV88E6352_G2_PRIO_OVERRIDE_QPRIAVBEN 0x0080
|
||||
#define MV88E6352_G2_PRIO_OVERRIDE_DATAAVB_MASK 0x0030
|
||||
#define MV88E6XXX_G2_PRIO_OVERRIDE_QFPRIEN 0x0008
|
||||
@@ -356,6 +357,9 @@ int mv88e6185_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
|
||||
int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
|
||||
|
||||
int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip);
|
||||
+int mv88e6xxx_g2_claim_qpri_po(struct mv88e6xxx_chip *chip, u8 pointer,
|
||||
+ u8 qpri);
|
||||
+int mv88e6xxx_g2_relinquish_qpri_po(struct mv88e6xxx_chip *chip, u8 pointer);
|
||||
|
||||
int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
|
||||
bool hash, u16 mask);
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
index 66073a1ef260..aba78838171b 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/port.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
@@ -1539,6 +1539,52 @@ int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
|
||||
return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
|
||||
}
|
||||
|
||||
+int mv88e6xxx_port_claim_ether_type(struct mv88e6xxx_chip *chip, int port,
|
||||
+ u16 etype)
|
||||
+{
|
||||
+ struct mv88e6xxx_port *p = &chip->ports[port];
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (!chip->info->ops->port_set_ether_type)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ mutex_lock(&chip->arb_lock);
|
||||
+ if (refcount_read(&p->etype.refcnt)) {
|
||||
+ if (etype == p->etype.proto)
|
||||
+ refcount_inc(&p->etype.refcnt);
|
||||
+ else
|
||||
+ err = -EBUSY;
|
||||
+ } else {
|
||||
+ err = chip->info->ops->port_set_ether_type(chip, port, etype);
|
||||
+ if (!err) {
|
||||
+ refcount_set(&p->etype.refcnt, 1);
|
||||
+ p->etype.proto = etype;
|
||||
+ }
|
||||
+ }
|
||||
+ mutex_unlock(&chip->arb_lock);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+int mv88e6xxx_port_relinquish_ether_type(struct mv88e6xxx_chip *chip, int port)
|
||||
+{
|
||||
+ struct mv88e6xxx_port *p = &chip->ports[port];
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (!chip->info->ops->port_set_ether_type)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ mutex_lock(&chip->arb_lock);
|
||||
+ if (refcount_dec_and_test(&p->etype.refcnt)) {
|
||||
+ err = chip->info->ops->port_set_ether_type(chip, port,
|
||||
+ MV88E6XXX_PORT_ETH_TYPE_DEFAULT);
|
||||
+ if (err)
|
||||
+ refcount_set(&p->etype.refcnt, 1);
|
||||
+ }
|
||||
+ mutex_unlock(&chip->arb_lock);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
/* Offset 0x16: LED Control Register */
|
||||
|
||||
int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port,
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
|
||||
index 7157864dc20f..7edb04c41ac8 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/port.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/port.h
|
||||
@@ -286,7 +286,18 @@
|
||||
|
||||
/* Offset 0x0F: Port Special Ether Type */
|
||||
#define MV88E6XXX_PORT_ETH_TYPE 0x0f
|
||||
-#define MV88E6XXX_PORT_ETH_TYPE_DEFAULT 0x9100
|
||||
+
|
||||
+/* When MV88E6XXX_PORT_ETH_TYPE is used to override the queue priority
|
||||
+ * of matching packets, the override applies to all the chip's
|
||||
+ * ports. However, if the packet also matches a traffic class that the
|
||||
+ * hardware classifies as being of higher priority, then that class's
|
||||
+ * override configuration is used instead, even if that override is
|
||||
+ * disabled. The class which is one level higher than EType is PPPoE,
|
||||
+ * so by using that as the default value when no other value has been
|
||||
+ * requested, we effectively disable the EType class for that port.
|
||||
+ */
|
||||
+#define MV88E6XXX_PORT_ETH_TYPE_DEFAULT ETH_P_PPP_DISC
|
||||
+
|
||||
|
||||
/* Offset 0x10: InDiscards Low Counter */
|
||||
#define MV88E6XXX_PORT_IN_DISCARD_LO 0x10
|
||||
@@ -426,8 +437,13 @@ int mv88e6352_port_set_policy(struct mv88e6xxx_chip *chip, int port,
|
||||
int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port,
|
||||
enum mv88e6xxx_policy_mapping mapping,
|
||||
enum mv88e6xxx_policy_action action);
|
||||
+int mv88e6393x_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
|
||||
+ u16 etype);
|
||||
int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
|
||||
u16 etype);
|
||||
+int mv88e6xxx_port_claim_ether_type(struct mv88e6xxx_chip *chip, int port,
|
||||
+ u16 etype);
|
||||
+int mv88e6xxx_port_relinquish_ether_type(struct mv88e6xxx_chip *chip, int port);
|
||||
int mv88e6393x_port_led_write(struct mv88e6xxx_chip *chip, int port,
|
||||
unsigned int pointer, u16 data);
|
||||
int mv88e6393x_port_led_read(struct mv88e6xxx_chip *chip, int port,
|
||||
@@ -438,8 +454,6 @@ int mv88e6393x_set_egress_port(struct mv88e6xxx_chip *chip,
|
||||
int mv88e6393x_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
|
||||
int upstream_port);
|
||||
int mv88e6393x_port_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
|
||||
-int mv88e6393x_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
|
||||
- u16 etype);
|
||||
int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
|
||||
bool message_port);
|
||||
int mv88e6xxx_port_set_trunk(struct mv88e6xxx_chip *chip, int port,
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
From cdddc24c05cedc0d0fabc48da17ec26aeb7c1ef9 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 27 Mar 2024 10:10:19 +0100
|
||||
Subject: [PATCH 22/35] net: phy: Do not resume PHY when attaching
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
The PHY should not start negotiating with its link-partner until
|
||||
explicitly instructed to do so.
|
||||
|
||||
Therefore, skip resuming the PHY in the attach phase, deferring it to
|
||||
when phy_start() is called from the net_device's open() callback,
|
||||
possibly via phylink_start().
|
||||
|
||||
Otherwise, drivers that attached to their PHYs during
|
||||
probing (e.g. DSA) would end up with a physical link being
|
||||
established, even though the corresponding interface was still
|
||||
administratively down.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/phy/phy_device.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
|
||||
index 1b144e23911c..16c9938465a2 100644
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -1555,7 +1555,6 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
- phy_resume(phydev);
|
||||
if (!phydev->is_on_sfp_module)
|
||||
phy_led_triggers_register(phydev);
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
From 1ec21a3fc54fb447501fd7edbf692b00a31fe3ec Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 27 Mar 2024 15:52:43 +0100
|
||||
Subject: [PATCH 23/35] net: dsa: mv88e6xxx: Improve indirect register access
|
||||
perf on 6393
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
When operating in multi-chip mode, the 6393 family maps a subset of
|
||||
commonly used global registers to the outermost address space (in
|
||||
which only the SMI command and data registers were available in
|
||||
previous families).
|
||||
|
||||
Therefore, add a new set of SMI operations which remaps accesses to
|
||||
such registers to the corresponding directly addressable register. All
|
||||
other accesses use the regular indirect interface.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 7 +++
|
||||
drivers/net/dsa/mv88e6xxx/global1.h | 3 ++
|
||||
drivers/net/dsa/mv88e6xxx/global2.h | 3 ++
|
||||
drivers/net/dsa/mv88e6xxx/smi.c | 76 +++++++++++++++++++++++++++++
|
||||
drivers/net/dsa/mv88e6xxx/smi.h | 30 ++++++++++++
|
||||
5 files changed, 119 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 09b22a5a6e45..62e0a4e5a9bb 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -6456,6 +6456,13 @@ static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip)
|
||||
/* Update the compatible info with the probed one */
|
||||
chip->info = info;
|
||||
|
||||
+ /* Now that we know the exact chip in use, we might be able to
|
||||
+ * make use of more efficient SMI operations
|
||||
+ */
|
||||
+ err = mv88e6xxx_smi_init(chip, chip->bus, chip->sw_addr);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
dev_info(chip->dev, "switch 0x%x detected: %s, revision %u\n",
|
||||
chip->info->prod_num, chip->info->name, rev);
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h
|
||||
index 3dbb7a1b8fe1..5ea956aadecc 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/global1.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
|
||||
@@ -218,6 +218,9 @@
|
||||
#define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI 0x00e0
|
||||
#define MV88E6390_G1_MONITOR_MGMT_CTL_DATA_MASK 0x00ff
|
||||
|
||||
+/* Offset 0x1B: Free Queue Size Register */
|
||||
+#define MV88E6XXX_G1_FREE_Q_SIZE 0x1b
|
||||
+
|
||||
/* Offset 0x1C: Global Control 2 */
|
||||
#define MV88E6XXX_G1_CTL2 0x1c
|
||||
#define MV88E6185_G1_CTL2_CASCADE_PORT_MASK 0xf000
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
|
||||
index 22a2583a31d9..0127902ceafc 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/global2.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
|
||||
@@ -144,6 +144,9 @@
|
||||
#define MV88E6XXX_G2_PRIO_OVERRIDE_QFPRIEN 0x0008
|
||||
#define MV88E6XXX_G2_PRIO_OVERRIDE_DATA_MASK 0x0007
|
||||
|
||||
+/* Offset 0x13: IMP Communication/Debug Register */
|
||||
+#define MV88E6390_G2_IMP_COMM 0x13
|
||||
+
|
||||
/* Offset 0x14: EEPROM Command */
|
||||
#define MV88E6XXX_G2_EEPROM_CMD 0x14
|
||||
#define MV88E6XXX_G2_EEPROM_CMD_BUSY 0x8000
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/smi.c b/drivers/net/dsa/mv88e6xxx/smi.c
|
||||
index a990271b7482..f54bb0e79030 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/smi.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/smi.c
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
+#include "global1.h"
|
||||
+#include "global2.h"
|
||||
#include "smi.h"
|
||||
|
||||
/* The switch ADDR[4:1] configuration pins define the chip SMI device address
|
||||
@@ -168,6 +170,78 @@ static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_indirect_ops = {
|
||||
.init = mv88e6xxx_smi_indirect_init,
|
||||
};
|
||||
|
||||
+static u8 mv88e6393_smi_indirect_remap(int dev, int reg)
|
||||
+{
|
||||
+ static const u8 g1_remap[32] = {
|
||||
+ [MV88E6352_G1_VTU_FID] = MV88E6393_SMI_G1_VTU_FID,
|
||||
+ [MV88E6352_G1_VTU_SID] = MV88E6393_SMI_G1_VTU_SID,
|
||||
+ [MV88E6XXX_G1_STS] = MV88E6393_SMI_G1_STS,
|
||||
+ [MV88E6XXX_G1_VTU_OP] = MV88E6393_SMI_G1_VTU_OP,
|
||||
+ [MV88E6XXX_G1_VTU_VID] = MV88E6393_SMI_G1_VTU_VID,
|
||||
+ [MV88E6XXX_G1_VTU_DATA1] = MV88E6393_SMI_G1_VTU_DATA1,
|
||||
+ [MV88E6XXX_G1_VTU_DATA2] = MV88E6393_SMI_G1_VTU_DATA2,
|
||||
+ [MV88E6352_G1_ATU_FID] = MV88E6393_SMI_G1_ATU_FID,
|
||||
+ [MV88E6XXX_G1_ATU_CTL] = MV88E6393_SMI_G1_ATU_CTL,
|
||||
+ [MV88E6XXX_G1_ATU_OP] = MV88E6393_SMI_G1_ATU_OP,
|
||||
+ [MV88E6XXX_G1_ATU_DATA] = MV88E6393_SMI_G1_ATU_DATA,
|
||||
+ [MV88E6XXX_G1_ATU_MAC01] = MV88E6393_SMI_G1_ATU_MAC01,
|
||||
+ [MV88E6XXX_G1_ATU_MAC23] = MV88E6393_SMI_G1_ATU_MAC23,
|
||||
+ [MV88E6XXX_G1_ATU_MAC45] = MV88E6393_SMI_G1_ATU_MAC45,
|
||||
+ [MV88E6XXX_G1_FREE_Q_SIZE] = MV88E6393_SMI_G1_FREE_Q_SIZE,
|
||||
+ [MV88E6XXX_G1_STATS_OP] = MV88E6393_SMI_G1_STATS_OP,
|
||||
+ [MV88E6XXX_G1_STATS_COUNTER_32] = MV88E6393_SMI_G1_STATS_COUNTER_32,
|
||||
+ [MV88E6XXX_G1_STATS_COUNTER_01] = MV88E6393_SMI_G1_STATS_COUNTER_01,
|
||||
+ };
|
||||
+
|
||||
+ static const u8 g2_remap[32] = {
|
||||
+ [MV88E6390_G2_IMP_COMM] = MV88E6393_SMI_G2_IMP_COMM,
|
||||
+ [MV88E6352_G2_AVB_CMD] = MV88E6393_SMI_G2_AVB_CMD,
|
||||
+ [MV88E6352_G2_AVB_DATA] = MV88E6393_SMI_G2_AVB_DATA,
|
||||
+ [MV88E6XXX_G2_SMI_PHY_CMD] = MV88E6393_SMI_G2_SMI_PHY_CMD,
|
||||
+ [MV88E6XXX_G2_SMI_PHY_DATA] = MV88E6393_SMI_G2_SMI_PHY_DATA,
|
||||
+ [MV88E6393X_G2_MACLINK_INT_SRC] = MV88E6393_SMI_G2_MACLINK_INT_SRC,
|
||||
+ };
|
||||
+
|
||||
+ switch (dev) {
|
||||
+ case 0x1b:
|
||||
+ return g1_remap[reg];
|
||||
+ case 0x1c:
|
||||
+ return g2_remap[reg];
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393_smi_indirect_read(struct mv88e6xxx_chip *chip,
|
||||
+ int dev, int reg, u16 *data)
|
||||
+{
|
||||
+ u8 remap = mv88e6393_smi_indirect_remap(dev, reg);
|
||||
+
|
||||
+ if (remap)
|
||||
+ return mv88e6xxx_smi_direct_read(chip, chip->sw_addr,
|
||||
+ remap, data);
|
||||
+
|
||||
+ return mv88e6xxx_smi_indirect_read(chip, dev, reg, data);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393_smi_indirect_write(struct mv88e6xxx_chip *chip,
|
||||
+ int dev, int reg, u16 data)
|
||||
+{
|
||||
+ u8 remap = mv88e6393_smi_indirect_remap(dev, reg);
|
||||
+
|
||||
+ if (remap)
|
||||
+ return mv88e6xxx_smi_direct_write(chip, chip->sw_addr,
|
||||
+ remap, data);
|
||||
+
|
||||
+ return mv88e6xxx_smi_indirect_write(chip, dev, reg, data);
|
||||
+}
|
||||
+
|
||||
+static const struct mv88e6xxx_bus_ops mv88e6393_smi_indirect_ops = {
|
||||
+ .read = mv88e6393_smi_indirect_read,
|
||||
+ .write = mv88e6393_smi_indirect_write,
|
||||
+ .init = mv88e6xxx_smi_indirect_init,
|
||||
+};
|
||||
+
|
||||
int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
|
||||
struct mii_bus *bus, int sw_addr)
|
||||
{
|
||||
@@ -175,6 +249,8 @@ int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
|
||||
chip->smi_ops = &mv88e6xxx_smi_dual_direct_ops;
|
||||
else if (sw_addr == 0)
|
||||
chip->smi_ops = &mv88e6xxx_smi_direct_ops;
|
||||
+ else if (chip->info->family == MV88E6XXX_FAMILY_6393)
|
||||
+ chip->smi_ops = &mv88e6393_smi_indirect_ops;
|
||||
else if (chip->info->multi_chip)
|
||||
chip->smi_ops = &mv88e6xxx_smi_indirect_ops;
|
||||
else
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/smi.h b/drivers/net/dsa/mv88e6xxx/smi.h
|
||||
index c6c71d5757f5..788cf68b7b33 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/smi.h
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/smi.h
|
||||
@@ -31,6 +31,36 @@
|
||||
/* Offset 0x01: SMI Data Register */
|
||||
#define MV88E6XXX_SMI_DATA 0x01
|
||||
|
||||
+/* When using the 6393 in indirect addressing mode, a subset of the
|
||||
+ * most commonly used registers are directly mapped out to the chip's
|
||||
+ * top address space, allowing them to be directly accessed.
|
||||
+ */
|
||||
+#define MV88E6393_SMI_G1_VTU_FID 0x02
|
||||
+#define MV88E6393_SMI_G1_VTU_SID 0x03
|
||||
+#define MV88E6393_SMI_G1_STS 0x04
|
||||
+#define MV88E6393_SMI_G1_VTU_OP 0x05
|
||||
+#define MV88E6393_SMI_G1_VTU_VID 0x06
|
||||
+#define MV88E6393_SMI_G1_VTU_DATA1 0x07
|
||||
+#define MV88E6393_SMI_G1_VTU_DATA2 0x08
|
||||
+#define MV88E6393_SMI_G1_ATU_FID 0x09
|
||||
+#define MV88E6393_SMI_G1_ATU_CTL 0x0a
|
||||
+#define MV88E6393_SMI_G1_ATU_OP 0x0b
|
||||
+#define MV88E6393_SMI_G1_ATU_DATA 0x0c
|
||||
+#define MV88E6393_SMI_G1_ATU_MAC01 0x0d
|
||||
+#define MV88E6393_SMI_G1_ATU_MAC23 0x0e
|
||||
+#define MV88E6393_SMI_G1_ATU_MAC45 0x0f
|
||||
+#define MV88E6393_SMI_G2_IMP_COMM 0x13
|
||||
+#define MV88E6393_SMI_G2_AVB_CMD 0x16
|
||||
+#define MV88E6393_SMI_G2_AVB_DATA 0x17
|
||||
+#define MV88E6393_SMI_G2_SMI_PHY_CMD 0x18
|
||||
+#define MV88E6393_SMI_G2_SMI_PHY_DATA 0x19
|
||||
+#define MV88E6393_SMI_G2_MACLINK_INT_SRC 0x1a
|
||||
+#define MV88E6393_SMI_G1_FREE_Q_SIZE 0x1b
|
||||
+#define MV88E6393_SMI_G1_STATS_OP 0x1d
|
||||
+#define MV88E6393_SMI_G1_STATS_COUNTER_32 0x1e
|
||||
+#define MV88E6393_SMI_G1_STATS_COUNTER_01 0x1f
|
||||
+
|
||||
+
|
||||
int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
|
||||
struct mii_bus *bus, int sw_addr);
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
From 5d7be493dcaa75ee69d521043062389d7772f8dc Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Thu, 4 Apr 2024 16:36:30 +0200
|
||||
Subject: [PATCH 24/35] net: bridge: drop delay for applying strict multicast
|
||||
filtering
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
This *local* patch drops the initial delay before applying strict multicast
|
||||
filtering, introduced in [1] and recently updated in [2].
|
||||
|
||||
The main reason for this patch is RFC conformance and customer expectations.
|
||||
At power on we assume the querier role by default and are expected to stop
|
||||
unknown flooding as soon as we have a membership report in place, not after
|
||||
10 seconds.
|
||||
|
||||
A proper fix for upstreaming could be to add a knob to disable the delay.
|
||||
|
||||
[1]: https://lore.kernel.org/netdev/1375311980-25575-1-git-send-email-linus.luessing@web.de/
|
||||
[2]: https://lore.kernel.org/netdev/20240127175033.9640-1-linus.luessing@c0d3.blue/
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
net/bridge/br_multicast.c | 42 +++++++--------------------------------
|
||||
net/bridge/br_private.h | 4 +---
|
||||
2 files changed, 8 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
|
||||
index 8de12a235095..919abce8b5ac 100644
|
||||
--- a/net/bridge/br_multicast.c
|
||||
+++ b/net/bridge/br_multicast.c
|
||||
@@ -1761,10 +1761,6 @@ static void br_ip6_multicast_querier_expired(struct timer_list *t)
|
||||
}
|
||||
#endif
|
||||
|
||||
-static void br_multicast_query_delay_expired(struct timer_list *t)
|
||||
-{
|
||||
-}
|
||||
-
|
||||
static void br_multicast_select_own_querier(struct net_bridge_mcast *brmctx,
|
||||
struct br_ip *ip,
|
||||
struct sk_buff *skb)
|
||||
@@ -3195,12 +3191,8 @@ int br_multicast_dump_querier_state(struct sk_buff *skb,
|
||||
|
||||
static void
|
||||
br_multicast_update_query_timer(struct net_bridge_mcast *brmctx,
|
||||
- struct bridge_mcast_other_query *query,
|
||||
- unsigned long max_delay)
|
||||
+ struct bridge_mcast_other_query *query)
|
||||
{
|
||||
- if (!timer_pending(&query->timer))
|
||||
- mod_timer(&query->delay_timer, jiffies + max_delay);
|
||||
-
|
||||
mod_timer(&query->timer, jiffies + brmctx->multicast_querier_interval);
|
||||
}
|
||||
|
||||
@@ -3391,13 +3383,12 @@ static void
|
||||
br_ip4_multicast_query_received(struct net_bridge_mcast *brmctx,
|
||||
struct net_bridge_mcast_port *pmctx,
|
||||
struct bridge_mcast_other_query *query,
|
||||
- struct br_ip *saddr,
|
||||
- unsigned long max_delay)
|
||||
+ struct br_ip *saddr)
|
||||
{
|
||||
if (!br_multicast_select_querier(brmctx, pmctx, saddr))
|
||||
return;
|
||||
|
||||
- br_multicast_update_query_timer(brmctx, query, max_delay);
|
||||
+ br_multicast_update_query_timer(brmctx, query);
|
||||
br_ip4_multicast_mark_router(brmctx, pmctx);
|
||||
}
|
||||
|
||||
@@ -3406,13 +3397,12 @@ static void
|
||||
br_ip6_multicast_query_received(struct net_bridge_mcast *brmctx,
|
||||
struct net_bridge_mcast_port *pmctx,
|
||||
struct bridge_mcast_other_query *query,
|
||||
- struct br_ip *saddr,
|
||||
- unsigned long max_delay)
|
||||
+ struct br_ip *saddr)
|
||||
{
|
||||
if (!br_multicast_select_querier(brmctx, pmctx, saddr))
|
||||
return;
|
||||
|
||||
- br_multicast_update_query_timer(brmctx, query, max_delay);
|
||||
+ br_multicast_update_query_timer(brmctx, query);
|
||||
br_ip6_multicast_mark_router(brmctx, pmctx);
|
||||
}
|
||||
#endif
|
||||
@@ -3466,7 +3456,7 @@ static void br_ip4_multicast_query(struct net_bridge_mcast *brmctx,
|
||||
|
||||
br_ip4_multicast_query_received(brmctx, pmctx,
|
||||
&brmctx->ip4_other_query,
|
||||
- &saddr, max_delay);
|
||||
+ &saddr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -3554,7 +3544,7 @@ static int br_ip6_multicast_query(struct net_bridge_mcast *brmctx,
|
||||
|
||||
br_ip6_multicast_query_received(brmctx, pmctx,
|
||||
&brmctx->ip6_other_query,
|
||||
- &saddr, max_delay);
|
||||
+ &saddr);
|
||||
goto out;
|
||||
} else if (!group) {
|
||||
goto out;
|
||||
@@ -4062,8 +4052,6 @@ void br_multicast_ctx_init(struct net_bridge *br,
|
||||
br_ip4_multicast_local_router_expired, 0);
|
||||
timer_setup(&brmctx->ip4_other_query.timer,
|
||||
br_ip4_multicast_querier_expired, 0);
|
||||
- timer_setup(&brmctx->ip4_other_query.delay_timer,
|
||||
- br_multicast_query_delay_expired, 0);
|
||||
timer_setup(&brmctx->ip4_own_query.timer,
|
||||
br_ip4_multicast_query_expired, 0);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
@@ -4071,8 +4059,6 @@ void br_multicast_ctx_init(struct net_bridge *br,
|
||||
br_ip6_multicast_local_router_expired, 0);
|
||||
timer_setup(&brmctx->ip6_other_query.timer,
|
||||
br_ip6_multicast_querier_expired, 0);
|
||||
- timer_setup(&brmctx->ip6_other_query.delay_timer,
|
||||
- br_multicast_query_delay_expired, 0);
|
||||
timer_setup(&brmctx->ip6_own_query.timer,
|
||||
br_ip6_multicast_query_expired, 0);
|
||||
#endif
|
||||
@@ -4207,12 +4193,10 @@ static void __br_multicast_stop(struct net_bridge_mcast *brmctx)
|
||||
{
|
||||
del_timer_sync(&brmctx->ip4_mc_router_timer);
|
||||
del_timer_sync(&brmctx->ip4_other_query.timer);
|
||||
- del_timer_sync(&brmctx->ip4_other_query.delay_timer);
|
||||
del_timer_sync(&brmctx->ip4_own_query.timer);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
del_timer_sync(&brmctx->ip6_mc_router_timer);
|
||||
del_timer_sync(&brmctx->ip6_other_query.timer);
|
||||
- del_timer_sync(&brmctx->ip6_other_query.delay_timer);
|
||||
del_timer_sync(&brmctx->ip6_own_query.timer);
|
||||
#endif
|
||||
}
|
||||
@@ -4640,8 +4624,6 @@ EXPORT_SYMBOL_GPL(br_multicast_router);
|
||||
|
||||
int br_multicast_set_querier(struct net_bridge_mcast *brmctx, unsigned long val)
|
||||
{
|
||||
- unsigned long max_delay;
|
||||
-
|
||||
val = !!val;
|
||||
|
||||
spin_lock_bh(&brmctx->br->multicast_lock);
|
||||
@@ -4652,19 +4634,9 @@ int br_multicast_set_querier(struct net_bridge_mcast *brmctx, unsigned long val)
|
||||
if (!val)
|
||||
goto unlock;
|
||||
|
||||
- max_delay = brmctx->multicast_query_response_interval;
|
||||
-
|
||||
- if (!timer_pending(&brmctx->ip4_other_query.timer))
|
||||
- mod_timer(&brmctx->ip4_other_query.delay_timer,
|
||||
- jiffies + max_delay);
|
||||
-
|
||||
br_multicast_start_querier(brmctx, &brmctx->ip4_own_query);
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
- if (!timer_pending(&brmctx->ip6_other_query.timer))
|
||||
- mod_timer(&brmctx->ip6_other_query.delay_timer,
|
||||
- jiffies + max_delay);
|
||||
-
|
||||
br_multicast_start_querier(brmctx, &brmctx->ip6_own_query);
|
||||
#endif
|
||||
|
||||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
|
||||
index 5142decee8e7..db4f0705661a 100644
|
||||
--- a/net/bridge/br_private.h
|
||||
+++ b/net/bridge/br_private.h
|
||||
@@ -78,7 +78,6 @@ struct bridge_mcast_own_query {
|
||||
/* other querier */
|
||||
struct bridge_mcast_other_query {
|
||||
struct timer_list timer;
|
||||
- struct timer_list delay_timer;
|
||||
};
|
||||
|
||||
/* selected querier */
|
||||
@@ -1154,8 +1153,7 @@ __br_multicast_querier_exists(struct net_bridge_mcast *brmctx,
|
||||
own_querier_enabled = false;
|
||||
}
|
||||
|
||||
- return !timer_pending(&querier->delay_timer) &&
|
||||
- (own_querier_enabled || timer_pending(&querier->timer));
|
||||
+ return own_querier_enabled || timer_pending(&querier->timer);
|
||||
}
|
||||
|
||||
static inline bool br_multicast_querier_exists(struct net_bridge_mcast *brmctx,
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
From 492a824661dbc188b5abeb7434b5cf67c2016415 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Mon, 22 Apr 2024 23:18:01 +0200
|
||||
Subject: [PATCH 25/35] net: dsa: mv88e6xxx: Honor ports being managed via
|
||||
in-band-status
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Keep all link parameters in their unforced states when the port is
|
||||
declared as being managed via in-band-status, and let the MAC
|
||||
configure itself, via whatever method is being used (e.g. SGMII or
|
||||
USXGMII autoneg)
|
||||
|
||||
This state is the default set up by mv88e6xxx_port_setup_mac(), so all
|
||||
we have to do is to make the phylink MAC callbacks no-ops in cases
|
||||
when in-band-status is being used.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 62e0a4e5a9bb..58ba6af586a3 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -945,6 +945,9 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
|
||||
const struct mv88e6xxx_ops *ops;
|
||||
int err = 0;
|
||||
|
||||
+ if (mode == MLO_AN_INBAND)
|
||||
+ return;
|
||||
+
|
||||
ops = chip->info->ops;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
@@ -975,6 +978,9 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
|
||||
const struct mv88e6xxx_ops *ops;
|
||||
int err = 0;
|
||||
|
||||
+ if (mode == MLO_AN_INBAND)
|
||||
+ return;
|
||||
+
|
||||
ops = chip->info->ops;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
From c9c9597a47b00b720f5223c83ab05bb89481eda8 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 24 Apr 2024 21:35:26 +0200
|
||||
Subject: [PATCH 26/35] net: dsa: mv88e6xxx: Fix port policy config on 6393X
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
mv88e6393x_port_policy_{read,write} expect the `pointer` argument to
|
||||
be "pre-shifted" 8 bits.
|
||||
|
||||
Therefore, make sure mv88e6393x_port_set_policy adheres to this
|
||||
requirement.
|
||||
|
||||
Before this change, no policy actions from offset 1 could be
|
||||
configured. In particular, this meant that VTU policy trapping was
|
||||
never enabled on DSA ports, which broke standalone port isolation in
|
||||
multichip switch trees made up of 6393X decices.
|
||||
|
||||
Fixes: 6584b26020fc ("net: dsa: mv88e6xxx: implement .port_set_policy for Amethyst")
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/port.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
index aba78838171b..3f5759992baf 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/port.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
@@ -1793,12 +1793,12 @@ int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port,
|
||||
shift %= 8;
|
||||
mask >>= ptr * 8;
|
||||
|
||||
- err = mv88e6393x_port_policy_read(chip, port, ptr, ®);
|
||||
+ err = mv88e6393x_port_policy_read(chip, port, ptr << 8, ®);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
reg &= ~mask;
|
||||
reg |= (val << shift) & mask;
|
||||
|
||||
- return mv88e6393x_port_policy_write(chip, port, ptr, reg);
|
||||
+ return mv88e6393x_port_policy_write(chip, port, ptr << 8, reg);
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
From 4ff224b5f5de1347a1f686aa85cb918a7db18879 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 24 Apr 2024 22:41:04 +0200
|
||||
Subject: [PATCH 27/35] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user
|
||||
ports on 6393X
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
For packets with a DA in the IEEE reserved L2 group range, originating
|
||||
from a CPU, forward it as normal, rather than classifying it as
|
||||
management.
|
||||
|
||||
Example use-case:
|
||||
|
||||
bridge (group_fwd_mask 0x4000)
|
||||
/ | \
|
||||
swp1 swp2 tap0
|
||||
\ /
|
||||
(mv88e6xxx)
|
||||
|
||||
We've created a bridge with a non-zero group_fwd_mask (allowing LLDP
|
||||
in this example) containing a set of ports managed by mv88e6xxx and
|
||||
some foreign interface (e.g. an L2 VPN tunnel).
|
||||
|
||||
Since an LLDP packet coming in to the bridge from the other side of
|
||||
tap0 is eligable for tx forward offloading, a FORWARD frame destined
|
||||
for swp1 and swp2 would be send to the conduit interface.
|
||||
|
||||
Before this change, due to rsvd2cpu being enabled on the CPU port, the
|
||||
switch would try to trap it back to the CPU. Given that the CPU is
|
||||
trusted, instead assume that it indeed meant for the packet to be
|
||||
forwarded like any other.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/port.c | 31 +++++++++++++++++++++++++------
|
||||
1 file changed, 25 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
index 3f5759992baf..3dfe0f7805a0 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/port.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/port.c
|
||||
@@ -1432,6 +1432,23 @@ static int mv88e6393x_port_policy_write_all(struct mv88e6xxx_chip *chip,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int mv88e6393x_port_policy_write_user(struct mv88e6xxx_chip *chip,
|
||||
+ u16 pointer, u8 data)
|
||||
+{
|
||||
+ int err, port;
|
||||
+
|
||||
+ for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
|
||||
+ if (!dsa_is_user_port(chip->ds, port))
|
||||
+ continue;
|
||||
+
|
||||
+ err = mv88e6393x_port_policy_write(chip, port, pointer, data);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int mv88e6393x_set_egress_port(struct mv88e6xxx_chip *chip,
|
||||
enum mv88e6xxx_egress_direction direction,
|
||||
int port)
|
||||
@@ -1473,26 +1490,28 @@ int mv88e6393x_port_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
|
||||
int err;
|
||||
|
||||
/* Consider the frames with reserved multicast destination
|
||||
- * addresses matching 01:80:c2:00:00:00 and
|
||||
- * 01:80:c2:00:00:02 as MGMT.
|
||||
+ * addresses matching 01:80:c2:00:00:00 and 01:80:c2:00:00:02
|
||||
+ * as MGMT when received on user ports. Forward as normal on
|
||||
+ * CPU/DSA ports, to support bridges with non-zero
|
||||
+ * group_fwd_masks.
|
||||
*/
|
||||
ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000000XLO;
|
||||
- err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff);
|
||||
+ err = mv88e6393x_port_policy_write_user(chip, ptr, 0xff);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000000XHI;
|
||||
- err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff);
|
||||
+ err = mv88e6393x_port_policy_write_user(chip, ptr, 0xff);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000002XLO;
|
||||
- err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff);
|
||||
+ err = mv88e6393x_port_policy_write_user(chip, ptr, 0xff);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ptr = MV88E6393X_PORT_POLICY_MGMT_CTL_PTR_01C280000002XHI;
|
||||
- err = mv88e6393x_port_policy_write_all(chip, ptr, 0xff);
|
||||
+ err = mv88e6393x_port_policy_write_user(chip, ptr, 0xff);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
From f0d4beabe769fec594b309c3f1ebb79cfdbede8b Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 29 Apr 2024 15:14:51 +0200
|
||||
Subject: [PATCH 28/35] usb: core: adjust log level for unauthorized devices
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
The fact that a USB device currently is not authorized is not an error,
|
||||
so let's adjust the log level so these messages slip below radar for the
|
||||
commonly used 'quiet' log level.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/usb/core/driver.c | 4 ++--
|
||||
drivers/usb/core/generic.c | 2 +-
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
|
||||
index f58a0299fb3b..46450d806373 100644
|
||||
--- a/drivers/usb/core/driver.c
|
||||
+++ b/drivers/usb/core/driver.c
|
||||
@@ -332,10 +332,10 @@ static int usb_probe_interface(struct device *dev)
|
||||
return error;
|
||||
|
||||
if (udev->authorized == 0) {
|
||||
- dev_err(&intf->dev, "Device is not authorized for usage\n");
|
||||
+ dev_warn(&intf->dev, "Device is not authorized for usage\n");
|
||||
return error;
|
||||
} else if (intf->authorized == 0) {
|
||||
- dev_err(&intf->dev, "Interface %d is not authorized for usage\n",
|
||||
+ dev_warn(&intf->dev, "Interface %d is not authorized for usage\n",
|
||||
intf->altsetting->desc.bInterfaceNumber);
|
||||
return error;
|
||||
}
|
||||
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
|
||||
index 740342a2812a..2682bcf3e79f 100644
|
||||
--- a/drivers/usb/core/generic.c
|
||||
+++ b/drivers/usb/core/generic.c
|
||||
@@ -231,7 +231,7 @@ int usb_generic_driver_probe(struct usb_device *udev)
|
||||
* with the driver core and lets interface drivers bind to them.
|
||||
*/
|
||||
if (udev->authorized == 0)
|
||||
- dev_err(&udev->dev, "Device is not authorized for usage\n");
|
||||
+ dev_warn(&udev->dev, "Device is not authorized for usage\n");
|
||||
else {
|
||||
c = usb_choose_configuration(udev);
|
||||
if (c >= 0) {
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
From 5f96d718c850084504c53ec0b8d9fcf75ea9996c Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 15 May 2024 13:50:58 +0200
|
||||
Subject: [PATCH 29/35] net: dsa: mv88e6xxx: Grab register lock during counter
|
||||
snapshotting
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
This was missing for the standard counter groups. Since no caller
|
||||
already holds the lock, opt for pushing the locking down into
|
||||
mv88e6xxx_stats_snapshot() rather than having it duplicated at each
|
||||
call site.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 58ba6af586a3..7f289ecda847 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -1010,10 +1010,15 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
|
||||
|
||||
static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
|
||||
{
|
||||
+ int err;
|
||||
+
|
||||
if (!chip->info->ops->stats_snapshot)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
- return chip->info->ops->stats_snapshot(chip, port);
|
||||
+ mv88e6xxx_reg_lock(chip);
|
||||
+ err = chip->info->ops->stats_snapshot(chip, port);
|
||||
+ mv88e6xxx_reg_unlock(chip);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
#define MV88E6XXX_HW_STAT_MAPPER(_fn) \
|
||||
@@ -1385,10 +1390,7 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
int ret;
|
||||
|
||||
- mv88e6xxx_reg_lock(chip);
|
||||
-
|
||||
ret = mv88e6xxx_stats_snapshot(chip, port);
|
||||
- mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
if (ret < 0)
|
||||
return;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
From 6d4c436335003259cc02a0f015fd3d1d54e988a2 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Thu, 16 May 2024 14:51:54 +0200
|
||||
Subject: [PATCH 30/35] net: bridge: Differentiate MDB additions from
|
||||
modifications
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Before this change, the reception of an IGMPv3 report (and analogously
|
||||
for MLDv2) that adds a new group, would trigger two MDB RTM_NEWMDB
|
||||
notifications from br_ip4_multicast_igmp3_report():
|
||||
|
||||
1. In br_ip4_multicast_add_group() when creating the entry
|
||||
2. Directly at the end of br_ip4_multicast_igmp3_report(), as the new
|
||||
group is also deemed to be "changed"
|
||||
|
||||
The corresponding switchdev notifications generated by these present a
|
||||
problem for drivers wanting to reference count group memberships,
|
||||
since logically there is only a single reference to the group. Indeed,
|
||||
when the membership eventually times out, only a single RTM_DELMDB is
|
||||
generated.
|
||||
|
||||
Therefore, discriminate new groups from changes to existing groups by
|
||||
introducing a RTM_SETMDB events to be used in the latter scenario.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
include/uapi/linux/rtnetlink.h | 2 ++
|
||||
net/bridge/br_mdb.c | 4 ++--
|
||||
net/bridge/br_multicast.c | 8 ++++----
|
||||
3 files changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
|
||||
index 51c13cf9c5ae..fbc8fd1d5f2c 100644
|
||||
--- a/include/uapi/linux/rtnetlink.h
|
||||
+++ b/include/uapi/linux/rtnetlink.h
|
||||
@@ -134,6 +134,8 @@ enum {
|
||||
#define RTM_DELMDB RTM_DELMDB
|
||||
RTM_GETMDB = 86,
|
||||
#define RTM_GETMDB RTM_GETMDB
|
||||
+ RTM_SETMDB = 87,
|
||||
+#define RTM_SETMDB RTM_SETMDB
|
||||
|
||||
RTM_NEWNSID = 88,
|
||||
#define RTM_NEWNSID RTM_NEWNSID
|
||||
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
|
||||
index 7305f5f8215c..a2882b126ecb 100644
|
||||
--- a/net/bridge/br_mdb.c
|
||||
+++ b/net/bridge/br_mdb.c
|
||||
@@ -724,7 +724,7 @@ static int br_mdb_replace_group_sg(const struct br_mdb_config *cfg,
|
||||
else
|
||||
del_timer(&pg->timer);
|
||||
|
||||
- br_mdb_notify(cfg->br->dev, mp, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(cfg->br->dev, mp, pg, RTM_SETMDB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -945,7 +945,7 @@ static int br_mdb_replace_group_star_g(const struct br_mdb_config *cfg,
|
||||
else
|
||||
del_timer(&pg->timer);
|
||||
|
||||
- br_mdb_notify(cfg->br->dev, mp, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(cfg->br->dev, mp, pg, RTM_SETMDB);
|
||||
|
||||
if (br_multicast_should_handle_mode(brmctx, cfg->group.proto))
|
||||
br_multicast_star_g_handle_mode(pg, cfg->filter_mode);
|
||||
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
|
||||
index 919abce8b5ac..36f510b1f96c 100644
|
||||
--- a/net/bridge/br_multicast.c
|
||||
+++ b/net/bridge/br_multicast.c
|
||||
@@ -618,7 +618,7 @@ static void br_multicast_fwd_src_handle(struct net_bridge_group_src *src)
|
||||
sg_mp = br_mdb_ip_get(src->br, &sg_key.addr);
|
||||
if (!sg_mp)
|
||||
return;
|
||||
- br_mdb_notify(src->br->dev, sg_mp, sg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(src->br->dev, sg_mp, sg, RTM_SETMDB);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -885,7 +885,7 @@ static void br_multicast_port_group_expired(struct timer_list *t)
|
||||
|
||||
if (WARN_ON(!mp))
|
||||
goto out;
|
||||
- br_mdb_notify(br->dev, mp, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(br->dev, mp, pg, RTM_SETMDB);
|
||||
}
|
||||
out:
|
||||
spin_unlock(&br->multicast_lock);
|
||||
@@ -2886,7 +2886,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge_mcast *brmctx,
|
||||
break;
|
||||
}
|
||||
if (changed)
|
||||
- br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_SETMDB);
|
||||
unlock_continue:
|
||||
spin_unlock(&brmctx->br->multicast_lock);
|
||||
}
|
||||
@@ -3028,7 +3028,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge_mcast *brmctx,
|
||||
break;
|
||||
}
|
||||
if (changed)
|
||||
- br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_NEWMDB);
|
||||
+ br_mdb_notify(brmctx->br->dev, mdst, pg, RTM_SETMDB);
|
||||
unlock_continue:
|
||||
spin_unlock(&brmctx->br->multicast_lock);
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
From c333c612688d5e974b95fcf4b04f185d7cf4f80d Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 28 May 2024 10:38:42 +0200
|
||||
Subject: [PATCH 31/35] net: dsa: tag_dsa: Use tag priority as initial
|
||||
skb->priority
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Use the 3-bit priority field from the DSA tag as the initial packet
|
||||
priority on ingress to the CPU.
|
||||
|
||||
These bits contain the frame priority (FPri) of the packet. Barring
|
||||
any non-standard policy configuration, this corresponds to:
|
||||
|
||||
1. The original PCP bits if the packet is received with a VLAN tag
|
||||
2. ...or the the 3 MSBs of the DSCP field, if it is an IP packet
|
||||
3. ...otherwise 0
|
||||
|
||||
Ideally we could then map this priority to an internal one, like we
|
||||
can do with an "ingress-qos-map" on VLAN interfaces. Until that is
|
||||
implemented, support the setup that is likely to be the most common; a
|
||||
1:1 mapping from FPri to skb->priority.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
net/dsa/tag_dsa.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
|
||||
index 1fd7fa26db64..284bc65d1f63 100644
|
||||
--- a/net/dsa/tag_dsa.c
|
||||
+++ b/net/dsa/tag_dsa.c
|
||||
@@ -323,6 +323,13 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
|
||||
dsa_strip_etype_header(skb, DSA_HLEN + extra);
|
||||
}
|
||||
|
||||
+ /* Ideally we would have a way of configuring the mapping of PCP
|
||||
+ * bits to skb->priority on DSA ports (like ingress-qos-map for
|
||||
+ * vlan interfaces). For now, assume that a 1:1 mapping is more
|
||||
+ * useful than ignoring the priority altogether.
|
||||
+ */
|
||||
+ skb->priority = dsa_header[2] >> 5;
|
||||
+
|
||||
return skb;
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
From 18c025745fd8b8c9b3e688e9d78668a56cf71217 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 28 May 2024 11:04:22 +0200
|
||||
Subject: [PATCH 32/35] net: dsa: mv88e6xxx: Add mqprio qdisc support
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Add support for attaching mqprio qdisc's to mv88e6xxx ports and use
|
||||
the packet's traffic class as the outgoing priority when no PCP bits
|
||||
are available.
|
||||
|
||||
We cannot directly target a particular transmit queue on mv88e6xxx
|
||||
chips, we can only specify the frame priority (FPri), which will
|
||||
typically cause the switch to set the packet's queue priority (QPri)
|
||||
to the same value.
|
||||
|
||||
For symmetry, we give precedence to an explicit PCP value available in
|
||||
the packet, since that maps directly to the chip's FPri.
|
||||
|
||||
In cases where no PCP bits are available, use the packet's queue
|
||||
mapping to derive its traffic class and use that as the FPri. Since
|
||||
the packet will always be egressing without a tag in these cases, we
|
||||
are effectively only specifying the QPri.
|
||||
|
||||
Since FPri is always a 3-bit field, even on older chips with only 4
|
||||
physical queues, always report 8 queues and let the chip's policy
|
||||
handle the mapping down to the "real" number.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 70 ++++++++++++++++++++++++++++++++
|
||||
net/dsa/tag_dsa.c | 4 +-
|
||||
2 files changed, 73 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 7f289ecda847..0c6ab36a6905 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/phylink.h>
|
||||
#include <net/dsa.h>
|
||||
+#include <net/pkt_sched.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "devlink.h"
|
||||
@@ -7102,6 +7103,68 @@ int mv88e6xxx_port_del_etype_prio(struct dsa_switch *ds, int port, u16 etype,
|
||||
return err;
|
||||
}
|
||||
|
||||
+static int mv88e6xxx_qos_port_mqprio(struct mv88e6xxx_chip *chip, int port,
|
||||
+ struct tc_mqprio_qopt_offload *mqprio)
|
||||
+{
|
||||
+ struct net_device *dev = dsa_to_port(chip->ds, port)->slave;
|
||||
+ struct tc_mqprio_qopt *qopt = &mqprio->qopt;
|
||||
+ int tc, err = 0, num_txq = 0;
|
||||
+
|
||||
+ if (!qopt->num_tc)
|
||||
+ goto out_reset;
|
||||
+
|
||||
+ err = netdev_set_num_tc(dev, qopt->num_tc);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ for (tc = 0; tc < qopt->num_tc; tc++) {
|
||||
+ num_txq += qopt->count[tc];
|
||||
+
|
||||
+ err = netdev_set_tc_queue(dev, tc, qopt->count[tc], qopt->offset[tc]);
|
||||
+ if (err)
|
||||
+ goto out_reset;
|
||||
+ }
|
||||
+
|
||||
+ err = netif_set_real_num_tx_queues(dev, num_txq);
|
||||
+ if (err)
|
||||
+ goto out_reset;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+out_reset:
|
||||
+ netdev_reset_tc(dev);
|
||||
+ return err;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_qos_query_caps(struct tc_query_caps_base *base)
|
||||
+{
|
||||
+ switch (base->type) {
|
||||
+ case TC_SETUP_QDISC_MQPRIO:
|
||||
+ struct tc_mqprio_caps *caps = base->caps;
|
||||
+
|
||||
+ caps->validate_queue_counts = true;
|
||||
+ return 0;
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+}
|
||||
+static int mv88e6xxx_port_setup_tc(struct dsa_switch *ds, int port,
|
||||
+ enum tc_setup_type type,
|
||||
+ void *type_data)
|
||||
+{
|
||||
+ struct mv88e6xxx_chip *chip = ds->priv;
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case TC_QUERY_CAPS:
|
||||
+ return mv88e6xxx_qos_query_caps(type_data);
|
||||
+ case TC_SETUP_QDISC_MQPRIO:
|
||||
+ return mv88e6xxx_qos_port_mqprio(chip, port, type_data);
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.get_tag_protocol = mv88e6xxx_get_tag_protocol,
|
||||
.change_tag_protocol = mv88e6xxx_change_tag_protocol,
|
||||
@@ -7170,6 +7233,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.crosschip_lag_leave = mv88e6xxx_crosschip_lag_leave,
|
||||
.port_add_etype_prio = mv88e6xxx_port_add_etype_prio,
|
||||
.port_del_etype_prio = mv88e6xxx_port_del_etype_prio,
|
||||
+ .port_setup_tc = mv88e6xxx_port_setup_tc,
|
||||
};
|
||||
|
||||
static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
|
||||
@@ -7195,6 +7259,12 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
|
||||
*/
|
||||
ds->num_lag_ids = mv88e6xxx_has_lag(chip) ? 16 : 0;
|
||||
|
||||
+ /* Even though older chips only have 4 queues, we always have
|
||||
+ * 3 bits of priority information in the DSA tag, which is how
|
||||
+ * we indirectly address the queues.
|
||||
+ */
|
||||
+ ds->num_tx_queues = 8;
|
||||
+
|
||||
dev_set_drvdata(dev, ds);
|
||||
|
||||
return dsa_register_switch(ds);
|
||||
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
|
||||
index 284bc65d1f63..782cad614573 100644
|
||||
--- a/net/dsa/tag_dsa.c
|
||||
+++ b/net/dsa/tag_dsa.c
|
||||
@@ -180,8 +180,10 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
|
||||
}
|
||||
} else {
|
||||
u16 vid;
|
||||
+ u8 tc;
|
||||
|
||||
vid = br_dev ? MV88E6XXX_VID_BRIDGED : MV88E6XXX_VID_STANDALONE;
|
||||
+ tc = netdev_txq_to_tc(dev, skb_get_queue_mapping(skb));
|
||||
|
||||
skb_push(skb, DSA_HLEN + extra);
|
||||
dsa_alloc_etype_header(skb, DSA_HLEN + extra);
|
||||
@@ -191,7 +193,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
dsa_header[0] = (cmd << 6) | tag_dev;
|
||||
dsa_header[1] = tag_port << 3;
|
||||
- dsa_header[2] = vid >> 8;
|
||||
+ dsa_header[2] = (tc << 5) | (vid >> 8);
|
||||
dsa_header[3] = vid & 0xff;
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
From f2d4ff12c7a0e644cbeac6675b755fb4a87b362a Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Wed, 29 May 2024 13:20:41 +0200
|
||||
Subject: [PATCH 33/35] net: dsa: mv88e6xxx: Use VLAN prio over IP when both
|
||||
are available
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Switch the priority sourcing precdence to prefer VLAN PCP over IP
|
||||
DSCP, when both are available.
|
||||
|
||||
Ever since the initial commit of this driver, IP priority (DSCP/TOS)
|
||||
has instead taken precedence over VLAN priority (PCP) when determining
|
||||
a packet's initial queue and frame priority (Qpri/Fpri). There are two
|
||||
main reasons for choosing the new default:
|
||||
|
||||
1. It matches the chip's hardware default settings and thus follows
|
||||
the principle of least astonishment.
|
||||
|
||||
2. In the typical case where a packet initially ingresses a network on
|
||||
a UNI port, the first switch will have the most context available
|
||||
about that flow; and is therefore entrusted to determine the
|
||||
packet's priority. As the packet then moves through the network
|
||||
core over trusted VLAN trunks, the packet should keep its original
|
||||
priority, independent of what inner protocol fields may indicate.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 0c6ab36a6905..305abb33b0c6 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -3381,9 +3381,13 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
||||
|
||||
/* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
|
||||
* disable Header mode, enable IGMP/MLD snooping, disable VLAN
|
||||
- * tunneling, determine priority by looking at 802.1p and IP
|
||||
- * priority fields (IP prio has precedence), and set STP state
|
||||
- * to Forwarding.
|
||||
+ * tunneling, and set STP state to Forwarding.
|
||||
+ *
|
||||
+ * Use the following sources of information, in order of
|
||||
+ * precedence, to determine a packet's initial Qpri/Fpri:
|
||||
+ * 1. VLAN PCP field, if available
|
||||
+ * 2. IPv4/6 DSCP field, if available
|
||||
+ * 3. Ingress port defaults
|
||||
*
|
||||
* If this is the CPU link, use DSA or EDSA tagging depending
|
||||
* on which tagging mode was configured.
|
||||
@@ -3394,6 +3398,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
||||
* forwarding of unknown unicasts and multicasts.
|
||||
*/
|
||||
reg = MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
|
||||
+ MV88E6XXX_PORT_CTL0_TAG_IF_BOTH |
|
||||
MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
|
||||
/* Forward any IPv4 IGMP or IPv6 MLD frames received
|
||||
* by a USER port to the CPU port to allow snooping.
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
From ceaaa4f44f9b3ec82c4e0a24c2322aae58fa3aa0 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Wed, 6 Nov 2024 15:39:33 +0100
|
||||
Subject: [PATCH 34/35] net: dsa: mb88e6xxx: use EOPNOTSUPP for unsupported
|
||||
flags
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Make sure to return correct error code for unsupported flags, and
|
||||
propagate any error.
|
||||
|
||||
Follow-up to a5cf5c0
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/leds.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/leds.c b/drivers/net/dsa/mv88e6xxx/leds.c
|
||||
index b2a55d96b506..fe1ed3ed2a8a 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/leds.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/leds.c
|
||||
@@ -99,7 +99,7 @@ static int mv88e6393x_led_flags_to_mode(struct mv88e6xxx_led *led, unsigned long
|
||||
return i;
|
||||
}
|
||||
|
||||
- return -EINVAL;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int mv88e6393x_led_mode_to_flags(struct mv88e6xxx_led *led, u8 mode,
|
||||
@@ -216,6 +216,9 @@ static int mv88e6393x_led_hw_control_set(struct mv88e6xxx_led *led,
|
||||
{
|
||||
int mode = mv88e6393x_led_flags_to_mode(led, flags);
|
||||
|
||||
+ if (mode < 0)
|
||||
+ return mode;
|
||||
+
|
||||
return mv88e6393x_led_set(led, mode);
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
From ab93e65511ee508d1b637e4ad0dc6dcddd2c48dc Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 26 Nov 2024 19:45:59 +0100
|
||||
Subject: [PATCH 35/35] net: dsa: mv88e6xxx: Trap locally terminated VLANs
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Before this change, in a setup like the following, packets assigned to
|
||||
VLAN 10 were forwarded between the switch ports, even though the
|
||||
configuration dictates that they should only be locally terminated.
|
||||
|
||||
ip link add dev br0 up type bridge vlan_filtering 1
|
||||
ip link set dev swp1 master br0
|
||||
ip link set dev swp2 master br0
|
||||
ip link add dev swp1.10 link swp1 up type vlan id 10
|
||||
ip link add dev swp2.10 link swp2 up type vlan id 10
|
||||
|
||||
swp1.10 br0 swp2.10
|
||||
\ / \ /
|
||||
swp1 swp2
|
||||
|
||||
Therefore, make sure that VLANs that are added to the VTU to terminate
|
||||
a VLAN upper interface, rather than to offload bridge VLANs, are
|
||||
marked as policy entries. As the VTU policy of user ports is already
|
||||
set to TRAP (to ensure proper standalone port operation), this will
|
||||
cause all packets assigned to these VLANs to properly terminated.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/dsa/mv88e6xxx/chip.c | 33 ++++++++++++++++++--------------
|
||||
include/net/switchdev.h | 4 ++++
|
||||
net/dsa/slave.c | 4 ++++
|
||||
3 files changed, 27 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
index 305abb33b0c6..259eec1a3a1d 100644
|
||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||
@@ -2610,7 +2610,7 @@ static int mv88e6xxx_port_broadcast_sync(struct mv88e6xxx_chip *chip, int port,
|
||||
}
|
||||
|
||||
static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
|
||||
- u16 vid, u8 member, bool warn)
|
||||
+ u16 vid, u8 member, bool warn, bool policy)
|
||||
{
|
||||
const u8 non_member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER;
|
||||
struct mv88e6xxx_vtu_entry vlan;
|
||||
@@ -2622,9 +2622,7 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
|
||||
|
||||
if (!vlan.valid) {
|
||||
memset(&vlan, 0, sizeof(vlan));
|
||||
-
|
||||
- if (vid == MV88E6XXX_VID_STANDALONE)
|
||||
- vlan.policy = true;
|
||||
+ vlan.policy = policy;
|
||||
|
||||
err = mv88e6xxx_atu_new(chip, &vlan.fid);
|
||||
if (err)
|
||||
@@ -2647,6 +2645,9 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
|
||||
if (err)
|
||||
return err;
|
||||
} else if (vlan.member[port] != member) {
|
||||
+ if (vlan.policy != policy)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
vlan.member[port] = member;
|
||||
|
||||
err = mv88e6xxx_vtu_loadpurge(chip, &vlan);
|
||||
@@ -2693,7 +2694,8 @@ static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
|
||||
- err = mv88e6xxx_port_vlan_join(chip, port, vlan->vid, member, warn);
|
||||
+ err = mv88e6xxx_port_vlan_join(chip, port, vlan->vid, member, warn,
|
||||
+ vlan->from_upper);
|
||||
if (err) {
|
||||
dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port,
|
||||
vlan->vid, untagged ? 'u' : 't');
|
||||
@@ -3433,14 +3435,17 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- /* On chips that support it, set all downstream DSA ports'
|
||||
- * VLAN policy to TRAP. In combination with loading
|
||||
- * MV88E6XXX_VID_STANDALONE as a policy entry in the VTU, this
|
||||
- * provides a better isolation barrier between standalone
|
||||
- * ports, as the ATU is bypassed on any intermediate switches
|
||||
- * between the incoming port and the CPU.
|
||||
+ /* On chips that support it, set all downstream DSA and user
|
||||
+ * ports' VLAN policy to TRAP. for downstream DSA ports, in
|
||||
+ * combination with loading MV88E6XXX_VID_STANDALONE as a
|
||||
+ * policy entry in the VTU, this provides a better isolation
|
||||
+ * barrier between standalone ports, as the ATU is bypassed on
|
||||
+ * any intermediate switches between the incoming port and the
|
||||
+ * CPU. On user ports we need it to support stacked VLAN
|
||||
+ * uppers on ports that are simultaneously attached to a VLAN
|
||||
+ * filtering bridge.
|
||||
*/
|
||||
- if (dsa_is_downstream_port(ds, port) &&
|
||||
+ if ((dsa_is_downstream_port(ds, port) || dsa_is_user_port(ds, port)) &&
|
||||
chip->info->ops->port_set_policy) {
|
||||
err = chip->info->ops->port_set_policy(chip, port,
|
||||
MV88E6XXX_POLICY_MAPPING_VTU,
|
||||
@@ -3470,7 +3475,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
||||
*/
|
||||
err = mv88e6xxx_port_vlan_join(chip, port, MV88E6XXX_VID_STANDALONE,
|
||||
MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED,
|
||||
- false);
|
||||
+ false, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -3484,7 +3489,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
||||
*/
|
||||
err = mv88e6xxx_port_vlan_join(chip, port, MV88E6XXX_VID_BRIDGED,
|
||||
MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED,
|
||||
- false);
|
||||
+ false, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
|
||||
index 8346b0d29542..764cd3dd4645 100644
|
||||
--- a/include/net/switchdev.h
|
||||
+++ b/include/net/switchdev.h
|
||||
@@ -104,6 +104,10 @@ struct switchdev_obj_port_vlan {
|
||||
* Entries with BRIDGE_VLAN_INFO_BRENTRY unset are not notified at all.
|
||||
*/
|
||||
bool changed;
|
||||
+
|
||||
+ /* If set, this VLAN object stems from an upper interface
|
||||
+ * being stacked on/removed from the original device. */
|
||||
+ bool from_upper;
|
||||
};
|
||||
|
||||
#define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \
|
||||
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
|
||||
index 18d913bcd180..b45c2ac1f1f0 100644
|
||||
--- a/net/dsa/slave.c
|
||||
+++ b/net/dsa/slave.c
|
||||
@@ -1762,6 +1762,8 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
|
||||
.vid = vid,
|
||||
/* This API only allows programming tagged, non-PVID VIDs */
|
||||
.flags = 0,
|
||||
+
|
||||
+ .from_upper = true,
|
||||
};
|
||||
struct netlink_ext_ack extack = {0};
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
@@ -1836,6 +1838,8 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
|
||||
.vid = vid,
|
||||
/* This API only allows programming tagged, non-PVID VIDs */
|
||||
.flags = 0,
|
||||
+
|
||||
+ .from_upper = true,
|
||||
};
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
struct netdev_hw_addr *ha;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
+45
-27
@@ -1,26 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
KDIR=$1
|
||||
KTAG=$2
|
||||
PDIR=$3
|
||||
#!/bin/bash
|
||||
|
||||
usage()
|
||||
{
|
||||
cat <<EOF
|
||||
usage: $0 <kernel-dir> [<kernel-tag>] [<patch-dir>]
|
||||
usage: $0 -k <kernel-dir> -o <old-version> [-t <kernel-tag>] [-p <patch-dir>] [-d <defconfig-dir>]
|
||||
|
||||
Synchronize patches directory with changes from a GIT versioned kernel
|
||||
tree.
|
||||
|
||||
<kernel-dir> Path to kernel tree.
|
||||
-k <kernel-dir> Path to kernel tree.
|
||||
-o <old-version> Version to be replaced by new kernel version.
|
||||
-t <kernel-tag> Base tag from which to generate patches. Default: "v"
|
||||
followed by the value of BR2_LINUX_KERNEL_VERSION in
|
||||
the current configuration.
|
||||
-p <patch-dir> Path to kernel patches directory. Default: the value of
|
||||
BR2_EXTERNAL_INFIX_PATH in the current configuration,
|
||||
followed by "/patches/linux/<kernel-tag>".
|
||||
-d <defconfig-dir> Path to defconfig. Default the value of BR2_EXTERNAL_INFIX_PATH
|
||||
in the current configuration, followed by "/configs".
|
||||
|
||||
<kernel-tag> Base tag from which to generate patches. Default: "v"
|
||||
followed by the value of BR2_LINUX_KERNEL_VERSION in
|
||||
the current configuration.
|
||||
|
||||
<patch-dir> Path to kernel patches directory. Default: the value of
|
||||
BR2_EXTERNAL_INFIX_PATH in the current configuration,
|
||||
followed by "/patches/linux".
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -36,33 +34,53 @@ if [ $# -lt 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ "$KTAG" ]; then
|
||||
ixkver=$(getconfig BR2_LINUX_KERNEL_VERSION)
|
||||
[ "$ixkver" ] && KTAG="v$ixkver"
|
||||
while getopts "k:o:p:d:t:" flag; do
|
||||
case "${flag}" in
|
||||
k) KERNEL_DIR=${OPTARG};;
|
||||
t) KERNEL_TAG=${OPTARG};;
|
||||
o) OLD_VER=${OPTARG};;
|
||||
p) PATCH_DIR=${OPTARG};;
|
||||
d) DEFCONFIG_DIR=${OPTARG};;
|
||||
*) exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ! [ "$KERNEL_TAG" ]; then
|
||||
ixkver=$(getconfig BR2_LINUX_KERNEL_VERSION)
|
||||
[ "$ixkver" ] && KERNEL_TAG="v$ixkver"
|
||||
else
|
||||
ixkver=${KTAG#v}
|
||||
ixkver=${KERNEL_TAG#v}
|
||||
fi
|
||||
|
||||
if ! [ "$KTAG" ]; then
|
||||
if ! [ "$KERNEL_TAG" ]; then
|
||||
echo "Kernel tag was not supplied, and could not be inferred" >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ "$PDIR" ]; then
|
||||
NEW_VER=${KERNEL_TAG#v}
|
||||
|
||||
if ! [ "$PATCH_DIR" ]; then
|
||||
ixdir=$(getconfig BR2_EXTERNAL_INFIX_PATH)
|
||||
[ "$ixdir" ] && PDIR="$ixdir/patches/linux/$ixkver"
|
||||
[ "$ixdir" ] && PATCH_DIR="$ixdir/patches/linux/$NEW_VER"
|
||||
fi
|
||||
|
||||
if ! [ "$PDIR" ]; then
|
||||
if ! [ "$PATCH_DIR" ]; then
|
||||
echo "Patch directory was not supplied, and could not be inferred" >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
KDIR=$(readlink -f $KDIR)
|
||||
PDIR=$(readlink -f $PDIR)
|
||||
if ! [ "$DEFCONFIG_DIR" ]; then
|
||||
ixdir=$(getconfig BR2_EXTERNAL_INFIX_PATH)
|
||||
DEFCONFIG_DIR=$ixdir/configs
|
||||
fi
|
||||
|
||||
git ls-files --error-unmatch $PDIR 1>/dev/null 2>&1 && git -C $PDIR rm *.patch
|
||||
git -C $KDIR format-patch -o $PDIR $KTAG..HEAD
|
||||
git -C $PDIR add *.patch
|
||||
KERNEL_DIR=$(readlink -f $KERNEL_DIR)
|
||||
PATCH_DIR=$(readlink -f $PATCH_DIR)
|
||||
DEFCONFIG_DIR=$(readlink -f $DEFCONFIG_DIR)
|
||||
|
||||
git ls-files --error-unmatch $PATCH_DIR 1>/dev/null 2>&1 && git -C $PATCH_DIR rm *.patch
|
||||
git -C $KERNEL_DIR format-patch -o $PATCH_DIR $KERNEL_TAG..HEAD
|
||||
git -C $PATCH_DIR add *.patch
|
||||
find "$DEFCONFIG_DIR" -name "*_defconfig" -exec sed -i "s/BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=\"$OLD_VER\"/BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=\"$NEW_VER\"/" {} \;
|
||||
|
||||
Reference in New Issue
Block a user