* [PATCH net 05/11] mptcp: pm: ADD_ADDR rtx: free sk if last
From: Matthieu Baerts (NGI0) @ 2026-05-05 15:00 UTC (permalink / raw)
To: Mat Martineau, Geliang Tang, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Christoph Paasch
Cc: netdev, mptcp, linux-kernel, Matthieu Baerts (NGI0), stable
In-Reply-To: <20260505-net-mptcp-pm-fixes-7-1-rc3-v1-0-fca8091060a4@kernel.org>
When an ADD_ADDR is retransmitted, the sk is held in sk_reset_timer(),
and released at the end.
If at that moment, it was the last reference being held, the sk would
not be freed. sock_put() should then be called instead of __sock_put().
But that's not enough: if it is the last reference, sock_put() will call
sk_free(), which will end up calling sk_stop_timer_sync() on the same
timer, and waiting indefinitely to finish. So it is needed to mark that
the timer is done at the end of the timer handler when it has not been
rescheduled, not to call sk_stop_timer_sync() on "itself".
Fixes: 00cfd77b9063 ("mptcp: retransmit ADD_ADDR when timeout")
Cc: stable@vger.kernel.org
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
net/mptcp/pm.c | 30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 2a01bf1b5bfd..8899327e59a1 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -16,6 +16,7 @@ struct mptcp_pm_add_entry {
struct list_head list;
struct mptcp_addr_info addr;
u8 retrans_times;
+ bool timer_done;
struct timer_list add_timer;
struct mptcp_sock *sock;
struct rcu_head rcu;
@@ -327,22 +328,22 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
add_timer);
struct mptcp_sock *msk = entry->sock;
struct sock *sk = (struct sock *)msk;
- unsigned int timeout;
+ unsigned int timeout = 0;
pr_debug("msk=%p\n", msk);
- if (unlikely(inet_sk_state_load(sk) == TCP_CLOSE))
- goto exit;
-
bh_lock_sock(sk);
+ if (unlikely(inet_sk_state_load(sk) == TCP_CLOSE))
+ goto out;
+
if (sock_owned_by_user(sk)) {
/* Try again later. */
- sk_reset_timer(sk, timer, jiffies + HZ / 20);
+ timeout = HZ / 20;
goto out;
}
if (mptcp_pm_should_add_signal_addr(msk)) {
- sk_reset_timer(sk, timer, jiffies + TCP_RTO_MAX / 8);
+ timeout = TCP_RTO_MAX / 8;
goto out;
}
@@ -360,8 +361,9 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
}
if (entry->retrans_times < ADD_ADDR_RETRANS_MAX)
- sk_reset_timer(sk, timer,
- jiffies + (timeout << entry->retrans_times));
+ timeout <<= entry->retrans_times;
+ else
+ timeout = 0;
spin_unlock_bh(&msk->pm.lock);
@@ -369,9 +371,13 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
mptcp_pm_subflow_established(msk);
out:
+ if (timeout)
+ sk_reset_timer(sk, timer, jiffies + timeout);
+ else
+ /* if sock_put calls sk_free: avoid waiting for this timer */
+ entry->timer_done = true;
bh_unlock_sock(sk);
-exit:
- __sock_put(sk);
+ sock_put(sk);
}
struct mptcp_pm_add_entry *
@@ -434,6 +440,7 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0);
reset_timer:
+ add_entry->timer_done = false;
timeout = mptcp_adjust_add_addr_timeout(msk);
if (timeout)
sk_reset_timer(sk, &add_entry->add_timer, jiffies + timeout);
@@ -454,7 +461,8 @@ static void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
spin_unlock_bh(&msk->pm.lock);
list_for_each_entry_safe(entry, tmp, &free_list, list) {
- sk_stop_timer_sync(sk, &entry->add_timer);
+ if (!entry->timer_done)
+ sk_stop_timer_sync(sk, &entry->add_timer);
kfree_rcu(entry, rcu);
}
}
--
2.53.0
^ permalink raw reply related
* [PATCH net 04/11] mptcp: pm: ADD_ADDR rtx: always decrease sk refcount
From: Matthieu Baerts (NGI0) @ 2026-05-05 15:00 UTC (permalink / raw)
To: Mat Martineau, Geliang Tang, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Christoph Paasch
Cc: netdev, mptcp, linux-kernel, Matthieu Baerts (NGI0), stable
In-Reply-To: <20260505-net-mptcp-pm-fixes-7-1-rc3-v1-0-fca8091060a4@kernel.org>
When an ADD_ADDR is retransmitted, the sk is held in sk_reset_timer().
It should then be released in all cases at the end.
Some (unlikely) checks were returning directly instead of calling
sock_put() to decrease the refcount. Jump to a new 'exit' label to call
__sock_put() (which will become sock_put() in the next commit) to fix
this potential leak.
While at it, drop the '!msk' check which cannot happen because it is
never reset, and explicitly mark the remaining one as "unlikely".
Fixes: 00cfd77b9063 ("mptcp: retransmit ADD_ADDR when timeout")
Cc: stable@vger.kernel.org
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
net/mptcp/pm.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 3912128d9b86..2a01bf1b5bfd 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -331,11 +331,8 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
pr_debug("msk=%p\n", msk);
- if (!msk)
- return;
-
- if (inet_sk_state_load(sk) == TCP_CLOSE)
- return;
+ if (unlikely(inet_sk_state_load(sk) == TCP_CLOSE))
+ goto exit;
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
@@ -373,6 +370,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
out:
bh_unlock_sock(sk);
+exit:
__sock_put(sk);
}
--
2.53.0
^ permalink raw reply related
* [PATCH net 03/11] mptcp: pm: ADD_ADDR rtx: fix potential data-race
From: Matthieu Baerts (NGI0) @ 2026-05-05 15:00 UTC (permalink / raw)
To: Mat Martineau, Geliang Tang, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Christoph Paasch
Cc: netdev, mptcp, linux-kernel, Matthieu Baerts (NGI0), stable
In-Reply-To: <20260505-net-mptcp-pm-fixes-7-1-rc3-v1-0-fca8091060a4@kernel.org>
This mptcp_pm_add_timer() helper is executed as a timer callback in
softirq context. To avoid any data races, the socket lock needs to be
held with bh_lock_sock().
If the socket is in use, retry again soon after, similar to what is done
with the keepalive timer.
Fixes: 00cfd77b9063 ("mptcp: retransmit ADD_ADDR when timeout")
Cc: stable@vger.kernel.org
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
net/mptcp/pm.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 5056eb8db24e..3912128d9b86 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -337,6 +337,13 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
if (inet_sk_state_load(sk) == TCP_CLOSE)
return;
+ bh_lock_sock(sk);
+ if (sock_owned_by_user(sk)) {
+ /* Try again later. */
+ sk_reset_timer(sk, timer, jiffies + HZ / 20);
+ goto out;
+ }
+
if (mptcp_pm_should_add_signal_addr(msk)) {
sk_reset_timer(sk, timer, jiffies + TCP_RTO_MAX / 8);
goto out;
@@ -365,6 +372,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
mptcp_pm_subflow_established(msk);
out:
+ bh_unlock_sock(sk);
__sock_put(sk);
}
--
2.53.0
^ permalink raw reply related
* [PATCH net 02/11] mptcp: pm: ADD_ADDR rtx: allow ID 0
From: Matthieu Baerts (NGI0) @ 2026-05-05 15:00 UTC (permalink / raw)
To: Mat Martineau, Geliang Tang, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Christoph Paasch
Cc: netdev, mptcp, linux-kernel, Matthieu Baerts (NGI0), stable
In-Reply-To: <20260505-net-mptcp-pm-fixes-7-1-rc3-v1-0-fca8091060a4@kernel.org>
ADD_ADDR can be sent for the ID 0, which corresponds to the local
address and port linked to the initial subflow.
Indeed, this address could be removed, and re-added later on, e.g. what
is done in the "delete re-add signal" MPTCP Join selftests. So no reason
to ignore it.
Fixes: 00cfd77b9063 ("mptcp: retransmit ADD_ADDR when timeout")
Cc: stable@vger.kernel.org
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
net/mptcp/pm.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 57a456690406..5056eb8db24e 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -337,9 +337,6 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
if (inet_sk_state_load(sk) == TCP_CLOSE)
return;
- if (!entry->addr.id)
- return;
-
if (mptcp_pm_should_add_signal_addr(msk)) {
sk_reset_timer(sk, timer, jiffies + TCP_RTO_MAX / 8);
goto out;
--
2.53.0
^ permalink raw reply related
* [PATCH net 01/11] mptcp: pm: kernel: correctly retransmit ADD_ADDR ID 0
From: Matthieu Baerts (NGI0) @ 2026-05-05 15:00 UTC (permalink / raw)
To: Mat Martineau, Geliang Tang, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Christoph Paasch
Cc: netdev, mptcp, linux-kernel, Matthieu Baerts (NGI0), stable
In-Reply-To: <20260505-net-mptcp-pm-fixes-7-1-rc3-v1-0-fca8091060a4@kernel.org>
When adding the ADD_ADDR to the list, the address including the IP, port
and ID are copied. On the other hand, when the endpoint corresponds to
the one from the initial subflow, the ID is set to 0, as specified by
the MPTCP protocol.
The issue is that the ID was reset after having copied the ID in the
ADD_ADDR entry. So the retransmission was done, but using a different ID
than the initial one.
Fixes: 8b8ed1b429f8 ("mptcp: pm: reuse ID 0 after delete and re-add")
Cc: stable@vger.kernel.org
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
net/mptcp/pm_kernel.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c
index c9f1e5af3cd3..fc818b63752e 100644
--- a/net/mptcp/pm_kernel.c
+++ b/net/mptcp/pm_kernel.c
@@ -347,6 +347,8 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
/* check first for announce */
if (msk->pm.add_addr_signaled < endp_signal_max) {
+ u8 endp_id;
+
/* due to racing events on both ends we can reach here while
* previous add address is still running: if we invoke now
* mptcp_pm_announce_addr(), that will fail and the
@@ -360,19 +362,20 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
if (!select_signal_address(pernet, msk, &local))
goto subflow;
+ /* Special case for ID0: set the correct ID */
+ endp_id = local.addr.id;
+ if (endp_id == msk->mpc_endpoint_id)
+ local.addr.id = 0;
+
/* If the alloc fails, we are on memory pressure, not worth
* continuing, and trying to create subflows.
*/
if (!mptcp_pm_alloc_anno_list(msk, &local.addr))
return;
- __clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
+ __clear_bit(endp_id, msk->pm.id_avail_bitmap);
msk->pm.add_addr_signaled++;
- /* Special case for ID0: set the correct ID */
- if (local.addr.id == msk->mpc_endpoint_id)
- local.addr.id = 0;
-
mptcp_pm_announce_addr(msk, &local.addr, false);
mptcp_pm_addr_send_ack(msk);
--
2.53.0
^ permalink raw reply related
* [PATCH net 00/11] mptcp: pm: misc. fixes for v7.1-rc3
From: Matthieu Baerts (NGI0) @ 2026-05-05 15:00 UTC (permalink / raw)
To: Mat Martineau, Geliang Tang, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Christoph Paasch
Cc: netdev, mptcp, linux-kernel, Matthieu Baerts (NGI0), stable,
Shuah Khan, linux-kselftest
Here are various fixes, mainly related to ADD_ADDRs:
- Patch 1: save ADD_ADDR for rtx with ID0 when needed. A fix for v6.1.
- Patch 2: remove unneeded exception for ID 0. A fix for v5.10.
- Patches 3-5: fix potential data-race and leaks during ADD_ADDR rtx. A
fix for v5.10.
- Patch 6: resched blocked ADD_ADDR rtx after a more appropriated
timeout, not after 15 seconds. A fix for v5.10.
- Patch 7: skip inactive subflows when when looking at the max RTO. A
fix for v6.18.
- Patch 8: avoid iterating over all subflows when there is no need to. A
fix for v6.18.
- Patch 9: skip closed subflows when looking at sending MP_PRIO. A fix
for v5.17.
- Patch 10: properly catch errors when using check_output() in the
selftests. A fix for v6.9.
- Patch 11: skip the 'unknown' flag test when 'ip mptcp' is used. A fix
for v6.10.
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
Matthieu Baerts (NGI0) (11):
mptcp: pm: kernel: correctly retransmit ADD_ADDR ID 0
mptcp: pm: ADD_ADDR rtx: allow ID 0
mptcp: pm: ADD_ADDR rtx: fix potential data-race
mptcp: pm: ADD_ADDR rtx: always decrease sk refcount
mptcp: pm: ADD_ADDR rtx: free sk if last
mptcp: pm: ADD_ADDR rtx: resched blocked ADD_ADDR quicker
mptcp: pm: ADD_ADDR rtx: skip inactive subflows
mptcp: pm: ADD_ADDR rtx: return early if no retrans
mptcp: pm: prio: skip closed subflows
selftests: mptcp: check output: catch cmd errors
selftests: mptcp: pm: restrict 'unknown' check to pm_nl_ctl
net/mptcp/pm.c | 62 +++++++++++++++++--------
net/mptcp/pm_kernel.c | 13 ++++--
tools/testing/selftests/net/mptcp/mptcp_lib.sh | 16 ++++---
tools/testing/selftests/net/mptcp/pm_netlink.sh | 20 +++++---
4 files changed, 73 insertions(+), 38 deletions(-)
---
base-commit: 07d99587396024932e02474c3a5bede71d108454
change-id: 20260504-net-mptcp-pm-fixes-7-1-rc3-e4d81787300e
Best regards,
--
Matthieu Baerts (NGI0) <matttbe@kernel.org>
^ permalink raw reply
* [PATCH v2] net: dsa: realtek: rtl8365mb: add support for RTL8367SB
From: Mieczyslaw Nalewaj @ 2026-05-05 14:17 UTC (permalink / raw)
To: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Alvin Šipraga,
Yury Norov, Rasmus Villemoes, Russell King, netdev
In-Reply-To: <05921e1f-693b-4322-a762-c8f03c386a78.ref@yahoo.com>
Add chip info entry for the Realtek RTL8367SB switch. This device has
chip ID 0x6367 and version 0x0010. It exposes two external interfaces:
port 6 supports SGMII and HSGMII, while port 7 supports MII, TMII,
RMII and RGMII. Use the existing 8365MB-VC jam table for initialization.
Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
---
drivers/net/dsa/realtek/rtl8365mb.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index 073f12ca8028..84d6fdb94a96 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -545,6 +545,18 @@ static const struct rtl8365mb_chip_info
.jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc),
},
{
+ .name = "RTL8367SB",
+ .chip_id = 0x6367,
+ .chip_ver = 0x0010,
+ .extints = {
+ { 6, 1, PHY_INTF(SGMII) | PHY_INTF(HSGMII) },
+ { 7, 2, PHY_INTF(MII) | PHY_INTF(TMII) |
+ PHY_INTF(RMII) | PHY_INTF(RGMII) },
+ },
+ .jam_table = rtl8365mb_init_jam_8365mb_vc,
+ .jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc),
+ },
+ {
.name = "RTL8367RB-VB",
.chip_id = 0x6367,
.chip_ver = 0x0020,
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v5 14/16] wifi: ath12k: Switch to generic PAS TZ APIs
From: Jeff Johnson @ 2026-05-05 14:50 UTC (permalink / raw)
To: Sumit Garg, andersson, konradybcio, Sowmiya Sree Elavalagan
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, robh, krzk+dt,
conor+dt, robin.clark, sean, akhilpo, lumag, abhinav.kumar,
jesszhan0024, marijn.suijten, airlied, simona, vikash.garodia,
dikshita.agarwal, bod, mchehab, elder, andrew+netdev, davem,
edumazet, kuba, pabeni, jjohnson, mathieu.poirier,
trilokkumar.soni, mukesh.ojha, pavan.kondeti, jorge.ramirez,
tonyh, vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, linux-kernel, Sumit Garg
In-Reply-To: <3bfdc11c-115f-45ab-b0ab-75ad88dc6f31@oss.qualcomm.com>
On 5/5/2026 7:27 AM, Jeff Johnson wrote:
> On 5/4/2026 6:06 AM, Sumit Garg wrote:
>> @@ -485,9 +485,9 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab, bool is_suspend)
>> pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) |
>> ATH12K_AHB_UPD_SWID;
>> /* Release the firmware */
>> - ret = qcom_scm_pas_shutdown(pasid);
>> + ret = qcom_pas_shutdown(pasid);
>> if (ret)
>> - ath12k_err(ab, "scm pas shutdown failed for userPD%d\n",
>> + ath12k_err(ab, "pas shutdown failed for userPD%d: %d\n",
>> ab_ahb->userpd_id);
>
> at some point the "ret" param was dropped, and this now generates build warnings
The 'ret' param was dropped by:
8fb66931fe31 ("wifi: ath12k: Enable IPQ5424 WiFi device support")
Not sure if that was on purpose or accidental. Sowmiya?
- if (ret)
- ath12k_err(ab, "scm pas shutdown failed for userPD%d: %d\n",
- ab_ahb->userpd_id, ret);
...
+ if (ret)
+ ath12k_err(ab, "scm pas shutdown failed for userPD%d\n",
+ ab_ahb->userpd_id);
^ permalink raw reply
* [PATCH nf-next 4/4] selftests: netfilter: nft_flowtable.sh: Add IPv4 over IPv6 flowtable selftest
From: Lorenzo Bianconi @ 2026-05-05 14:49 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno, Simon Horman, David Ahern,
Ido Schimmel, Pablo Neira Ayuso, Florian Westphal, Phil Sutter,
Shuah Khan
Cc: linux-arm-kernel, linux-mediatek, netdev, netfilter-devel,
coreteam, linux-kselftest, Lorenzo Bianconi
In-Reply-To: <20260505-b4-flowtable-sw-accel-ip6ip-v1-0-9ac39ccc9ea9@kernel.org>
Similar to IPIP and IP6IP6, introduce specific selftest for IPv4 over IPv6
flowtable sw acceleration in nft_flowtable.sh
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../selftests/net/netfilter/nft_flowtable.sh | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/tools/testing/selftests/net/netfilter/nft_flowtable.sh b/tools/testing/selftests/net/netfilter/nft_flowtable.sh
index 7a34ef468975..d9995549f8a6 100755
--- a/tools/testing/selftests/net/netfilter/nft_flowtable.sh
+++ b/tools/testing/selftests/net/netfilter/nft_flowtable.sh
@@ -594,7 +594,9 @@ ip netns exec "$nsr1" sysctl net.ipv4.conf.tun0.forwarding=1 > /dev/null
ip -net "$nsr1" link add name tun6 type ip6tnl local fee1:2::1 remote fee1:2::2
ip -net "$nsr1" link set tun6 up
+ip -net "$nsr1" addr add 192.168.210.1/24 dev tun6
ip -net "$nsr1" addr add fee1:3::1/64 dev tun6 nodad
+ip netns exec "$nsr1" sysctl net.ipv4.conf.tun6.forwarding=1 > /dev/null
ip -net "$nsr2" link add name tun0 type ipip local 192.168.10.2 remote 192.168.10.1
ip -net "$nsr2" link set tun0 up
@@ -603,7 +605,9 @@ ip netns exec "$nsr2" sysctl net.ipv4.conf.tun0.forwarding=1 > /dev/null
ip -net "$nsr2" link add name tun6 type ip6tnl local fee1:2::2 remote fee1:2::1 || ret=1
ip -net "$nsr2" link set tun6 up
+ip -net "$nsr2" addr add 192.168.210.2/24 dev tun6
ip -net "$nsr2" addr add fee1:3::2/64 dev tun6 nodad
+ip netns exec "$nsr2" sysctl net.ipv4.conf.tun6.forwarding=1 > /dev/null
ip -net "$nsr1" route change default via 192.168.100.2
ip -net "$nsr2" route change default via 192.168.100.1
@@ -636,6 +640,15 @@ else
ret=1
fi
+ip -net "$nsr1" route change default via 192.168.210.2
+ip -net "$nsr2" route change default via 192.168.210.1
+
+if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IP6IP4 tunnel"; then
+ echo "FAIL: flow offload for ns1/ns2 with IP6IP4 tunnel" 1>&2
+ ip netns exec "$nsr1" nft list ruleset
+ ret=1
+fi
+
# Create vlan tagged devices for IPIP traffic.
ip -net "$nsr1" link add link veth1 name veth1.10 type vlan id 10
ip -net "$nsr1" link set veth1.10 up
@@ -653,7 +666,9 @@ ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun0.10 a
ip -net "$nsr1" link add name tun6.10 type ip6tnl local fee1:4::1 remote fee1:4::2
ip -net "$nsr1" link set tun6.10 up
+ip -net "$nsr1" addr add 192.168.220.1/24 dev tun6.10
ip -net "$nsr1" addr add fee1:5::1/64 dev tun6.10 nodad
+ip netns exec "$nsr1" sysctl net.ipv4.conf.tun6/10.forwarding=1 > /dev/null
ip -6 -net "$nsr1" route delete default
ip -6 -net "$nsr1" route add default via fee1:5::2
ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun6.10 accept'
@@ -672,7 +687,9 @@ ip netns exec "$nsr2" sysctl net.ipv4.conf.tun0/10.forwarding=1 > /dev/null
ip -net "$nsr2" link add name tun6.10 type ip6tnl local fee1:4::2 remote fee1:4::1 || ret=1
ip -net "$nsr2" link set tun6.10 up
+ip -net "$nsr2" addr add 192.168.220.2/24 dev tun6.10
ip -net "$nsr2" addr add fee1:5::2/64 dev tun6.10 nodad
+ip netns exec "$nsr2" sysctl net.ipv4.conf.tun6/10.forwarding=1 > /dev/null
ip -6 -net "$nsr2" route delete default
ip -6 -net "$nsr2" route add default via fee1:5::1
@@ -690,6 +707,15 @@ else
ret=1
fi
+ip -net "$nsr1" route change default via 192.168.220.2
+ip -net "$nsr2" route change default via 192.168.220.1
+
+if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IP6IP4 tunnel over vlan"; then
+ echo "FAIL: flow offload for ns1/ns2 with IP6IP4 tunnel over vlan" 1>&2
+ ip netns exec "$nsr1" nft list ruleset
+ ret=1
+fi
+
# Restore the previous configuration
ip -net "$nsr1" route change default via 192.168.10.2
ip -net "$nsr2" route change default via 192.168.10.1
--
2.54.0
^ permalink raw reply related
* [PATCH nf-next 3/4] net: netfilter: Add IPv4 over IPv6 tunnel flowtable acceleration
From: Lorenzo Bianconi @ 2026-05-05 14:49 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno, Simon Horman, David Ahern,
Ido Schimmel, Pablo Neira Ayuso, Florian Westphal, Phil Sutter,
Shuah Khan
Cc: linux-arm-kernel, linux-mediatek, netdev, netfilter-devel,
coreteam, linux-kselftest, Lorenzo Bianconi
In-Reply-To: <20260505-b4-flowtable-sw-accel-ip6ip-v1-0-9ac39ccc9ea9@kernel.org>
Introduce sw flowtable acceleration for the TX/RX paths of
IPv4 over IPv6 tunnels, relying on the netfilter flowtable
infrastructure.
The feature can be tested with a forwarding scenario between two
NICs (eth0 and eth1), where an IPv4 over IPv6 tunnel is used to
reach a remote site via eth1 as the underlay device:
ETH0 -- TUN0 <==> ETH1 -- [IP network] -- TUN1 (192.168.100.2)
[IP configuration]
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:00:22:33:11:55 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.2/24 scope global eth0
valid_lft forever preferred_lft forever
7: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:11:22:33:11:55 brd ff:ff:ff:ff:ff:ff
inet6 2001:db8:2::1/64 scope global nodad
valid_lft forever preferred_lft forever
8: tun0@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
link/tunnel6 2001:db8:2::1 peer 2001:db8:2::2 permaddr ce9c:2940:7dcc::
inet 192.168.100.1/24 scope global tun0
valid_lft forever preferred_lft forever
$ ip route show
default via 192.168.100.2 dev tun0
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.2
192.168.100.0/24 dev tun0 proto kernel scope link src 192.168.100.1
$ ip -6 route show
2001:db8:2::/64 dev eth1 proto kernel metric 256 pref medium
default via 2002:db8:1::2 dev tun0 metric 1024 pref medium
$ nft list ruleset
table inet filter {
flowtable ft {
hook ingress priority filter
devices = { eth0, eth1 }
}
chain forward {
type filter hook forward priority filter; policy accept;
meta l4proto { tcp, udp } flow add @ft
}
}
When reproducing this scenario using veth interfaces, the following
results were observed:
- TCP stream received from IPv4 over IPv6 tunnel:
- net-next (baseline): ~126 Gbps
- net-next + IP6IP flowtable support: ~140 Gbps
- TCP stream transmitted to IPv4 over IPv6 tunnel:
- net-next (baseline): ~127 Gbps
- net-next + IP6IP flowtable support: ~141 Gbps
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
net/netfilter/nf_flow_table_core.c | 14 ++--
net/netfilter/nf_flow_table_ip.c | 127 +++++++++++++++++++++++++++----------
net/netfilter/nf_flow_table_path.c | 6 +-
3 files changed, 107 insertions(+), 40 deletions(-)
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index 2c4140e6f53c..53fea3da0747 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -76,9 +76,11 @@ struct flow_offload *flow_offload_alloc(struct nf_conn *ct)
}
EXPORT_SYMBOL_GPL(flow_offload_alloc);
-static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple)
+static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple,
+ u8 tun_encap_proto)
{
- if (flow_tuple->l3proto == NFPROTO_IPV6)
+ if (flow_tuple->l3proto == NFPROTO_IPV6 ||
+ tun_encap_proto == NFPROTO_IPV6)
return rt6_get_cookie(dst_rt6_info(flow_tuple->dst_cache));
return 0;
@@ -134,10 +136,14 @@ static int flow_offload_fill_route(struct flow_offload *flow,
dst_release(dst);
break;
case FLOW_OFFLOAD_XMIT_XFRM:
- case FLOW_OFFLOAD_XMIT_NEIGH:
+ case FLOW_OFFLOAD_XMIT_NEIGH: {
+ u8 encap_proto = route->tuple[!dir].in.tun.encap_proto;
+
flow_tuple->ifidx = route->tuple[dir].out.ifindex;
flow_tuple->dst_cache = dst;
- flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple);
+ flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple,
+ encap_proto);
+ }
break;
default:
WARN_ON_ONCE(1);
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 9efd76b57847..70d7b5a200e2 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -191,27 +191,27 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
break;
}
- switch (inner_proto) {
- case htons(ETH_P_IP):
- iph = (struct iphdr *)(skb_network_header(skb) + offset);
- if (ctx->tun.proto == IPPROTO_IPIP) {
+ if (ctx->tun.proto == IPPROTO_IPIP || ctx->tun.proto == IPPROTO_IPV6) {
+ switch (inner_proto) {
+ case htons(ETH_P_IP):
+ iph = (struct iphdr *)(skb_network_header(skb) +
+ offset);
tuple->tun.dst_v4.s_addr = iph->daddr;
tuple->tun.src_v4.s_addr = iph->saddr;
- tuple->tun.l3_proto = IPPROTO_IPIP;
+ tuple->tun.l3_proto = ctx->tun.proto;
tuple->tun.encap_proto = AF_INET;
- }
- break;
- case htons(ETH_P_IPV6):
- ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
- if (ctx->tun.proto == IPPROTO_IPV6) {
+ break;
+ case htons(ETH_P_IPV6):
+ ip6h = (struct ipv6hdr *)(skb_network_header(skb) +
+ offset);
tuple->tun.dst_v6 = ip6h->daddr;
tuple->tun.src_v6 = ip6h->saddr;
- tuple->tun.l3_proto = IPPROTO_IPV6;
+ tuple->tun.l3_proto = ctx->tun.proto;
tuple->tun.encap_proto = AF_INET6;
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
}
}
@@ -367,9 +367,9 @@ static bool nf_flow_ip6_tunnel_proto(struct nf_flowtable_ctx *ctx,
if (hdrlen < 0)
return false;
- if (nexthdr == IPPROTO_IPV6) {
+ if (nexthdr == IPPROTO_IPIP || nexthdr == IPPROTO_IPV6) {
ctx->tun.hdr_size = hdrlen;
- ctx->tun.proto = IPPROTO_IPV6;
+ ctx->tun.proto = nexthdr;
}
ctx->offset += ctx->tun.hdr_size;
@@ -388,6 +388,10 @@ static void nf_flow_ip_tunnel_pop(struct nf_flowtable_ctx *ctx,
skb_pull(skb, ctx->tun.hdr_size);
skb_reset_network_header(skb);
+ if (ctx->tun.proto == IPPROTO_IPIP)
+ skb->protocol = htons(ETH_P_IP);
+ else
+ skb->protocol = htons(ETH_P_IPV6);
}
static bool nf_flow_skb_encap_protocol(struct nf_flowtable_ctx *ctx,
@@ -650,18 +654,29 @@ static int nf_flow_tunnel_ip6ip6_push(struct net *net, struct sk_buff *skb,
struct in6_addr **ip6_daddr,
int encap_limit)
{
- struct ipv6hdr *ip6h = (struct ipv6hdr *)skb_network_header(skb);
- u8 hop_limit = ip6h->hop_limit, proto = IPPROTO_IPV6;
struct rtable *rt = dst_rtable(tuple->dst_cache);
- __u8 dsfield = ipv6_get_dsfield(ip6h);
+ u8 hop_limit, proto = tuple->tun.l3_proto;
struct flowi6 fl6 = {
.daddr = tuple->tun.src_v6,
.saddr = tuple->tun.dst_v6,
.flowi6_proto = proto,
};
+ struct ipv6hdr *ip6h;
+ __u8 dsfield;
int err, mtu;
u32 headroom;
+ if (tuple->tun.l3_proto == IPPROTO_IPIP) {
+ struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
+
+ dsfield = ipv4_get_dsfield(iph);
+ hop_limit = iph->ttl;
+ } else {
+ ip6h = (struct ipv6hdr *)skb_network_header(skb);
+ dsfield = ipv6_get_dsfield(ip6h);
+ hop_limit = ip6h->hop_limit;
+ }
+
err = iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6);
if (err)
return err;
@@ -697,12 +712,13 @@ static int nf_flow_tunnel_ip6ip6_push(struct net *net, struct sk_buff *skb,
hopt = skb_push(skb, ipv6_optlen(opt.ops.dst1opt));
memcpy(hopt, opt.ops.dst1opt, ipv6_optlen(opt.ops.dst1opt));
- hopt->nexthdr = IPPROTO_IPV6;
+ hopt->nexthdr = proto;
proto = NEXTHDR_DEST;
}
skb_push(skb, sizeof(*ip6h));
skb_reset_network_header(skb);
+ skb->protocol = htons(ETH_P_IPV6);
ip6h = ipv6_hdr(skb);
ip6_flow_hdr(ip6h, dsfield,
@@ -767,6 +783,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
.in = state->in,
};
struct nf_flow_xmit xmit = {};
+ struct in6_addr *ip6_daddr;
struct flow_offload *flow;
struct neighbour *neigh;
struct rtable *rt;
@@ -796,28 +813,50 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
other_tuple = &flow->tuplehash[!dir].tuple;
ip_daddr = other_tuple->src_v4.s_addr;
- if (nf_flow_tunnel_v4_push(state->net, skb, other_tuple, &ip_daddr) < 0)
+ if (other_tuple->tun.encap_proto == AF_INET6) {
+ if (nf_flow_tunnel_v6_push(state->net, skb, other_tuple,
+ &ip6_daddr,
+ IPV6_DEFAULT_TNL_ENCAP_LIMIT) < 0)
+ return NF_DROP;
+ } else if (nf_flow_tunnel_v4_push(state->net, skb, other_tuple,
+ &ip_daddr) < 0) {
return NF_DROP;
+ }
if (nf_flow_encap_push(skb, other_tuple) < 0)
return NF_DROP;
switch (tuplehash->tuple.xmit_type) {
- case FLOW_OFFLOAD_XMIT_NEIGH:
- rt = dst_rtable(tuplehash->tuple.dst_cache);
+ case FLOW_OFFLOAD_XMIT_NEIGH: {
+ struct dst_entry *dst;
+
xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
if (!xmit.outdev) {
flow_offload_teardown(flow);
return NF_DROP;
}
- neigh = ip_neigh_gw4(rt->dst.dev, rt_nexthop(rt, ip_daddr));
+ if (other_tuple->tun.encap_proto == AF_INET6 ||
+ ctx.tun.proto == IPPROTO_IPV6) {
+ struct rt6_info *rt6;
+
+ rt6 = dst_rt6_info(tuplehash->tuple.dst_cache);
+ neigh = ip_neigh_gw6(rt6->dst.dev,
+ rt6_nexthop(rt6, ip6_daddr));
+ dst = &rt6->dst;
+ } else {
+ rt = dst_rtable(tuplehash->tuple.dst_cache);
+ neigh = ip_neigh_gw4(rt->dst.dev,
+ rt_nexthop(rt, ip_daddr));
+ dst = &rt->dst;
+ }
if (IS_ERR(neigh)) {
flow_offload_teardown(flow);
return NF_DROP;
}
xmit.dest = neigh->ha;
- skb_dst_set_noref(skb, &rt->dst);
+ skb_dst_set_noref(skb, dst);
break;
+ }
case FLOW_OFFLOAD_XMIT_DIRECT:
xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
if (!xmit.outdev) {
@@ -1068,8 +1107,12 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
if (!nf_flow_skb_encap_protocol(ctx, skb, htons(ETH_P_IPV6)))
return NULL;
- if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)
+ if (ctx->tun.proto == IPPROTO_IPIP) {
+ if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)
+ return NULL;
+ } else if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0) {
return NULL;
+ }
return flow_offload_lookup(flow_table, &tuple);
}
@@ -1097,8 +1140,11 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
if (tuplehash == NULL)
return NF_ACCEPT;
- ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb,
- encap_limit);
+ if (ctx.tun.proto == IPPROTO_IPIP)
+ ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
+ else
+ ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash,
+ skb, encap_limit);
if (ret < 0)
return NF_DROP;
else if (ret == 0)
@@ -1125,21 +1171,38 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
return NF_DROP;
switch (tuplehash->tuple.xmit_type) {
- case FLOW_OFFLOAD_XMIT_NEIGH:
- rt = dst_rt6_info(tuplehash->tuple.dst_cache);
+ case FLOW_OFFLOAD_XMIT_NEIGH: {
+ struct dst_entry *dst;
+
xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
if (!xmit.outdev) {
flow_offload_teardown(flow);
return NF_DROP;
}
- neigh = ip_neigh_gw6(rt->dst.dev, rt6_nexthop(rt, ip6_daddr));
+ if (other_tuple->tun.encap_proto == AF_INET ||
+ ctx.tun.proto == IPPROTO_IPIP) {
+ __be32 ip_daddr = other_tuple->src_v4.s_addr;
+ struct rtable *rt4;
+
+ skb->protocol = htons(ETH_P_IP);
+ rt4 = dst_rtable(tuplehash->tuple.dst_cache);
+ neigh = ip_neigh_gw4(rt4->dst.dev,
+ rt_nexthop(rt4, ip_daddr));
+ dst = &rt4->dst;
+ } else {
+ rt = dst_rt6_info(tuplehash->tuple.dst_cache);
+ neigh = ip_neigh_gw6(rt->dst.dev,
+ rt6_nexthop(rt, ip6_daddr));
+ dst = &rt->dst;
+ }
if (IS_ERR(neigh)) {
flow_offload_teardown(flow);
return NF_DROP;
}
xmit.dest = neigh->ha;
- skb_dst_set_noref(skb, &rt->dst);
+ skb_dst_set_noref(skb, dst);
break;
+ }
case FLOW_OFFLOAD_XMIT_DIRECT:
xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
if (!xmit.outdev) {
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index 5a5774d9b6f5..74b6f5ea35f9 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -209,12 +209,11 @@ static int nft_flow_tunnel_update_route(const struct nft_pktinfo *pkt,
struct dst_entry *tun_dst = NULL;
struct flowi fl = {};
- switch (nft_pf(pkt)) {
+ switch (tun->encap_proto) {
case NFPROTO_IPV4:
fl.u.ip4.daddr = tun->dst_v4.s_addr;
fl.u.ip4.saddr = tun->src_v4.s_addr;
fl.u.ip4.flowi4_iif = nft_in(pkt)->ifindex;
- fl.u.ip4.flowi4_dscp = ip4h_dscp(ip_hdr(pkt->skb));
fl.u.ip4.flowi4_mark = pkt->skb->mark;
fl.u.ip4.flowi4_flags = FLOWI_FLAG_ANYSRC;
break;
@@ -222,13 +221,12 @@ static int nft_flow_tunnel_update_route(const struct nft_pktinfo *pkt,
fl.u.ip6.daddr = tun->dst_v6;
fl.u.ip6.saddr = tun->src_v6;
fl.u.ip6.flowi6_iif = nft_in(pkt)->ifindex;
- fl.u.ip6.flowlabel = ip6_flowinfo(ipv6_hdr(pkt->skb));
fl.u.ip6.flowi6_mark = pkt->skb->mark;
fl.u.ip6.flowi6_flags = FLOWI_FLAG_ANYSRC;
break;
}
- nf_route(nft_net(pkt), &tun_dst, &fl, false, nft_pf(pkt));
+ nf_route(nft_net(pkt), &tun_dst, &fl, false, tun->encap_proto);
if (!tun_dst)
return -ENOENT;
--
2.54.0
^ permalink raw reply related
* [PATCH nf-next 2/4] net: netfilter: Add encap_proto to flow_offload_tunnel
From: Lorenzo Bianconi @ 2026-05-05 14:49 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno, Simon Horman, David Ahern,
Ido Schimmel, Pablo Neira Ayuso, Florian Westphal, Phil Sutter,
Shuah Khan
Cc: linux-arm-kernel, linux-mediatek, netdev, netfilter-devel,
coreteam, linux-kselftest, Lorenzo Bianconi
In-Reply-To: <20260505-b4-flowtable-sw-accel-ip6ip-v1-0-9ac39ccc9ea9@kernel.org>
Add encap_proto (AF_INET or AF_INET6) to struct flow_offload_tunnel
to allow its use as part of the hash table key during flowtable entry
lookup.
This is a preliminary change to support IPv4 over IPv6 tunneling via
the flowtable infrastructure for software acceleration.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
include/linux/netdevice.h | 1 +
include/net/netfilter/nf_flow_table.h | 1 +
net/ipv4/ipip.c | 1 +
net/ipv6/ip6_tunnel.c | 1 +
net/netfilter/nf_flow_table_ip.c | 2 ++
net/netfilter/nf_flow_table_path.c | 2 ++
6 files changed, 8 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 85bd9d46b5a0..02f593397fad 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -902,6 +902,7 @@ struct net_device_path {
};
u8 l3_proto;
+ u8 encap_proto;
} tun;
struct {
enum {
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index b09c11c048d5..96e8ecf0f530 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -118,6 +118,7 @@ struct flow_offload_tunnel {
};
u8 l3_proto;
+ u8 encap_proto;
};
struct flow_offload_tuple {
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index ff95b1b9908e..5425af051d5a 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -369,6 +369,7 @@ static int ipip_fill_forward_path(struct net_device_path_ctx *ctx,
path->tun.src_v4.s_addr = tiph->saddr;
path->tun.dst_v4.s_addr = tiph->daddr;
path->tun.l3_proto = IPPROTO_IPIP;
+ path->tun.encap_proto = AF_INET;
path->dev = ctx->dev;
ctx->dev = rt->dst.dev;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 3d64e672eeee..c99ed41bfc99 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1851,6 +1851,7 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
path->type = DEV_PATH_TUN;
path->tun.src_v6 = t->parms.laddr;
path->tun.dst_v6 = t->parms.raddr;
+ path->tun.encap_proto = AF_INET6;
if (ctx->ether_type == cpu_to_be16(ETH_P_IP))
path->tun.l3_proto = IPPROTO_IPIP;
else
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index fd56d663cb5b..9efd76b57847 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -198,6 +198,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
tuple->tun.dst_v4.s_addr = iph->daddr;
tuple->tun.src_v4.s_addr = iph->saddr;
tuple->tun.l3_proto = IPPROTO_IPIP;
+ tuple->tun.encap_proto = AF_INET;
}
break;
case htons(ETH_P_IPV6):
@@ -206,6 +207,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
tuple->tun.dst_v6 = ip6h->daddr;
tuple->tun.src_v6 = ip6h->saddr;
tuple->tun.l3_proto = IPPROTO_IPV6;
+ tuple->tun.encap_proto = AF_INET6;
}
break;
default:
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index df4e180ed3c2..5a5774d9b6f5 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -127,6 +127,7 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
info->tun.src_v6 = path->tun.src_v6;
info->tun.dst_v6 = path->tun.dst_v6;
info->tun.l3_proto = path->tun.l3_proto;
+ info->tun.encap_proto = path->tun.encap_proto;
info->num_tuns++;
} else {
if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {
@@ -270,6 +271,7 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
route->tuple[!dir].in.tun.src_v6 = info.tun.dst_v6;
route->tuple[!dir].in.tun.dst_v6 = info.tun.src_v6;
route->tuple[!dir].in.tun.l3_proto = info.tun.l3_proto;
+ route->tuple[!dir].in.tun.encap_proto = info.tun.encap_proto;
route->tuple[!dir].in.num_tuns = info.num_tuns;
}
--
2.54.0
^ permalink raw reply related
* [PATCH nf-next 1/4] net: netfilter: Add ether_type to net_device_path_ctx
From: Lorenzo Bianconi @ 2026-05-05 14:49 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno, Simon Horman, David Ahern,
Ido Schimmel, Pablo Neira Ayuso, Florian Westphal, Phil Sutter,
Shuah Khan
Cc: linux-arm-kernel, linux-mediatek, netdev, netfilter-devel,
coreteam, linux-kselftest, Lorenzo Bianconi
In-Reply-To: <20260505-b4-flowtable-sw-accel-ip6ip-v1-0-9ac39ccc9ea9@kernel.org>
Add an ether_type field to struct net_device_path_ctx to allow IPv6
tunnel drivers to select the appropriate L3 protocol based on the
encapsulated traffic.
Update the airoha and mtk Ethernet drivers to use the new
dev_fill_forward_path() signature.
This is a preliminary patch to enable sw flowtable acceleration for
IPv4 over IPv6 tunnels.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_ppe.c | 14 +++++++++-----
drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 13 ++++++++-----
include/linux/netdevice.h | 4 +++-
net/core/dev.c | 6 ++++--
net/ipv6/ip6_tunnel.c | 5 ++++-
net/netfilter/nf_flow_table_path.c | 8 +++++---
6 files changed, 33 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 26da519236bf..c5eccb3a43a1 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -245,7 +245,8 @@ static int airoha_ppe_flow_mangle_ipv4(const struct flow_action_entry *act,
return 0;
}
-static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr,
+static int airoha_ppe_get_wdma_info(struct net_device *dev,
+ const u8 *addr, __be16 ether_type,
struct airoha_wdma_info *info)
{
struct net_device_path_stack stack;
@@ -256,7 +257,7 @@ static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr,
return -ENODEV;
rcu_read_lock();
- err = dev_fill_forward_path(dev, addr, &stack);
+ err = dev_fill_forward_path(dev, addr, ether_type, &stack);
rcu_read_unlock();
if (err)
return err;
@@ -300,7 +301,7 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
struct airoha_foe_entry *hwe,
struct net_device *dev, int type,
struct airoha_flow_data *data,
- int l4proto)
+ __be16 ether_type, int l4proto)
{
u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val;
int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev);
@@ -322,7 +323,8 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
if (dev) {
struct airoha_wdma_info info = {};
- if (!airoha_ppe_get_wdma_info(dev, data->eth.h_dest, &info)) {
+ if (!airoha_ppe_get_wdma_info(dev, data->eth.h_dest,
+ ether_type, &info)) {
val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, info.idx) |
FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT,
FE_PSE_PORT_CDM4);
@@ -1047,6 +1049,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_eth *eth,
struct flow_action_entry *act;
struct airoha_foe_entry hwe;
int err, i, offload_type;
+ __be16 ether_type = 0;
u16 addr_type = 0;
u8 l4proto = 0;
@@ -1073,6 +1076,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_eth *eth,
struct flow_match_basic match;
flow_rule_match_basic(rule, &match);
+ ether_type = match.key->n_proto;
l4proto = match.key->ip_proto;
} else {
return -EOPNOTSUPP;
@@ -1143,7 +1147,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_eth *eth,
return -EINVAL;
err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
- &data, l4proto);
+ &data, ether_type, l4proto);
if (err)
return err;
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
index cc8c4ef8038f..2601c17b29c8 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
@@ -89,7 +89,8 @@ mtk_flow_offload_mangle_eth(const struct flow_action_entry *act, void *eth)
}
static int
-mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_info *info)
+mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr,
+ __be16 ether_type, struct mtk_wdma_info *info)
{
struct net_device_path_stack stack;
struct net_device_path *path;
@@ -102,7 +103,7 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
return -1;
rcu_read_lock();
- err = dev_fill_forward_path(dev, addr, &stack);
+ err = dev_fill_forward_path(dev, addr, ether_type, &stack);
rcu_read_unlock();
if (err)
return err;
@@ -190,12 +191,12 @@ mtk_flow_get_dsa_port(struct net_device **dev)
static int
mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
struct net_device *dev, const u8 *dest_mac,
- int *wed_index)
+ __be16 ether_type, int *wed_index)
{
struct mtk_wdma_info info = {};
int pse_port, dsa_port, queue;
- if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) {
+ if (mtk_flow_get_wdma_info(dev, dest_mac, ether_type, &info) == 0) {
mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue,
info.bss, info.wcid, info.amsdu);
if (mtk_is_netsys_v2_or_greater(eth)) {
@@ -273,6 +274,7 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
struct mtk_flow_data data = {};
struct mtk_foe_entry foe;
struct mtk_flow_entry *entry;
+ __be16 ether_type = 0;
int offload_type = 0;
int wed_index = -1;
u16 addr_type = 0;
@@ -319,6 +321,7 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
struct flow_match_basic match;
flow_rule_match_basic(rule, &match);
+ ether_type = match.key->n_proto;
l4proto = match.key->ip_proto;
} else {
return -EOPNOTSUPP;
@@ -481,7 +484,7 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
mtk_foe_entry_set_pppoe(eth, &foe, data.pppoe.sid);
err = mtk_flow_set_output_device(eth, &foe, odev, data.eth.h_dest,
- &wed_index);
+ ether_type, &wed_index);
if (err)
return err;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 744ffa243501..85bd9d46b5a0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -938,6 +938,7 @@ struct net_device_path_stack {
struct net_device_path_ctx {
const struct net_device *dev;
u8 daddr[ETH_ALEN];
+ __be16 ether_type;
int num_vlans;
struct {
@@ -3391,7 +3392,8 @@ void dev_remove_offload(struct packet_offload *po);
int dev_get_iflink(const struct net_device *dev);
int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
-int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+int dev_fill_forward_path(const struct net_device *dev,
+ const u8 *daddr, __be16 ether_type,
struct net_device_path_stack *stack);
struct net_device *dev_get_by_name(struct net *net, const char *name);
struct net_device *dev_get_by_name_rcu(struct net *net, const char *name);
diff --git a/net/core/dev.c b/net/core/dev.c
index 06c195906231..5f6171c08849 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -750,12 +750,14 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack)
return &stack->path[k];
}
-int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+int dev_fill_forward_path(const struct net_device *dev,
+ const u8 *daddr, __be16 ether_type,
struct net_device_path_stack *stack)
{
const struct net_device *last_dev;
struct net_device_path_ctx ctx = {
- .dev = dev,
+ .dev = dev,
+ .ether_type = ether_type,
};
struct net_device_path *path;
int ret = 0;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index c468c83af0f2..3d64e672eeee 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1851,7 +1851,10 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
path->type = DEV_PATH_TUN;
path->tun.src_v6 = t->parms.laddr;
path->tun.dst_v6 = t->parms.raddr;
- path->tun.l3_proto = IPPROTO_IPV6;
+ if (ctx->ether_type == cpu_to_be16(ETH_P_IP))
+ path->tun.l3_proto = IPPROTO_IPIP;
+ else
+ path->tun.l3_proto = IPPROTO_IPV6;
path->dev = ctx->dev;
ctx->dev = dst->dev;
}
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index 6bb9579dcc2a..df4e180ed3c2 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -45,7 +45,8 @@ static bool nft_is_valid_ether_device(const struct net_device *dev)
static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
const struct dst_entry *dst_cache,
const struct nf_conn *ct,
- enum ip_conntrack_dir dir, u8 *ha,
+ enum ip_conntrack_dir dir,
+ u8 *ha, __be16 ether_type,
struct net_device_path_stack *stack)
{
const void *daddr = &ct->tuplehash[!dir].tuple.src.u3;
@@ -70,7 +71,7 @@ static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
return -1;
out:
- return dev_fill_forward_path(dev, ha, stack);
+ return dev_fill_forward_path(dev, ha, ether_type, stack);
}
struct nft_forward_info {
@@ -248,7 +249,8 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
unsigned char ha[ETH_ALEN];
int i;
- if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
+ if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, pkt->ethertype,
+ &stack) >= 0)
nft_dev_path_info(&stack, &info, ha, &ft->data);
if (info.outdev)
--
2.54.0
^ permalink raw reply related
* [PATCH nf-next 0/4] Add IPv4 over IPv6 flowtable SW acceleration
From: Lorenzo Bianconi @ 2026-05-05 14:49 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Felix Fietkau, Matthias Brugger,
AngeloGioacchino Del Regno, Simon Horman, David Ahern,
Ido Schimmel, Pablo Neira Ayuso, Florian Westphal, Phil Sutter,
Shuah Khan
Cc: linux-arm-kernel, linux-mediatek, netdev, netfilter-devel,
coreteam, linux-kselftest, Lorenzo Bianconi
Similar to IPIP and IP6I6 tunnels, introduce sw acceleration for IPv4 over
IPv6 tunnels in the netfilter flowtable infrastructure.
---
Lorenzo Bianconi (4):
net: netfilter: Add ether_type to net_device_path_ctx
net: netfilter: Add encap_proto to flow_offload_tunnel
net: netfilter: Add IPv4 over IPv6 tunnel flowtable acceleration
selftests: netfilter: nft_flowtable.sh: Add IPv4 over IPv6 flowtable selftest
drivers/net/ethernet/airoha/airoha_ppe.c | 14 ++-
drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 13 ++-
include/linux/netdevice.h | 5 +-
include/net/netfilter/nf_flow_table.h | 1 +
net/core/dev.c | 6 +-
net/ipv4/ipip.c | 1 +
net/ipv6/ip6_tunnel.c | 6 +-
net/netfilter/nf_flow_table_core.c | 14 ++-
net/netfilter/nf_flow_table_ip.c | 129 ++++++++++++++++-----
net/netfilter/nf_flow_table_path.c | 16 +--
.../selftests/net/netfilter/nft_flowtable.sh | 26 +++++
11 files changed, 174 insertions(+), 57 deletions(-)
---
base-commit: c1e5127b577c6b88fa48e532616932ae978528d5
change-id: 20260505-b4-flowtable-sw-accel-ip6ip-7101034cd147
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply
* Re: [PATCH net 4/4] bnxt_en: Use absolute target ns from ptp_clock_request
From: Vadim Fedorenko @ 2026-05-05 14:39 UTC (permalink / raw)
To: Pavan Chebbi, davem, kuba
Cc: andrew+netdev, andrew.gospodarek, edumazet, michael.chan, netdev,
pabeni, Kalesh AP, Richard Cochran
In-Reply-To: <20260504083611.1383776-5-pavan.chebbi@broadcom.com>
On 04/05/2026 09:36, Pavan Chebbi wrote:
> There is no need to calculate the target PHC cycles required
> to make phase adjustment on the PPS OUT signal. This is because
> the application supplies absolute n_sec value in the future and
> is already the actual desired target value.
>
> Remove the unnecessary code.
>
> Fixes: 9e518f25802c ("bnxt_en: 1PPS functions to configure TSIO pins")
> Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> Cc: Richard Cochran <richardcochran@gmail.com>
> Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
> ---
> drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 29 ++++---------------
> 1 file changed, 5 insertions(+), 24 deletions(-)
>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Tested-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
^ permalink raw reply
* Re: [PATCH net-next v3 2/2] dpll: zl3073x: report FFO as DPLL vs input reference offset
From: Petr Oros @ 2026-05-05 14:34 UTC (permalink / raw)
To: Ivan Vecera, netdev, Jiri Pirko
Cc: Andrew Lunn, Arkadiusz Kubalewski, David S. Miller, Donald Hunter,
Eric Dumazet, Jakub Kicinski, Jonathan Corbet, Leon Romanovsky,
Mark Bloch, Michal Schmidt, Paolo Abeni, Pasi Vaananen,
Prathosh Satish, Saeed Mahameed, Shuah Khan, Simon Horman,
Tariq Toukan, Vadim Fedorenko, linux-doc, linux-kernel,
linux-rdma
In-Reply-To: <20260504155340.411063-3-ivecera@redhat.com>
On 5/4/26 17:53, Ivan Vecera wrote:
> Replace the per-reference frequency offset measurement (which was
> redundant with measured-frequency) with a direct read of the DPLL's
> delta frequency offset vs its tracked input reference.
>
> The new implementation uses the dpll_df_offset_x register with
> ref_ofst=1 via the dpll_df_read_x semaphore mechanism. This
> provides 2^-48 resolution (~3.5 fE) and reports the actual
> frequency difference between the DPLL and its active input.
>
> FFO is now reported only for the active input pin in the nested
> (pin vs parent DPLL) context. Top-level FFO returns -ENODATA.
>
> Rewrite ffo_check to compare the cached df_offset converted to PPT
> instead of using the old per-reference measurement. Remove the
> ref_ffo_update periodic measurement and the ref ffo field since
> they are no longer needed.
>
> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
> ---
> drivers/dpll/zl3073x/chan.c | 31 +++++++++++++++++++++++--
> drivers/dpll/zl3073x/chan.h | 14 ++++++++++++
> drivers/dpll/zl3073x/core.c | 45 -------------------------------------
> drivers/dpll/zl3073x/dpll.c | 34 ++++++++++++----------------
> drivers/dpll/zl3073x/ref.h | 14 ------------
> drivers/dpll/zl3073x/regs.h | 15 +++++++++++++
> 6 files changed, 72 insertions(+), 81 deletions(-)
>
> diff --git a/drivers/dpll/zl3073x/chan.c b/drivers/dpll/zl3073x/chan.c
> index 2f48ca2391494..2fe3c3da84bb5 100644
> --- a/drivers/dpll/zl3073x/chan.c
> +++ b/drivers/dpll/zl3073x/chan.c
> @@ -18,6 +18,7 @@
> int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index)
> {
> struct zl3073x_chan *chan = &zldev->chan[index];
> + u64 val;
> int rc;
>
> rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MON_STATUS(index),
> @@ -25,8 +26,34 @@ int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index)
> if (rc)
> return rc;
>
> - return zl3073x_read_u8(zldev, ZL_REG_DPLL_REFSEL_STATUS(index),
> - &chan->refsel_status);
> + rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_REFSEL_STATUS(index),
> + &chan->refsel_status);
> + if (rc)
> + return rc;
> +
> + /* Read df_offset vs tracked reference */
> + rc = zl3073x_poll_zero_u8(zldev, ZL_REG_DPLL_DF_READ(index),
> + ZL_DPLL_DF_READ_SEM);
> + if (rc)
> + return rc;
> +
> + rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_DF_READ(index),
> + ZL_DPLL_DF_READ_SEM | ZL_DPLL_DF_READ_REF_OFST);
> + if (rc)
> + return rc;
> +
> + rc = zl3073x_poll_zero_u8(zldev, ZL_REG_DPLL_DF_READ(index),
> + ZL_DPLL_DF_READ_SEM);
> + if (rc)
> + return rc;
> +
> + rc = zl3073x_read_u48(zldev, ZL_REG_DPLL_DF_OFFSET(index), &val);
> + if (rc)
> + return rc;
> +
> + chan->df_offset = sign_extend64(val, 47);
> +
> + return 0;
> }
>
> /**
> diff --git a/drivers/dpll/zl3073x/chan.h b/drivers/dpll/zl3073x/chan.h
> index 481da2133202b..4353809c69122 100644
> --- a/drivers/dpll/zl3073x/chan.h
> +++ b/drivers/dpll/zl3073x/chan.h
> @@ -17,6 +17,7 @@ struct zl3073x_dev;
> * @ref_prio: reference priority registers (4 bits per ref, P/N packed)
> * @mon_status: monitor status register value
> * @refsel_status: reference selection status register value
> + * @df_offset: frequency offset vs tracked reference in 2^-48 steps
> */
> struct zl3073x_chan {
> struct_group(cfg,
> @@ -26,6 +27,7 @@ struct zl3073x_chan {
> struct_group(stat,
> u8 mon_status;
> u8 refsel_status;
> + s64 df_offset;
> );
> };
>
> @@ -37,6 +39,18 @@ int zl3073x_chan_state_set(struct zl3073x_dev *zldev, u8 index,
>
> int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index);
>
> +/**
> + * zl3073x_chan_df_offset_get - get cached df_offset vs tracked reference
> + * @chan: pointer to channel state
> + *
> + * Return: frequency offset in 2^-48 steps
> + */
> +static inline s64
> +zl3073x_chan_df_offset_get(const struct zl3073x_chan *chan)
> +{
> + return chan->df_offset;
> +}
> +
> /**
> * zl3073x_chan_mode_get - get DPLL channel operating mode
> * @chan: pointer to channel state
> diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c
> index 5f1e70f3e40a0..b3345060490db 100644
> --- a/drivers/dpll/zl3073x/core.c
> +++ b/drivers/dpll/zl3073x/core.c
> @@ -704,44 +704,6 @@ zl3073x_ref_freq_meas_update(struct zl3073x_dev *zldev)
> return 0;
> }
>
> -/**
> - * zl3073x_ref_ffo_update - update reference fractional frequency offsets
> - * @zldev: pointer to zl3073x_dev structure
> - *
> - * The function asks device to latch the latest measured fractional
> - * frequency offset values, reads and stores them into the ref state.
> - *
> - * Return: 0 on success, <0 on error
> - */
> -static int
> -zl3073x_ref_ffo_update(struct zl3073x_dev *zldev)
> -{
> - int i, rc;
> -
> - rc = zl3073x_ref_freq_meas_latch(zldev,
> - ZL_REF_FREQ_MEAS_CTRL_REF_FREQ_OFF);
> - if (rc)
> - return rc;
> -
> - /* Read DPLL-to-REFx frequency offset measurements */
> - for (i = 0; i < ZL3073X_NUM_REFS; i++) {
> - s32 value;
> -
> - /* Read value stored in units of 2^-32 signed */
> - rc = zl3073x_read_u32(zldev, ZL_REG_REF_FREQ(i), &value);
> - if (rc)
> - return rc;
> -
> - /* Convert to ppt
> - * ffo = (10^12 * value) / 2^32
> - * ffo = ( 5^12 * value) / 2^20
> - */
> - zldev->ref[i].ffo = mul_s64_u64_shr(value, 244140625, 20);
> - }
> -
> - return 0;
> -}
> -
> static void
> zl3073x_dev_periodic_work(struct kthread_work *work)
> {
> @@ -776,13 +738,6 @@ zl3073x_dev_periodic_work(struct kthread_work *work)
> }
> }
>
> - /* Update references' fractional frequency offsets */
> - rc = zl3073x_ref_ffo_update(zldev);
> - if (rc)
> - dev_warn(zldev->dev,
> - "Failed to update fractional frequency offsets: %pe\n",
> - ERR_PTR(rc));
> -
> list_for_each_entry(zldpll, &zldev->dplls, list)
> zl3073x_dpll_changes_check(zldpll);
>
> diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
> index f2d430d1a8e7b..af50cd6200001 100644
> --- a/drivers/dpll/zl3073x/dpll.c
> +++ b/drivers/dpll/zl3073x/dpll.c
> @@ -299,8 +299,12 @@ zl3073x_dpll_input_pin_ffo_get(const struct dpll_pin *dpll_pin, void *pin_priv,
> {
> struct zl3073x_dpll_pin *pin = pin_priv;
>
> - /* Only rx vs tx symbol rate FFO is supported */
> - if (dpll)
> + /* Only nested FFO (pin vs parent DPLL) is supported */
> + if (!dpll)
> + return -ENODATA;
> +
> + /* Report FFO only for the active pin */
> + if (pin->operstate != DPLL_PIN_OPERSTATE_ACTIVE)
> return -ENODATA;
>
> *ffo = pin->freq_offset;
> @@ -1733,37 +1737,27 @@ zl3073x_dpll_pin_phase_offset_check(struct zl3073x_dpll_pin *pin)
> }
>
> /**
> - * zl3073x_dpll_pin_ffo_check - check for pin fractional frequency offset change
> + * zl3073x_dpll_pin_ffo_check - check for FFO change on active pin
> * @pin: pin to check
> *
> - * Check for the given pin's fractional frequency change.
> - *
> - * Return: true on fractional frequency offset change, false otherwise
> + * Return: true on change, false otherwise
> */
> static bool
> zl3073x_dpll_pin_ffo_check(struct zl3073x_dpll_pin *pin)
> {
> struct zl3073x_dpll *zldpll = pin->dpll;
> - struct zl3073x_dev *zldev = zldpll->dev;
> - const struct zl3073x_ref *ref;
> - u8 ref_id;
> + const struct zl3073x_chan *chan;
> s64 ffo;
>
> - /* Get reference monitor status */
> - ref_id = zl3073x_input_pin_ref_get(pin->id);
> - ref = zl3073x_ref_state_get(zldev, ref_id);
> -
> - /* Do not report ffo changes if the reference monitor report errors */
> - if (!zl3073x_ref_is_status_ok(ref))
> + if (pin->operstate != DPLL_PIN_OPERSTATE_ACTIVE)
> return false;
>
> - /* Compare with previous value */
> - ffo = zl3073x_ref_ffo_get(ref);
> + chan = zl3073x_chan_state_get(zldpll->dev, zldpll->id);
> + ffo = mul_s64_u64_shr(zl3073x_chan_df_offset_get(chan),
> + 244140625, 36);
> +
> if (pin->freq_offset != ffo) {
> - dev_dbg(zldev->dev, "%s freq offset changed: %lld -> %lld\n",
> - pin->label, pin->freq_offset, ffo);
> pin->freq_offset = ffo;
> -
> return true;
> }
>
> diff --git a/drivers/dpll/zl3073x/ref.h b/drivers/dpll/zl3073x/ref.h
> index 55e80e4f08734..e140ca3ea17dc 100644
> --- a/drivers/dpll/zl3073x/ref.h
> +++ b/drivers/dpll/zl3073x/ref.h
> @@ -22,7 +22,6 @@ struct zl3073x_dev;
> * @freq_ratio_n: FEC mode divisor
> * @sync_ctrl: reference sync control
> * @config: reference config
> - * @ffo: current fractional frequency offset
> * @meas_freq: measured input frequency in Hz
> * @mon_status: reference monitor status
> */
> @@ -40,7 +39,6 @@ struct zl3073x_ref {
> u8 config;
> );
> struct_group(stat, /* Status */
> - s64 ffo;
> u32 meas_freq;
> u8 mon_status;
> );
> @@ -58,18 +56,6 @@ int zl3073x_ref_state_update(struct zl3073x_dev *zldev, u8 index);
>
> int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult);
>
> -/**
> - * zl3073x_ref_ffo_get - get current fractional frequency offset
> - * @ref: pointer to ref state
> - *
> - * Return: the latest measured fractional frequency offset
> - */
> -static inline s64
> -zl3073x_ref_ffo_get(const struct zl3073x_ref *ref)
> -{
> - return ref->ffo;
> -}
> -
> /**
> * zl3073x_ref_meas_freq_get - get measured input frequency
> * @ref: pointer to ref state
> diff --git a/drivers/dpll/zl3073x/regs.h b/drivers/dpll/zl3073x/regs.h
> index 8015808bdf548..9578f00095282 100644
> --- a/drivers/dpll/zl3073x/regs.h
> +++ b/drivers/dpll/zl3073x/regs.h
> @@ -164,6 +164,11 @@
> #define ZL_DPLL_MODE_REFSEL_MODE_NCO 4
> #define ZL_DPLL_MODE_REFSEL_REF GENMASK(7, 4)
>
> +#define ZL_REG_DPLL_DF_READ(_idx) \
> + ZL_REG_IDX(_idx, 5, 0x28, 1, ZL3073X_MAX_CHANNELS, 1)
> +#define ZL_DPLL_DF_READ_SEM BIT(4)
> +#define ZL_DPLL_DF_READ_REF_OFST BIT(3)
> +
> #define ZL_REG_DPLL_MEAS_CTRL ZL_REG(5, 0x50, 1)
> #define ZL_DPLL_MEAS_CTRL_EN BIT(0)
> #define ZL_DPLL_MEAS_CTRL_AVG_FACTOR GENMASK(7, 4)
> @@ -176,6 +181,16 @@
> #define ZL_REG_DPLL_PHASE_ERR_DATA(_idx) \
> ZL_REG_IDX(_idx, 5, 0x55, 6, ZL3073X_MAX_CHANNELS, 6)
>
> +/*******************************
> + * Register Pages 6-7, DPLL Data
> + *******************************/
> +
> +#define ZL_REG_DPLL_DF_OFFSET_03(_idx) \
> + ZL_REG_IDX(_idx, 6, 0x00, 6, 4, 0x20)
> +#define ZL_REG_DPLL_DF_OFFSET_4 ZL_REG(7, 0x00, 6)
> +#define ZL_REG_DPLL_DF_OFFSET(_idx) \
> + ((_idx) < 4 ? ZL_REG_DPLL_DF_OFFSET_03(_idx) : ZL_REG_DPLL_DF_OFFSET_4)
> +
> /***********************************
> * Register Page 9, Synth and Output
> ***********************************/
Reviewed-by: Petr Oros <poros@redhat.com>
^ permalink raw reply
* Re: [PATCH iproute2] dpll: fix man page correctness issues
From: Vadim Fedorenko @ 2026-05-05 14:32 UTC (permalink / raw)
To: Ivan Vecera, netdev; +Cc: Petr Oros, David Ahern, Stephen Hemminger
In-Reply-To: <20260503164200.145679-1-ivecera@redhat.com>
On 03/05/2026 17:42, Ivan Vecera wrote:
> Fix several inaccuracies in dpll.8 man page:
> - Remove bogus "holdover" and "freerun" from operating modes list,
> only "manual" and "automatic" modes exist in the DPLL API
> - Fix typo "locked-ho-ack" -> "locked-ho-acq" in lock status list
> - Add missing device show output fields: lock-status-error,
> clock-quality-level, mode-supported, phase-offset-monitor and
> phase-offset-avg-factor
> - Add missing pin show output fields: panel-label, package-label,
> fractional-frequency-offset and esync-pulse
> - Remove non-existent exit codes 2 and 255, the tool only returns
> 0 (success) or 1 (failure)
> - Use canonical enable/disable for phase-offset-monitor to match
> the tool's help text
>
> Fixes: 656cfc3ce05b ("dpll: Add dpll command")
> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
> ---
> man/man8/dpll.8 | 32 +++++++++++++++++++++-----------
> 1 file changed, 21 insertions(+), 11 deletions(-)
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
^ permalink raw reply
* Re: [PATCH v5 14/16] wifi: ath12k: Switch to generic PAS TZ APIs
From: Jeff Johnson @ 2026-05-05 14:27 UTC (permalink / raw)
To: Sumit Garg, andersson, konradybcio
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, robh, krzk+dt,
conor+dt, robin.clark, sean, akhilpo, lumag, abhinav.kumar,
jesszhan0024, marijn.suijten, airlied, simona, vikash.garodia,
dikshita.agarwal, bod, mchehab, elder, andrew+netdev, davem,
edumazet, kuba, pabeni, jjohnson, mathieu.poirier,
trilokkumar.soni, mukesh.ojha, pavan.kondeti, jorge.ramirez,
tonyh, vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, linux-kernel, Sumit Garg
In-Reply-To: <20260504130603.1474043-15-sumit.garg@kernel.org>
On 5/4/2026 6:06 AM, Sumit Garg wrote:
> @@ -485,9 +485,9 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab, bool is_suspend)
> pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) |
> ATH12K_AHB_UPD_SWID;
> /* Release the firmware */
> - ret = qcom_scm_pas_shutdown(pasid);
> + ret = qcom_pas_shutdown(pasid);
> if (ret)
> - ath12k_err(ab, "scm pas shutdown failed for userPD%d\n",
> + ath12k_err(ab, "pas shutdown failed for userPD%d: %d\n",
> ab_ahb->userpd_id);
at some point the "ret" param was dropped, and this now generates build warnings
> }
> }
^ permalink raw reply
* [PATCH net-next 9/9] net: dsa: microchip: split ksz_connect_tag_protocol()
From: Bastien Curutchet (Schneider Electric) @ 2026-05-05 14:25 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
In-Reply-To: <20260505-clean-ksz-driver-v1-0-05d70fa42461@bootlin.com>
All the KSZ switches use the same ksz_connect_tag_protocol while they
don't support all the KSZ tag protocols. So if, for some reason, a given
switch tries to connect another KSZ tag protocol, it won't fail.
Split the common ksz_connect_tag_protocol() into switch-specific
operations. This way, each switch will only accept to connect the tag
protocol it supports.
Remove the no longer used common operation.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 51 ++++++++++++++++++++++++++++++--
drivers/net/dsa/microchip/ksz9477.c | 17 ++++++++++-
drivers/net/dsa/microchip/ksz_common.c | 19 ------------
drivers/net/dsa/microchip/ksz_common.h | 2 --
drivers/net/dsa/microchip/lan937x_main.c | 17 ++++++++++-
5 files changed, 80 insertions(+), 26 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index fa2e1256323c2..abee0dc5ec04b 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -16,6 +16,7 @@
#include <linux/bitfield.h>
#include <linux/delay.h>
+#include <linux/dsa/ksz_common.h>
#include <linux/export.h>
#include <linux/gpio.h>
#include <linux/if_vlan.h>
@@ -2107,6 +2108,20 @@ static enum dsa_tag_protocol ksz8463_get_tag_protocol(struct dsa_switch *ds,
return DSA_TAG_PROTO_KSZ9893;
}
+static int ksz8463_connect_tag_protocol(struct dsa_switch *ds,
+ enum dsa_tag_protocol proto)
+{
+ struct ksz_tagger_data *tagger_data;
+
+ if (proto != DSA_TAG_PROTO_KSZ9893)
+ return -EPROTONOSUPPORT;
+
+ tagger_data = ksz_tagger_data(ds);
+ tagger_data->xmit_work_fn = ksz_port_deferred_xmit;
+
+ return 0;
+}
+
static enum dsa_tag_protocol ksz87xx_get_tag_protocol(struct dsa_switch *ds,
int port,
enum dsa_tag_protocol mp)
@@ -2114,6 +2129,15 @@ static enum dsa_tag_protocol ksz87xx_get_tag_protocol(struct dsa_switch *ds,
return DSA_TAG_PROTO_KSZ8795;
}
+static int ksz87xx_connect_tag_protocol(struct dsa_switch *ds,
+ enum dsa_tag_protocol proto)
+{
+ if (proto != DSA_TAG_PROTO_KSZ8795)
+ return -EPROTONOSUPPORT;
+
+ return 0;
+}
+
static enum dsa_tag_protocol ksz88xx_get_tag_protocol(struct dsa_switch *ds,
int port,
enum dsa_tag_protocol mp)
@@ -2126,6 +2150,27 @@ static enum dsa_tag_protocol ksz88xx_get_tag_protocol(struct dsa_switch *ds,
return DSA_TAG_PROTO_KSZ9893;
}
+static int ksz88xx_connect_tag_protocol(struct dsa_switch *ds,
+ enum dsa_tag_protocol proto)
+{
+ struct ksz_tagger_data *tagger_data;
+
+ if (ksz_is_8895_family(ds->priv)) { /* KSZ8864, KSZ8895 */
+ if (proto != DSA_TAG_PROTO_KSZ8795)
+ return -EPROTONOSUPPORT;
+
+ return 0;
+ }
+
+ if (proto != DSA_TAG_PROTO_KSZ9893)
+ return -EPROTONOSUPPORT;
+
+ tagger_data = ksz_tagger_data(ds);
+ tagger_data->xmit_work_fn = ksz_port_deferred_xmit;
+
+ return 0;
+}
+
static void ksz88x3_phylink_mac_config(struct phylink_config *config,
unsigned int mode,
const struct phylink_link_state *state)
@@ -2256,7 +2301,7 @@ const struct ksz_dev_ops ksz88xx_dev_ops = {
const struct dsa_switch_ops ksz8463_switch_ops = {
.get_tag_protocol = ksz8463_get_tag_protocol,
- .connect_tag_protocol = ksz_connect_tag_protocol,
+ .connect_tag_protocol = ksz8463_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
.teardown = ksz_teardown,
@@ -2317,7 +2362,7 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
const struct dsa_switch_ops ksz87xx_switch_ops = {
.get_tag_protocol = ksz87xx_get_tag_protocol,
- .connect_tag_protocol = ksz_connect_tag_protocol,
+ .connect_tag_protocol = ksz87xx_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
.teardown = ksz_teardown,
@@ -2378,7 +2423,7 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
const struct dsa_switch_ops ksz88xx_switch_ops = {
.get_tag_protocol = ksz88xx_get_tag_protocol,
- .connect_tag_protocol = ksz_connect_tag_protocol,
+ .connect_tag_protocol = ksz88xx_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
.teardown = ksz_teardown,
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 9bac95bb079ff..ac2c63fe0588c 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -5,6 +5,7 @@
* Copyright (C) 2017-2025 Microchip Technology Inc.
*/
+#include <linux/dsa/ksz_common.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/iopoll.h>
@@ -1624,6 +1625,20 @@ static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
return DSA_TAG_PROTO_KSZ9477;
}
+static int ksz9477_connect_tag_protocol(struct dsa_switch *ds,
+ enum dsa_tag_protocol proto)
+{
+ struct ksz_tagger_data *tagger_data;
+
+ if (proto != DSA_TAG_PROTO_KSZ9893 && proto != DSA_TAG_PROTO_KSZ9477)
+ return -EPROTONOSUPPORT;
+
+ tagger_data = ksz_tagger_data(ds);
+ tagger_data->xmit_work_fn = ksz_port_deferred_xmit;
+
+ return 0;
+}
+
static void ksz9477_set_gbit(struct ksz_device *dev, int port, bool gbit)
{
const u8 *bitval = dev->info->xmii_ctrl1;
@@ -1790,7 +1805,7 @@ const struct ksz_dev_ops ksz9477_dev_ops = {
const struct dsa_switch_ops ksz9477_switch_ops = {
.get_tag_protocol = ksz9477_get_tag_protocol,
- .connect_tag_protocol = ksz_connect_tag_protocol,
+ .connect_tag_protocol = ksz9477_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
.teardown = ksz_teardown,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 1be055d3f1994..426414a218455 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3304,25 +3304,6 @@ int ksz_port_bridge_flags(struct dsa_switch *ds, int port,
return 0;
}
-int ksz_connect_tag_protocol(struct dsa_switch *ds,
- enum dsa_tag_protocol proto)
-{
- struct ksz_tagger_data *tagger_data;
-
- switch (proto) {
- case DSA_TAG_PROTO_KSZ8795:
- return 0;
- case DSA_TAG_PROTO_KSZ9893:
- case DSA_TAG_PROTO_KSZ9477:
- case DSA_TAG_PROTO_LAN937X:
- tagger_data = ksz_tagger_data(ds);
- tagger_data->xmit_work_fn = ksz_port_deferred_xmit;
- return 0;
- default:
- return -EPROTONOSUPPORT;
- }
-}
-
int ksz_port_vlan_filtering(struct dsa_switch *ds, int port,
bool flag, struct netlink_ext_ack *extack)
{
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 39486b5571bd6..3dde7e7717272 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -473,8 +473,6 @@ void ksz_teardown(struct dsa_switch *ds);
int ksz_port_setup(struct dsa_switch *ds, int port);
void ksz_port_teardown(struct dsa_switch *ds, int port);
-int ksz_connect_tag_protocol(struct dsa_switch *ds,
- enum dsa_tag_protocol proto);
void ksz_init_mib_timer(struct ksz_device *dev);
bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port);
void ksz_r_mib_stats64(struct ksz_device *dev, int port);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index c39be6eb50121..e522990cce22e 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -2,6 +2,7 @@
/* Microchip LAN937X switch driver main logic
* Copyright (C) 2019-2024 Microchip Technology Inc.
*/
+#include <linux/dsa/ksz_common.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/iopoll.h>
@@ -674,6 +675,20 @@ static enum dsa_tag_protocol lan937x_get_tag_protocol(struct dsa_switch *ds,
return DSA_TAG_PROTO_LAN937X;
}
+static int lan937x_connect_tag_protocol(struct dsa_switch *ds,
+ enum dsa_tag_protocol proto)
+{
+ struct ksz_tagger_data *tagger_data;
+
+ if (proto != DSA_TAG_PROTO_LAN937X)
+ return -EPROTONOSUPPORT;
+
+ tagger_data = ksz_tagger_data(ds);
+ tagger_data->xmit_work_fn = ksz_port_deferred_xmit;
+
+ return 0;
+}
+
const struct phylink_mac_ops lan937x_phylink_mac_ops = {
.mac_config = ksz_phylink_mac_config,
.mac_link_down = ksz_phylink_mac_link_down,
@@ -722,7 +737,7 @@ const struct ksz_dev_ops lan937x_dev_ops = {
const struct dsa_switch_ops lan937x_switch_ops = {
.get_tag_protocol = lan937x_get_tag_protocol,
- .connect_tag_protocol = ksz_connect_tag_protocol,
+ .connect_tag_protocol = lan937x_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
.teardown = ksz_teardown,
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 8/9] net: dsa: microchip: split ksz_get_tag_protocol()
From: Bastien Curutchet @ 2026-05-05 14:25 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric), Vladimir Oltean
In-Reply-To: <20260505-clean-ksz-driver-v1-0-05d70fa42461@bootlin.com>
From: Vladimir Oltean <vladimir.oltean@nxp.com>
All the switch families use a common function to implement
.get_tag_protocol(). This function then returns the relevant protocol
depending on the chip ID.
Make the protocol to dsa_switch_ops association a little bit more
obvious by having separate implementations.
Change made by manually checking which chip id has which dsa_switch_ops
assigned to it, then filtering the common ksz_get_tag_protocol() for
just those chip IDs pertaining to it.
As an important benefit, we no longer have that weird-looking
DSA_TAG_PROTO_NONE fallback which was never actually returned.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 32 +++++++++++++++++++++++++++++---
drivers/net/dsa/microchip/ksz9477.c | 16 +++++++++++++++-
drivers/net/dsa/microchip/ksz_common.c | 31 -------------------------------
drivers/net/dsa/microchip/ksz_common.h | 3 ---
drivers/net/dsa/microchip/lan937x_main.c | 9 ++++++++-
5 files changed, 52 insertions(+), 39 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index f7801269b11a4..fa2e1256323c2 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -2100,6 +2100,32 @@ static void ksz8_switch_exit(struct ksz_device *dev)
ksz8_reset_switch(dev);
}
+static enum dsa_tag_protocol ksz8463_get_tag_protocol(struct dsa_switch *ds,
+ int port,
+ enum dsa_tag_protocol mp)
+{
+ return DSA_TAG_PROTO_KSZ9893;
+}
+
+static enum dsa_tag_protocol ksz87xx_get_tag_protocol(struct dsa_switch *ds,
+ int port,
+ enum dsa_tag_protocol mp)
+{
+ return DSA_TAG_PROTO_KSZ8795;
+}
+
+static enum dsa_tag_protocol ksz88xx_get_tag_protocol(struct dsa_switch *ds,
+ int port,
+ enum dsa_tag_protocol mp)
+{
+ struct ksz_device *dev = ds->priv;
+
+ if (ksz_is_8895_family(dev)) /* KSZ8864, KSZ8895 */
+ return DSA_TAG_PROTO_KSZ8795;
+
+ return DSA_TAG_PROTO_KSZ9893;
+}
+
static void ksz88x3_phylink_mac_config(struct phylink_config *config,
unsigned int mode,
const struct phylink_link_state *state)
@@ -2229,7 +2255,7 @@ const struct ksz_dev_ops ksz88xx_dev_ops = {
};
const struct dsa_switch_ops ksz8463_switch_ops = {
- .get_tag_protocol = ksz_get_tag_protocol,
+ .get_tag_protocol = ksz8463_get_tag_protocol,
.connect_tag_protocol = ksz_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
@@ -2290,7 +2316,7 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
};
const struct dsa_switch_ops ksz87xx_switch_ops = {
- .get_tag_protocol = ksz_get_tag_protocol,
+ .get_tag_protocol = ksz87xx_get_tag_protocol,
.connect_tag_protocol = ksz_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
@@ -2351,7 +2377,7 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
};
const struct dsa_switch_ops ksz88xx_switch_ops = {
- .get_tag_protocol = ksz_get_tag_protocol,
+ .get_tag_protocol = ksz88xx_get_tag_protocol,
.connect_tag_protocol = ksz_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 9fb0169b5e29e..9bac95bb079ff 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1610,6 +1610,20 @@ static void ksz9477_switch_exit(struct ksz_device *dev)
ksz9477_reset_switch(dev);
}
+static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
+ int port,
+ enum dsa_tag_protocol mp)
+{
+ struct ksz_device *dev = ds->priv;
+
+ if (dev->chip_id == KSZ8563_CHIP_ID ||
+ dev->chip_id == KSZ9893_CHIP_ID ||
+ dev->chip_id == KSZ9563_CHIP_ID)
+ return DSA_TAG_PROTO_KSZ9893;
+
+ return DSA_TAG_PROTO_KSZ9477;
+}
+
static void ksz9477_set_gbit(struct ksz_device *dev, int port, bool gbit)
{
const u8 *bitval = dev->info->xmii_ctrl1;
@@ -1775,7 +1789,7 @@ const struct ksz_dev_ops ksz9477_dev_ops = {
};
const struct dsa_switch_ops ksz9477_switch_ops = {
- .get_tag_protocol = ksz_get_tag_protocol,
+ .get_tag_protocol = ksz9477_get_tag_protocol,
.connect_tag_protocol = ksz_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 37e575bf4e14d..1be055d3f1994 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3304,37 +3304,6 @@ int ksz_port_bridge_flags(struct dsa_switch *ds, int port,
return 0;
}
-enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
- int port,
- enum dsa_tag_protocol mp)
-{
- struct ksz_device *dev = ds->priv;
- enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE;
-
- if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev))
- proto = DSA_TAG_PROTO_KSZ8795;
-
- if (dev->chip_id == KSZ88X3_CHIP_ID ||
- dev->chip_id == KSZ8463_CHIP_ID ||
- dev->chip_id == KSZ8563_CHIP_ID ||
- dev->chip_id == KSZ9893_CHIP_ID ||
- dev->chip_id == KSZ9563_CHIP_ID)
- proto = DSA_TAG_PROTO_KSZ9893;
-
- if (dev->chip_id == KSZ8567_CHIP_ID ||
- dev->chip_id == KSZ9477_CHIP_ID ||
- dev->chip_id == KSZ9896_CHIP_ID ||
- dev->chip_id == KSZ9897_CHIP_ID ||
- dev->chip_id == KSZ9567_CHIP_ID ||
- dev->chip_id == LAN9646_CHIP_ID)
- proto = DSA_TAG_PROTO_KSZ9477;
-
- if (is_lan937x(dev))
- proto = DSA_TAG_PROTO_LAN937X;
-
- return proto;
-}
-
int ksz_connect_tag_protocol(struct dsa_switch *ds,
enum dsa_tag_protocol proto)
{
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 37923a1c43d80..39486b5571bd6 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -473,9 +473,6 @@ void ksz_teardown(struct dsa_switch *ds);
int ksz_port_setup(struct dsa_switch *ds, int port);
void ksz_port_teardown(struct dsa_switch *ds, int port);
-enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
- int port,
- enum dsa_tag_protocol mp);
int ksz_connect_tag_protocol(struct dsa_switch *ds,
enum dsa_tag_protocol proto);
void ksz_init_mib_timer(struct ksz_device *dev);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index ff931b1143a52..c39be6eb50121 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -667,6 +667,13 @@ static void lan937x_switch_exit(struct ksz_device *dev)
lan937x_reset_switch(dev);
}
+static enum dsa_tag_protocol lan937x_get_tag_protocol(struct dsa_switch *ds,
+ int port,
+ enum dsa_tag_protocol mp)
+{
+ return DSA_TAG_PROTO_LAN937X;
+}
+
const struct phylink_mac_ops lan937x_phylink_mac_ops = {
.mac_config = ksz_phylink_mac_config,
.mac_link_down = ksz_phylink_mac_link_down,
@@ -714,7 +721,7 @@ const struct ksz_dev_ops lan937x_dev_ops = {
};
const struct dsa_switch_ops lan937x_switch_ops = {
- .get_tag_protocol = ksz_get_tag_protocol,
+ .get_tag_protocol = lan937x_get_tag_protocol,
.connect_tag_protocol = ksz_connect_tag_protocol,
.get_phy_flags = ksz_get_phy_flags,
.setup = ksz_setup,
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 7/9] net: dsa: microchip: hook up ksz_switch_alloc() to chip-specific dsa_switch_ops
From: Bastien Curutchet @ 2026-05-05 14:25 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric), Vladimir Oltean
In-Reply-To: <20260505-clean-ksz-driver-v1-0-05d70fa42461@bootlin.com>
From: Vladimir Oltean <vladimir.oltean@nxp.com>
Now that each switch driver has its own dsa_switch_ops (currently a copy
of ksz_switch_ops), we no longer need ksz_switch_ops and can remove it.
Get to the driver-specific dsa_switch_ops through the ksz_chip_data
structure.
Reorder the alloc()/get_match_data() calls such as to have that
pointer available.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8863_smi.c | 8 ++--
drivers/net/dsa/microchip/ksz9477_i2c.c | 8 ++--
drivers/net/dsa/microchip/ksz_common.c | 67 ++-------------------------------
drivers/net/dsa/microchip/ksz_common.h | 4 +-
drivers/net/dsa/microchip/ksz_spi.c | 8 ++--
5 files changed, 19 insertions(+), 76 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c
index a8bfcd917bf70..ba08d2cf8e99f 100644
--- a/drivers/net/dsa/microchip/ksz8863_smi.c
+++ b/drivers/net/dsa/microchip/ksz8863_smi.c
@@ -140,14 +140,14 @@ static int ksz8863_smi_probe(struct mdio_device *mdiodev)
int ret;
int i;
- dev = ksz_switch_alloc(&mdiodev->dev, mdiodev);
- if (!dev)
- return -ENOMEM;
-
chip = device_get_match_data(ddev);
if (!chip)
return -EINVAL;
+ dev = ksz_switch_alloc(&mdiodev->dev, chip, mdiodev);
+ if (!dev)
+ return -ENOMEM;
+
for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {
rc = ksz8863_regmap_config[i];
rc.lock_arg = &dev->regmap_mutex;
diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c
index a2beb27459f18..8e9d08f2e1d65 100644
--- a/drivers/net/dsa/microchip/ksz9477_i2c.c
+++ b/drivers/net/dsa/microchip/ksz9477_i2c.c
@@ -22,14 +22,14 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c)
struct ksz_device *dev;
int i, ret;
- dev = ksz_switch_alloc(&i2c->dev, i2c);
- if (!dev)
- return -ENOMEM;
-
chip = device_get_match_data(ddev);
if (!chip)
return -EINVAL;
+ dev = ksz_switch_alloc(&i2c->dev, chip, i2c);
+ if (!dev)
+ return -ENOMEM;
+
/* Save chip id to do special initialization when probing. */
dev->chip_id = chip->chip_id;
for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index e48b9d5c06301..37e575bf4e14d 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -4640,68 +4640,9 @@ int ksz_resume(struct dsa_switch *ds)
return 0;
}
-static const struct dsa_switch_ops ksz_switch_ops = {
- .get_tag_protocol = ksz_get_tag_protocol,
- .connect_tag_protocol = ksz_connect_tag_protocol,
- .get_phy_flags = ksz_get_phy_flags,
- .setup = ksz_setup,
- .teardown = ksz_teardown,
- .phy_read = ksz_phy_read16,
- .phy_write = ksz_phy_write16,
- .phylink_get_caps = ksz_phylink_get_caps,
- .port_setup = ksz_port_setup,
- .set_ageing_time = ksz_set_ageing_time,
- .get_strings = ksz_get_strings,
- .get_ethtool_stats = ksz_get_ethtool_stats,
- .get_sset_count = ksz_sset_count,
- .port_bridge_join = ksz_port_bridge_join,
- .port_bridge_leave = ksz_port_bridge_leave,
- .port_hsr_join = ksz_hsr_join,
- .port_hsr_leave = ksz_hsr_leave,
- .port_set_mac_address = ksz_port_set_mac_address,
- .port_stp_state_set = ksz_port_stp_state_set,
- .port_teardown = ksz_port_teardown,
- .port_pre_bridge_flags = ksz_port_pre_bridge_flags,
- .port_bridge_flags = ksz_port_bridge_flags,
- .port_fast_age = ksz_port_fast_age,
- .port_vlan_filtering = ksz_port_vlan_filtering,
- .port_vlan_add = ksz_port_vlan_add,
- .port_vlan_del = ksz_port_vlan_del,
- .port_fdb_dump = ksz_port_fdb_dump,
- .port_fdb_add = ksz_port_fdb_add,
- .port_fdb_del = ksz_port_fdb_del,
- .port_mdb_add = ksz_port_mdb_add,
- .port_mdb_del = ksz_port_mdb_del,
- .port_mirror_add = ksz_port_mirror_add,
- .port_mirror_del = ksz_port_mirror_del,
- .get_stats64 = ksz_get_stats64,
- .get_pause_stats = ksz_get_pause_stats,
- .port_change_mtu = ksz_change_mtu,
- .port_max_mtu = ksz_max_mtu,
- .get_wol = ksz_get_wol,
- .set_wol = ksz_set_wol,
- .suspend = ksz_suspend,
- .resume = ksz_resume,
- .get_ts_info = ksz_get_ts_info,
- .port_hwtstamp_get = ksz_hwtstamp_get,
- .port_hwtstamp_set = ksz_hwtstamp_set,
- .port_txtstamp = ksz_port_txtstamp,
- .port_rxtstamp = ksz_port_rxtstamp,
- .cls_flower_add = ksz_cls_flower_add,
- .cls_flower_del = ksz_cls_flower_del,
- .port_setup_tc = ksz_setup_tc,
- .support_eee = ksz_support_eee,
- .set_mac_eee = ksz_set_mac_eee,
- .port_get_default_prio = ksz_port_get_default_prio,
- .port_set_default_prio = ksz_port_set_default_prio,
- .port_get_dscp_prio = ksz_port_get_dscp_prio,
- .port_add_dscp_prio = ksz_port_add_dscp_prio,
- .port_del_dscp_prio = ksz_port_del_dscp_prio,
- .port_get_apptrust = ksz_port_get_apptrust,
- .port_set_apptrust = ksz_port_set_apptrust,
-};
-
-struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
+struct ksz_device *ksz_switch_alloc(struct device *base,
+ const struct ksz_chip_data *chip,
+ void *priv)
{
struct dsa_switch *ds;
struct ksz_device *swdev;
@@ -4712,7 +4653,7 @@ struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
ds->dev = base;
ds->num_ports = DSA_MAX_PORTS;
- ds->ops = &ksz_switch_ops;
+ ds->ops = chip->switch_ops;
swdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL);
if (!swdev)
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 125740deb5a21..37923a1c43d80 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -460,7 +460,9 @@ struct ksz_dev_ops {
int (*pcs_create)(struct ksz_device *dev);
};
-struct ksz_device *ksz_switch_alloc(struct device *base, void *priv);
+struct ksz_device *ksz_switch_alloc(struct device *base,
+ const struct ksz_chip_data *chip,
+ void *priv);
int ksz_switch_register(struct ksz_device *dev);
void ksz_switch_remove(struct ksz_device *dev);
int ksz_switch_suspend(struct device *dev);
diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c
index d8001734b0574..373e9054947cb 100644
--- a/drivers/net/dsa/microchip/ksz_spi.c
+++ b/drivers/net/dsa/microchip/ksz_spi.c
@@ -143,14 +143,14 @@ static int ksz_spi_probe(struct spi_device *spi)
struct ksz_device *dev;
int i, ret = 0;
- dev = ksz_switch_alloc(&spi->dev, spi);
- if (!dev)
- return -ENOMEM;
-
chip = device_get_match_data(ddev);
if (!chip)
return -EINVAL;
+ dev = ksz_switch_alloc(&spi->dev, chip, spi);
+ if (!dev)
+ return -ENOMEM;
+
/* Save chip id to do special initialization when probing. */
dev->chip_id = chip->chip_id;
if (chip->chip_id == KSZ88X3_CHIP_ID)
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 6/9] net: dsa: microchip: ensure each ksz_dev_ops has its own dsa_switch_ops
From: Bastien Curutchet @ 2026-05-05 14:25 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric), Vladimir Oltean
In-Reply-To: <20260505-clean-ksz-driver-v1-0-05d70fa42461@bootlin.com>
From: Vladimir Oltean <vladimir.oltean@nxp.com>
Currently we have a single dsa_switch_ops for 4 very distinct families
of switches, and many dsa_switch_ops methods are simply a dispatches
through ksz_dev_ops. That creates an avoidable level of indirection.
As a preparation for removing that indirection layer, create a separate
dsa_switch_ops structure wherever we have a ksz_dev_ops. These
structures are not yet used - ksz_switch_ops from ksz_common.c still is.
However, this reduces the noise from subsequent changes.
All new dsa_switch_ops are exact copies of ksz_switch_ops. But we need
to export function prototypes from ksz_common.c so that they are
callable from individual drivers.
Note that "individual drivers" are not actual separate kernel modules.
All of ksz8.c, ksz9477.c and lan937x_main.c are part of the same
ksz_switch.ko. Only the "register interface" drivers are different
modules (ksz9477_i2c.o for I2C, ksz_spi.o for SPI, ksz8863_smi.o for
MDIO). So we don't need to export any symbol.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 184 +++++++++++++++++++++++++++++
drivers/net/dsa/microchip/ksz8.h | 3 +
drivers/net/dsa/microchip/ksz9477.c | 62 ++++++++++
drivers/net/dsa/microchip/ksz9477.h | 1 +
drivers/net/dsa/microchip/ksz_common.c | 193 +++++++++++++++++--------------
drivers/net/dsa/microchip/ksz_common.h | 96 +++++++++++++++
drivers/net/dsa/microchip/lan937x.h | 1 +
drivers/net/dsa/microchip/lan937x_main.c | 62 ++++++++++
8 files changed, 516 insertions(+), 86 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index f311901c693f8..f7801269b11a4 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -31,6 +31,7 @@
#include <linux/phylink.h>
#include "ksz_common.h"
+#include "ksz_dcb.h"
#include "ksz8_reg.h"
#include "ksz8.h"
@@ -2227,6 +2228,189 @@ const struct ksz_dev_ops ksz88xx_dev_ops = {
.pme_pwrite8 = ksz8_pme_pwrite8,
};
+const struct dsa_switch_ops ksz8463_switch_ops = {
+ .get_tag_protocol = ksz_get_tag_protocol,
+ .connect_tag_protocol = ksz_connect_tag_protocol,
+ .get_phy_flags = ksz_get_phy_flags,
+ .setup = ksz_setup,
+ .teardown = ksz_teardown,
+ .phy_read = ksz_phy_read16,
+ .phy_write = ksz_phy_write16,
+ .phylink_get_caps = ksz_phylink_get_caps,
+ .port_setup = ksz_port_setup,
+ .set_ageing_time = ksz_set_ageing_time,
+ .get_strings = ksz_get_strings,
+ .get_ethtool_stats = ksz_get_ethtool_stats,
+ .get_sset_count = ksz_sset_count,
+ .port_bridge_join = ksz_port_bridge_join,
+ .port_bridge_leave = ksz_port_bridge_leave,
+ .port_hsr_join = ksz_hsr_join,
+ .port_hsr_leave = ksz_hsr_leave,
+ .port_set_mac_address = ksz_port_set_mac_address,
+ .port_stp_state_set = ksz_port_stp_state_set,
+ .port_teardown = ksz_port_teardown,
+ .port_pre_bridge_flags = ksz_port_pre_bridge_flags,
+ .port_bridge_flags = ksz_port_bridge_flags,
+ .port_fast_age = ksz_port_fast_age,
+ .port_vlan_filtering = ksz_port_vlan_filtering,
+ .port_vlan_add = ksz_port_vlan_add,
+ .port_vlan_del = ksz_port_vlan_del,
+ .port_fdb_dump = ksz_port_fdb_dump,
+ .port_fdb_add = ksz_port_fdb_add,
+ .port_fdb_del = ksz_port_fdb_del,
+ .port_mdb_add = ksz_port_mdb_add,
+ .port_mdb_del = ksz_port_mdb_del,
+ .port_mirror_add = ksz_port_mirror_add,
+ .port_mirror_del = ksz_port_mirror_del,
+ .get_stats64 = ksz_get_stats64,
+ .get_pause_stats = ksz_get_pause_stats,
+ .port_change_mtu = ksz_change_mtu,
+ .port_max_mtu = ksz_max_mtu,
+ .get_wol = ksz_get_wol,
+ .set_wol = ksz_set_wol,
+ .suspend = ksz_suspend,
+ .resume = ksz_resume,
+ .get_ts_info = ksz_get_ts_info,
+ .port_hwtstamp_get = ksz_hwtstamp_get,
+ .port_hwtstamp_set = ksz_hwtstamp_set,
+ .port_txtstamp = ksz_port_txtstamp,
+ .port_rxtstamp = ksz_port_rxtstamp,
+ .cls_flower_add = ksz_cls_flower_add,
+ .cls_flower_del = ksz_cls_flower_del,
+ .port_setup_tc = ksz_setup_tc,
+ .support_eee = ksz_support_eee,
+ .set_mac_eee = ksz_set_mac_eee,
+ .port_get_default_prio = ksz_port_get_default_prio,
+ .port_set_default_prio = ksz_port_set_default_prio,
+ .port_get_dscp_prio = ksz_port_get_dscp_prio,
+ .port_add_dscp_prio = ksz_port_add_dscp_prio,
+ .port_del_dscp_prio = ksz_port_del_dscp_prio,
+ .port_get_apptrust = ksz_port_get_apptrust,
+ .port_set_apptrust = ksz_port_set_apptrust,
+};
+
+const struct dsa_switch_ops ksz87xx_switch_ops = {
+ .get_tag_protocol = ksz_get_tag_protocol,
+ .connect_tag_protocol = ksz_connect_tag_protocol,
+ .get_phy_flags = ksz_get_phy_flags,
+ .setup = ksz_setup,
+ .teardown = ksz_teardown,
+ .phy_read = ksz_phy_read16,
+ .phy_write = ksz_phy_write16,
+ .phylink_get_caps = ksz_phylink_get_caps,
+ .port_setup = ksz_port_setup,
+ .set_ageing_time = ksz_set_ageing_time,
+ .get_strings = ksz_get_strings,
+ .get_ethtool_stats = ksz_get_ethtool_stats,
+ .get_sset_count = ksz_sset_count,
+ .port_bridge_join = ksz_port_bridge_join,
+ .port_bridge_leave = ksz_port_bridge_leave,
+ .port_hsr_join = ksz_hsr_join,
+ .port_hsr_leave = ksz_hsr_leave,
+ .port_set_mac_address = ksz_port_set_mac_address,
+ .port_stp_state_set = ksz_port_stp_state_set,
+ .port_teardown = ksz_port_teardown,
+ .port_pre_bridge_flags = ksz_port_pre_bridge_flags,
+ .port_bridge_flags = ksz_port_bridge_flags,
+ .port_fast_age = ksz_port_fast_age,
+ .port_vlan_filtering = ksz_port_vlan_filtering,
+ .port_vlan_add = ksz_port_vlan_add,
+ .port_vlan_del = ksz_port_vlan_del,
+ .port_fdb_dump = ksz_port_fdb_dump,
+ .port_fdb_add = ksz_port_fdb_add,
+ .port_fdb_del = ksz_port_fdb_del,
+ .port_mdb_add = ksz_port_mdb_add,
+ .port_mdb_del = ksz_port_mdb_del,
+ .port_mirror_add = ksz_port_mirror_add,
+ .port_mirror_del = ksz_port_mirror_del,
+ .get_stats64 = ksz_get_stats64,
+ .get_pause_stats = ksz_get_pause_stats,
+ .port_change_mtu = ksz_change_mtu,
+ .port_max_mtu = ksz_max_mtu,
+ .get_wol = ksz_get_wol,
+ .set_wol = ksz_set_wol,
+ .suspend = ksz_suspend,
+ .resume = ksz_resume,
+ .get_ts_info = ksz_get_ts_info,
+ .port_hwtstamp_get = ksz_hwtstamp_get,
+ .port_hwtstamp_set = ksz_hwtstamp_set,
+ .port_txtstamp = ksz_port_txtstamp,
+ .port_rxtstamp = ksz_port_rxtstamp,
+ .cls_flower_add = ksz_cls_flower_add,
+ .cls_flower_del = ksz_cls_flower_del,
+ .port_setup_tc = ksz_setup_tc,
+ .support_eee = ksz_support_eee,
+ .set_mac_eee = ksz_set_mac_eee,
+ .port_get_default_prio = ksz_port_get_default_prio,
+ .port_set_default_prio = ksz_port_set_default_prio,
+ .port_get_dscp_prio = ksz_port_get_dscp_prio,
+ .port_add_dscp_prio = ksz_port_add_dscp_prio,
+ .port_del_dscp_prio = ksz_port_del_dscp_prio,
+ .port_get_apptrust = ksz_port_get_apptrust,
+ .port_set_apptrust = ksz_port_set_apptrust,
+};
+
+const struct dsa_switch_ops ksz88xx_switch_ops = {
+ .get_tag_protocol = ksz_get_tag_protocol,
+ .connect_tag_protocol = ksz_connect_tag_protocol,
+ .get_phy_flags = ksz_get_phy_flags,
+ .setup = ksz_setup,
+ .teardown = ksz_teardown,
+ .phy_read = ksz_phy_read16,
+ .phy_write = ksz_phy_write16,
+ .phylink_get_caps = ksz_phylink_get_caps,
+ .port_setup = ksz_port_setup,
+ .set_ageing_time = ksz_set_ageing_time,
+ .get_strings = ksz_get_strings,
+ .get_ethtool_stats = ksz_get_ethtool_stats,
+ .get_sset_count = ksz_sset_count,
+ .port_bridge_join = ksz_port_bridge_join,
+ .port_bridge_leave = ksz_port_bridge_leave,
+ .port_hsr_join = ksz_hsr_join,
+ .port_hsr_leave = ksz_hsr_leave,
+ .port_set_mac_address = ksz_port_set_mac_address,
+ .port_stp_state_set = ksz_port_stp_state_set,
+ .port_teardown = ksz_port_teardown,
+ .port_pre_bridge_flags = ksz_port_pre_bridge_flags,
+ .port_bridge_flags = ksz_port_bridge_flags,
+ .port_fast_age = ksz_port_fast_age,
+ .port_vlan_filtering = ksz_port_vlan_filtering,
+ .port_vlan_add = ksz_port_vlan_add,
+ .port_vlan_del = ksz_port_vlan_del,
+ .port_fdb_dump = ksz_port_fdb_dump,
+ .port_fdb_add = ksz_port_fdb_add,
+ .port_fdb_del = ksz_port_fdb_del,
+ .port_mdb_add = ksz_port_mdb_add,
+ .port_mdb_del = ksz_port_mdb_del,
+ .port_mirror_add = ksz_port_mirror_add,
+ .port_mirror_del = ksz_port_mirror_del,
+ .get_stats64 = ksz_get_stats64,
+ .get_pause_stats = ksz_get_pause_stats,
+ .port_change_mtu = ksz_change_mtu,
+ .port_max_mtu = ksz_max_mtu,
+ .get_wol = ksz_get_wol,
+ .set_wol = ksz_set_wol,
+ .suspend = ksz_suspend,
+ .resume = ksz_resume,
+ .get_ts_info = ksz_get_ts_info,
+ .port_hwtstamp_get = ksz_hwtstamp_get,
+ .port_hwtstamp_set = ksz_hwtstamp_set,
+ .port_txtstamp = ksz_port_txtstamp,
+ .port_rxtstamp = ksz_port_rxtstamp,
+ .cls_flower_add = ksz_cls_flower_add,
+ .cls_flower_del = ksz_cls_flower_del,
+ .port_setup_tc = ksz_setup_tc,
+ .support_eee = ksz_support_eee,
+ .set_mac_eee = ksz_set_mac_eee,
+ .port_get_default_prio = ksz_port_get_default_prio,
+ .port_set_default_prio = ksz_port_set_default_prio,
+ .port_get_dscp_prio = ksz_port_get_dscp_prio,
+ .port_add_dscp_prio = ksz_port_add_dscp_prio,
+ .port_del_dscp_prio = ksz_port_del_dscp_prio,
+ .port_get_apptrust = ksz_port_get_apptrust,
+ .port_set_apptrust = ksz_port_set_apptrust,
+};
+
MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>");
MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/microchip/ksz8.h b/drivers/net/dsa/microchip/ksz8.h
index 2d787d6d96b05..bc371cc26c6f1 100644
--- a/drivers/net/dsa/microchip/ksz8.h
+++ b/drivers/net/dsa/microchip/ksz8.h
@@ -17,5 +17,8 @@ extern const struct ksz_dev_ops ksz87xx_dev_ops;
extern const struct ksz_dev_ops ksz88xx_dev_ops;
extern const struct phylink_mac_ops ksz88x3_phylink_mac_ops;
extern const struct phylink_mac_ops ksz8_phylink_mac_ops;
+extern const struct dsa_switch_ops ksz8463_switch_ops;
+extern const struct dsa_switch_ops ksz87xx_switch_ops;
+extern const struct dsa_switch_ops ksz88xx_switch_ops;
#endif
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 3fd2174364acf..9fb0169b5e29e 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -17,6 +17,7 @@
#include "ksz9477_reg.h"
#include "ksz_common.h"
+#include "ksz_dcb.h"
#include "ksz9477.h"
static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
@@ -1773,6 +1774,67 @@ const struct ksz_dev_ops ksz9477_dev_ops = {
.pcs_create = ksz9477_pcs_create,
};
+const struct dsa_switch_ops ksz9477_switch_ops = {
+ .get_tag_protocol = ksz_get_tag_protocol,
+ .connect_tag_protocol = ksz_connect_tag_protocol,
+ .get_phy_flags = ksz_get_phy_flags,
+ .setup = ksz_setup,
+ .teardown = ksz_teardown,
+ .phy_read = ksz_phy_read16,
+ .phy_write = ksz_phy_write16,
+ .phylink_get_caps = ksz_phylink_get_caps,
+ .port_setup = ksz_port_setup,
+ .set_ageing_time = ksz_set_ageing_time,
+ .get_strings = ksz_get_strings,
+ .get_ethtool_stats = ksz_get_ethtool_stats,
+ .get_sset_count = ksz_sset_count,
+ .port_bridge_join = ksz_port_bridge_join,
+ .port_bridge_leave = ksz_port_bridge_leave,
+ .port_hsr_join = ksz_hsr_join,
+ .port_hsr_leave = ksz_hsr_leave,
+ .port_set_mac_address = ksz_port_set_mac_address,
+ .port_stp_state_set = ksz_port_stp_state_set,
+ .port_teardown = ksz_port_teardown,
+ .port_pre_bridge_flags = ksz_port_pre_bridge_flags,
+ .port_bridge_flags = ksz_port_bridge_flags,
+ .port_fast_age = ksz_port_fast_age,
+ .port_vlan_filtering = ksz_port_vlan_filtering,
+ .port_vlan_add = ksz_port_vlan_add,
+ .port_vlan_del = ksz_port_vlan_del,
+ .port_fdb_dump = ksz_port_fdb_dump,
+ .port_fdb_add = ksz_port_fdb_add,
+ .port_fdb_del = ksz_port_fdb_del,
+ .port_mdb_add = ksz_port_mdb_add,
+ .port_mdb_del = ksz_port_mdb_del,
+ .port_mirror_add = ksz_port_mirror_add,
+ .port_mirror_del = ksz_port_mirror_del,
+ .get_stats64 = ksz_get_stats64,
+ .get_pause_stats = ksz_get_pause_stats,
+ .port_change_mtu = ksz_change_mtu,
+ .port_max_mtu = ksz_max_mtu,
+ .get_wol = ksz_get_wol,
+ .set_wol = ksz_set_wol,
+ .suspend = ksz_suspend,
+ .resume = ksz_resume,
+ .get_ts_info = ksz_get_ts_info,
+ .port_hwtstamp_get = ksz_hwtstamp_get,
+ .port_hwtstamp_set = ksz_hwtstamp_set,
+ .port_txtstamp = ksz_port_txtstamp,
+ .port_rxtstamp = ksz_port_rxtstamp,
+ .cls_flower_add = ksz_cls_flower_add,
+ .cls_flower_del = ksz_cls_flower_del,
+ .port_setup_tc = ksz_setup_tc,
+ .support_eee = ksz_support_eee,
+ .set_mac_eee = ksz_set_mac_eee,
+ .port_get_default_prio = ksz_port_get_default_prio,
+ .port_set_default_prio = ksz_port_set_default_prio,
+ .port_get_dscp_prio = ksz_port_get_dscp_prio,
+ .port_add_dscp_prio = ksz_port_add_dscp_prio,
+ .port_del_dscp_prio = ksz_port_del_dscp_prio,
+ .port_get_apptrust = ksz_port_get_apptrust,
+ .port_set_apptrust = ksz_port_set_apptrust,
+};
+
MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>");
MODULE_DESCRIPTION("Microchip KSZ9477 Series Switch DSA Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/microchip/ksz9477.h b/drivers/net/dsa/microchip/ksz9477.h
index 26a91f1a4c871..bacadcbc478cc 100644
--- a/drivers/net/dsa/microchip/ksz9477.h
+++ b/drivers/net/dsa/microchip/ksz9477.h
@@ -93,5 +93,6 @@ void ksz9477_phylink_mac_link_up(struct phylink_config *config,
extern const struct ksz_dev_ops ksz9477_dev_ops;
extern const struct phylink_mac_ops ksz9477_phylink_mac_ops;
+extern const struct dsa_switch_ops ksz9477_switch_ops;
#endif
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 308740829e76c..e48b9d5c06301 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -1258,6 +1258,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 4,
.ops = &ksz8463_dev_ops,
+ .switch_ops = &ksz8463_switch_ops,
.phylink_mac_ops = &ksz88x3_phylink_mac_ops,
.mib_names = ksz88xx_mib_names,
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
@@ -1283,6 +1284,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_ipms = 8,
.tc_cbs_supported = true,
.ops = &ksz9477_dev_ops,
+ .switch_ops = &ksz9477_switch_ops,
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
@@ -1313,6 +1315,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 4,
.ops = &ksz87xx_dev_ops,
+ .switch_ops = &ksz87xx_switch_ops,
.phylink_mac_ops = &ksz8_phylink_mac_ops,
.ksz87xx_eee_link_erratum = true,
.mib_names = ksz9477_mib_names,
@@ -1354,6 +1357,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 4,
.ops = &ksz87xx_dev_ops,
+ .switch_ops = &ksz87xx_switch_ops,
.phylink_mac_ops = &ksz8_phylink_mac_ops,
.ksz87xx_eee_link_erratum = true,
.mib_names = ksz9477_mib_names,
@@ -1381,6 +1385,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 4,
.ops = &ksz87xx_dev_ops,
+ .switch_ops = &ksz87xx_switch_ops,
.phylink_mac_ops = &ksz8_phylink_mac_ops,
.ksz87xx_eee_link_erratum = true,
.mib_names = ksz9477_mib_names,
@@ -1408,6 +1413,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 4,
.ops = &ksz88xx_dev_ops,
+ .switch_ops = &ksz88xx_switch_ops,
.phylink_mac_ops = &ksz88x3_phylink_mac_ops,
.mib_names = ksz88xx_mib_names,
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
@@ -1442,6 +1448,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 4,
.ops = &ksz88xx_dev_ops,
+ .switch_ops = &ksz88xx_switch_ops,
.phylink_mac_ops = &ksz88x3_phylink_mac_ops,
.mib_names = ksz88xx_mib_names,
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
@@ -1465,6 +1472,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 4,
.ops = &ksz88xx_dev_ops,
+ .switch_ops = &ksz88xx_switch_ops,
.phylink_mac_ops = &ksz88x3_phylink_mac_ops,
.mib_names = ksz88xx_mib_names,
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
@@ -1490,6 +1498,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_ipms = 8,
.tc_cbs_supported = true,
.ops = &ksz9477_dev_ops,
+ .switch_ops = &ksz9477_switch_ops,
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
.phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
@@ -1527,6 +1536,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 8,
.ops = &ksz9477_dev_ops,
+ .switch_ops = &ksz9477_switch_ops,
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
.phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
@@ -1562,6 +1572,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 8,
.ops = &ksz9477_dev_ops,
+ .switch_ops = &ksz9477_switch_ops,
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
.phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
@@ -1595,6 +1606,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 8,
.ops = &ksz9477_dev_ops,
+ .switch_ops = &ksz9477_switch_ops,
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
@@ -1624,6 +1636,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_ipms = 8,
.tc_cbs_supported = true,
.ops = &ksz9477_dev_ops,
+ .switch_ops = &ksz9477_switch_ops,
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
@@ -1654,6 +1667,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_ipms = 8,
.tc_cbs_supported = true,
.ops = &ksz9477_dev_ops,
+ .switch_ops = &ksz9477_switch_ops,
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
.phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
@@ -1690,6 +1704,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_ipms = 8,
.tc_cbs_supported = true,
.ops = &ksz9477_dev_ops,
+ .switch_ops = &ksz9477_switch_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1724,6 +1739,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true,
.phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
+ .switch_ops = &lan937x_switch_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
@@ -1754,6 +1770,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true,
.phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
+ .switch_ops = &lan937x_switch_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
@@ -1784,6 +1801,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true,
.phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
+ .switch_ops = &lan937x_switch_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
@@ -1818,6 +1836,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true,
.phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
+ .switch_ops = &lan937x_switch_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
@@ -1852,6 +1871,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true,
.phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
+ .switch_ops = &lan937x_switch_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
@@ -1884,6 +1904,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 4,
.num_ipms = 8,
.ops = &ksz9477_dev_ops,
+ .switch_ops = &ksz9477_switch_ops,
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
.phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
@@ -1949,8 +1970,8 @@ static int ksz_check_device_id(struct ksz_device *dev)
return 0;
}
-static void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
- struct phylink_config *config)
+void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config)
{
struct ksz_device *dev = ds->priv;
@@ -2095,8 +2116,8 @@ void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port)
spin_unlock(&mib->stats64_lock);
}
-static void ksz_get_stats64(struct dsa_switch *ds, int port,
- struct rtnl_link_stats64 *s)
+void ksz_get_stats64(struct dsa_switch *ds, int port,
+ struct rtnl_link_stats64 *s)
{
struct ksz_device *dev = ds->priv;
struct ksz_port_mib *mib;
@@ -2108,8 +2129,8 @@ static void ksz_get_stats64(struct dsa_switch *ds, int port,
spin_unlock(&mib->stats64_lock);
}
-static void ksz_get_pause_stats(struct dsa_switch *ds, int port,
- struct ethtool_pause_stats *pause_stats)
+void ksz_get_pause_stats(struct dsa_switch *ds, int port,
+ struct ethtool_pause_stats *pause_stats)
{
struct ksz_device *dev = ds->priv;
struct ksz_port_mib *mib;
@@ -2121,8 +2142,8 @@ static void ksz_get_pause_stats(struct dsa_switch *ds, int port,
spin_unlock(&mib->stats64_lock);
}
-static void ksz_get_strings(struct dsa_switch *ds, int port,
- u32 stringset, uint8_t *buf)
+void ksz_get_strings(struct dsa_switch *ds, int port,
+ u32 stringset, uint8_t *buf)
{
struct ksz_device *dev = ds->priv;
int i;
@@ -2729,7 +2750,7 @@ static int ksz_pirq_setup(struct ksz_device *dev, u8 p)
static int ksz_parse_drive_strength(struct ksz_device *dev);
-static int ksz_setup(struct dsa_switch *ds)
+int ksz_setup(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
u16 storm_mask, storm_rate;
@@ -2859,7 +2880,7 @@ static int ksz_setup(struct dsa_switch *ds)
return ret;
}
-static void ksz_teardown(struct dsa_switch *ds)
+void ksz_teardown(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
struct dsa_port *dp;
@@ -2959,7 +2980,7 @@ void ksz_init_mib_timer(struct ksz_device *dev)
}
}
-static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
+int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
{
struct ksz_device *dev = ds->priv;
u16 val = 0xffff;
@@ -2972,7 +2993,7 @@ static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
return val;
}
-static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
+int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
{
struct ksz_device *dev = ds->priv;
int ret;
@@ -2984,7 +3005,7 @@ static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
return 0;
}
-static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
+u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
{
struct ksz_device *dev = ds->priv;
@@ -3016,7 +3037,7 @@ void ksz_phylink_mac_link_down(struct phylink_config *config,
schedule_delayed_work(&dev->mib_read, 0);
}
-static int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
+int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
{
struct ksz_device *dev = ds->priv;
@@ -3026,8 +3047,8 @@ static int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
return dev->info->mib_cnt;
}
-static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
- uint64_t *buf)
+void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
+ uint64_t *buf)
{
const struct dsa_port *dp = dsa_to_port(ds, port);
struct ksz_device *dev = ds->priv;
@@ -3044,10 +3065,10 @@ static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
mutex_unlock(&mib->cnt_mutex);
}
-static int ksz_port_bridge_join(struct dsa_switch *ds, int port,
- struct dsa_bridge bridge,
- bool *tx_fwd_offload,
- struct netlink_ext_ack *extack)
+int ksz_port_bridge_join(struct dsa_switch *ds, int port,
+ struct dsa_bridge bridge,
+ bool *tx_fwd_offload,
+ struct netlink_ext_ack *extack)
{
/* port_stp_state_set() will be called after to put the port in
* appropriate state so there is no need to do anything.
@@ -3056,22 +3077,22 @@ static int ksz_port_bridge_join(struct dsa_switch *ds, int port,
return 0;
}
-static void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
- struct dsa_bridge bridge)
+void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
+ struct dsa_bridge bridge)
{
/* port_stp_state_set() will be called after to put the port in
* forwarding state so there is no need to do anything.
*/
}
-static void ksz_port_fast_age(struct dsa_switch *ds, int port)
+void ksz_port_fast_age(struct dsa_switch *ds, int port)
{
struct ksz_device *dev = ds->priv;
dev->dev_ops->flush_dyn_mac_table(dev, port);
}
-static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
+int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
{
struct ksz_device *dev = ds->priv;
@@ -3081,9 +3102,9 @@ static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
return dev->dev_ops->set_ageing_time(dev, msecs);
}
-static int ksz_port_fdb_add(struct dsa_switch *ds, int port,
- const unsigned char *addr, u16 vid,
- struct dsa_db db)
+int ksz_port_fdb_add(struct dsa_switch *ds, int port,
+ const unsigned char *addr, u16 vid,
+ struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
@@ -3093,9 +3114,9 @@ static int ksz_port_fdb_add(struct dsa_switch *ds, int port,
return dev->dev_ops->fdb_add(dev, port, addr, vid, db);
}
-static int ksz_port_fdb_del(struct dsa_switch *ds, int port,
- const unsigned char *addr,
- u16 vid, struct dsa_db db)
+int ksz_port_fdb_del(struct dsa_switch *ds, int port,
+ const unsigned char *addr,
+ u16 vid, struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
@@ -3105,8 +3126,8 @@ static int ksz_port_fdb_del(struct dsa_switch *ds, int port,
return dev->dev_ops->fdb_del(dev, port, addr, vid, db);
}
-static int ksz_port_fdb_dump(struct dsa_switch *ds, int port,
- dsa_fdb_dump_cb_t *cb, void *data)
+int ksz_port_fdb_dump(struct dsa_switch *ds, int port,
+ dsa_fdb_dump_cb_t *cb, void *data)
{
struct ksz_device *dev = ds->priv;
@@ -3116,9 +3137,9 @@ static int ksz_port_fdb_dump(struct dsa_switch *ds, int port,
return dev->dev_ops->fdb_dump(dev, port, cb, data);
}
-static int ksz_port_mdb_add(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_mdb *mdb,
- struct dsa_db db)
+int ksz_port_mdb_add(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_mdb *mdb,
+ struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
@@ -3128,9 +3149,9 @@ static int ksz_port_mdb_add(struct dsa_switch *ds, int port,
return dev->dev_ops->mdb_add(dev, port, mdb, db);
}
-static int ksz_port_mdb_del(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_mdb *mdb,
- struct dsa_db db)
+int ksz_port_mdb_del(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_mdb *mdb,
+ struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
@@ -3163,7 +3184,7 @@ static int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev,
return ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4, queue_map);
}
-static int ksz_port_setup(struct dsa_switch *ds, int port)
+int ksz_port_setup(struct dsa_switch *ds, int port)
{
struct ksz_device *dev = ds->priv;
int ret;
@@ -3233,7 +3254,7 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
ksz_update_port_member(dev, port);
}
-static void ksz_port_teardown(struct dsa_switch *ds, int port)
+void ksz_port_teardown(struct dsa_switch *ds, int port)
{
struct ksz_device *dev = ds->priv;
@@ -3252,9 +3273,9 @@ static void ksz_port_teardown(struct dsa_switch *ds, int port)
}
}
-static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port,
- struct switchdev_brport_flags flags,
- struct netlink_ext_ack *extack)
+int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port,
+ struct switchdev_brport_flags flags,
+ struct netlink_ext_ack *extack)
{
if (flags.mask & ~(BR_LEARNING | BR_ISOLATED))
return -EINVAL;
@@ -3262,9 +3283,9 @@ static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port,
return 0;
}
-static int ksz_port_bridge_flags(struct dsa_switch *ds, int port,
- struct switchdev_brport_flags flags,
- struct netlink_ext_ack *extack)
+int ksz_port_bridge_flags(struct dsa_switch *ds, int port,
+ struct switchdev_brport_flags flags,
+ struct netlink_ext_ack *extack)
{
struct ksz_device *dev = ds->priv;
struct ksz_port *p = &dev->ports[port];
@@ -3283,9 +3304,9 @@ static int ksz_port_bridge_flags(struct dsa_switch *ds, int port,
return 0;
}
-static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
- int port,
- enum dsa_tag_protocol mp)
+enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
+ int port,
+ enum dsa_tag_protocol mp)
{
struct ksz_device *dev = ds->priv;
enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE;
@@ -3314,8 +3335,8 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
return proto;
}
-static int ksz_connect_tag_protocol(struct dsa_switch *ds,
- enum dsa_tag_protocol proto)
+int ksz_connect_tag_protocol(struct dsa_switch *ds,
+ enum dsa_tag_protocol proto)
{
struct ksz_tagger_data *tagger_data;
@@ -3333,8 +3354,8 @@ static int ksz_connect_tag_protocol(struct dsa_switch *ds,
}
}
-static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port,
- bool flag, struct netlink_ext_ack *extack)
+int ksz_port_vlan_filtering(struct dsa_switch *ds, int port,
+ bool flag, struct netlink_ext_ack *extack)
{
struct ksz_device *dev = ds->priv;
@@ -3344,9 +3365,9 @@ static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port,
return dev->dev_ops->vlan_filtering(dev, port, flag, extack);
}
-static int ksz_port_vlan_add(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_vlan *vlan,
- struct netlink_ext_ack *extack)
+int ksz_port_vlan_add(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct netlink_ext_ack *extack)
{
struct ksz_device *dev = ds->priv;
@@ -3356,8 +3377,8 @@ static int ksz_port_vlan_add(struct dsa_switch *ds, int port,
return dev->dev_ops->vlan_add(dev, port, vlan, extack);
}
-static int ksz_port_vlan_del(struct dsa_switch *ds, int port,
- const struct switchdev_obj_port_vlan *vlan)
+int ksz_port_vlan_del(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan)
{
struct ksz_device *dev = ds->priv;
@@ -3367,9 +3388,9 @@ static int ksz_port_vlan_del(struct dsa_switch *ds, int port,
return dev->dev_ops->vlan_del(dev, port, vlan);
}
-static int ksz_port_mirror_add(struct dsa_switch *ds, int port,
- struct dsa_mall_mirror_tc_entry *mirror,
- bool ingress, struct netlink_ext_ack *extack)
+int ksz_port_mirror_add(struct dsa_switch *ds, int port,
+ struct dsa_mall_mirror_tc_entry *mirror,
+ bool ingress, struct netlink_ext_ack *extack)
{
struct ksz_device *dev = ds->priv;
@@ -3379,8 +3400,8 @@ static int ksz_port_mirror_add(struct dsa_switch *ds, int port,
return dev->dev_ops->mirror_add(dev, port, mirror, ingress, extack);
}
-static void ksz_port_mirror_del(struct dsa_switch *ds, int port,
- struct dsa_mall_mirror_tc_entry *mirror)
+void ksz_port_mirror_del(struct dsa_switch *ds, int port,
+ struct dsa_mall_mirror_tc_entry *mirror)
{
struct ksz_device *dev = ds->priv;
@@ -3388,7 +3409,7 @@ static void ksz_port_mirror_del(struct dsa_switch *ds, int port,
dev->dev_ops->mirror_del(dev, port, mirror);
}
-static int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu)
+int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu)
{
struct ksz_device *dev = ds->priv;
@@ -3398,7 +3419,7 @@ static int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu)
return dev->dev_ops->change_mtu(dev, port, mtu);
}
-static int ksz_max_mtu(struct dsa_switch *ds, int port)
+int ksz_max_mtu(struct dsa_switch *ds, int port)
{
struct ksz_device *dev = ds->priv;
@@ -3446,7 +3467,7 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
* Returns: true if the internal PHY on the given port supports fully
* operational EEE, false otherwise.
*/
-static bool ksz_support_eee(struct dsa_switch *ds, int port)
+bool ksz_support_eee(struct dsa_switch *ds, int port)
{
struct ksz_device *dev = ds->priv;
@@ -3489,8 +3510,8 @@ static bool ksz_support_eee(struct dsa_switch *ds, int port)
return false;
}
-static int ksz_set_mac_eee(struct dsa_switch *ds, int port,
- struct ethtool_keee *e)
+int ksz_set_mac_eee(struct dsa_switch *ds, int port,
+ struct ethtool_keee *e)
{
struct ksz_device *dev = ds->priv;
@@ -3735,8 +3756,8 @@ static int ksz_switch_detect(struct ksz_device *dev)
return 0;
}
-static int ksz_cls_flower_add(struct dsa_switch *ds, int port,
- struct flow_cls_offload *cls, bool ingress)
+int ksz_cls_flower_add(struct dsa_switch *ds, int port,
+ struct flow_cls_offload *cls, bool ingress)
{
struct ksz_device *dev = ds->priv;
@@ -3756,8 +3777,8 @@ static int ksz_cls_flower_add(struct dsa_switch *ds, int port,
return -EOPNOTSUPP;
}
-static int ksz_cls_flower_del(struct dsa_switch *ds, int port,
- struct flow_cls_offload *cls, bool ingress)
+int ksz_cls_flower_del(struct dsa_switch *ds, int port,
+ struct flow_cls_offload *cls, bool ingress)
{
struct ksz_device *dev = ds->priv;
@@ -4160,8 +4181,8 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
return -EOPNOTSUPP;
}
-static int ksz_setup_tc(struct dsa_switch *ds, int port,
- enum tc_setup_type type, void *type_data)
+int ksz_setup_tc(struct dsa_switch *ds, int port,
+ enum tc_setup_type type, void *type_data)
{
switch (type) {
case TC_SETUP_QDISC_CBS:
@@ -4220,8 +4241,8 @@ int ksz_handle_wake_reason(struct ksz_device *dev, int port)
* If enabled and supported, it sets the supported and active WoL
* flags.
*/
-static void ksz_get_wol(struct dsa_switch *ds, int port,
- struct ethtool_wolinfo *wol)
+void ksz_get_wol(struct dsa_switch *ds, int port,
+ struct ethtool_wolinfo *wol)
{
struct ksz_device *dev = ds->priv;
const u16 *regs = dev->info->regs;
@@ -4268,8 +4289,8 @@ static void ksz_get_wol(struct dsa_switch *ds, int port,
*
* Return: 0 on success, or other error codes on failure.
*/
-static int ksz_set_wol(struct dsa_switch *ds, int port,
- struct ethtool_wolinfo *wol)
+int ksz_set_wol(struct dsa_switch *ds, int port,
+ struct ethtool_wolinfo *wol)
{
u8 pme_ctrl = 0, pme_ctrl_old = 0;
struct ksz_device *dev = ds->priv;
@@ -4383,8 +4404,8 @@ static void ksz_wol_pre_shutdown(struct ksz_device *dev, bool *wol_enabled)
}
}
-static int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
- const unsigned char *addr)
+int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
+ const unsigned char *addr)
{
struct dsa_port *dp = dsa_to_port(ds, port);
struct ethtool_wolinfo wol;
@@ -4536,8 +4557,8 @@ void ksz_switch_macaddr_put(struct dsa_switch *ds)
kfree(switch_macaddr);
}
-static int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr,
- struct netlink_ext_ack *extack)
+int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr,
+ struct netlink_ext_ack *extack)
{
struct ksz_device *dev = ds->priv;
enum hsr_version ver;
@@ -4585,8 +4606,8 @@ static int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr,
return 0;
}
-static int ksz_hsr_leave(struct dsa_switch *ds, int port,
- struct net_device *hsr)
+int ksz_hsr_leave(struct dsa_switch *ds, int port,
+ struct net_device *hsr)
{
struct ksz_device *dev = ds->priv;
@@ -4602,7 +4623,7 @@ static int ksz_hsr_leave(struct dsa_switch *ds, int port,
return 0;
}
-static int ksz_suspend(struct dsa_switch *ds)
+int ksz_suspend(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
@@ -4610,7 +4631,7 @@ static int ksz_suspend(struct dsa_switch *ds)
return 0;
}
-static int ksz_resume(struct dsa_switch *ds)
+int ksz_resume(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 519e080c8910e..125740deb5a21 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -73,6 +73,7 @@ struct ksz_chip_data {
*/
bool phy_side_mdio_supported;
const struct ksz_dev_ops *ops;
+ const struct dsa_switch_ops *switch_ops;
const struct phylink_mac_ops *phylink_mac_ops;
bool phy_errata_9477;
bool ksz87xx_eee_link_erratum;
@@ -465,6 +466,16 @@ void ksz_switch_remove(struct ksz_device *dev);
int ksz_switch_suspend(struct device *dev);
int ksz_switch_resume(struct device *dev);
+int ksz_setup(struct dsa_switch *ds);
+void ksz_teardown(struct dsa_switch *ds);
+int ksz_port_setup(struct dsa_switch *ds, int port);
+void ksz_port_teardown(struct dsa_switch *ds, int port);
+
+enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
+ int port,
+ enum dsa_tag_protocol mp);
+int ksz_connect_tag_protocol(struct dsa_switch *ds,
+ enum dsa_tag_protocol proto);
void ksz_init_mib_timer(struct ksz_device *dev);
bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port);
void ksz_r_mib_stats64(struct ksz_device *dev, int port);
@@ -479,6 +490,58 @@ void ksz_switch_macaddr_put(struct dsa_switch *ds);
void ksz_switch_shutdown(struct ksz_device *dev);
int ksz_handle_wake_reason(struct ksz_device *dev, int port);
+int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
+int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
+u32 ksz_get_phy_flags(struct dsa_switch *ds, int port);
+
+int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
+void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
+ uint64_t *buf);
+void ksz_get_stats64(struct dsa_switch *ds, int port,
+ struct rtnl_link_stats64 *s);
+void ksz_get_pause_stats(struct dsa_switch *ds, int port,
+ struct ethtool_pause_stats *pause_stats);
+void ksz_get_strings(struct dsa_switch *ds, int port,
+ u32 stringset, uint8_t *buf);
+
+int ksz_port_bridge_join(struct dsa_switch *ds, int port,
+ struct dsa_bridge bridge,
+ bool *tx_fwd_offload,
+ struct netlink_ext_ack *extack);
+void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
+ struct dsa_bridge bridge);
+int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port,
+ struct switchdev_brport_flags flags,
+ struct netlink_ext_ack *extack);
+int ksz_port_bridge_flags(struct dsa_switch *ds, int port,
+ struct switchdev_brport_flags flags,
+ struct netlink_ext_ack *extack);
+int ksz_port_vlan_filtering(struct dsa_switch *ds, int port,
+ bool flag, struct netlink_ext_ack *extack);
+int ksz_port_vlan_add(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct netlink_ext_ack *extack);
+int ksz_port_vlan_del(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan);
+void ksz_port_fast_age(struct dsa_switch *ds, int port);
+int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs);
+int ksz_port_fdb_add(struct dsa_switch *ds, int port,
+ const unsigned char *addr, u16 vid,
+ struct dsa_db db);
+int ksz_port_fdb_del(struct dsa_switch *ds, int port,
+ const unsigned char *addr,
+ u16 vid, struct dsa_db db);
+int ksz_port_fdb_dump(struct dsa_switch *ds, int port,
+ dsa_fdb_dump_cb_t *cb, void *data);
+int ksz_port_mdb_add(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_mdb *mdb,
+ struct dsa_db db);
+int ksz_port_mdb_del(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_mdb *mdb,
+ struct dsa_db db);
+
+void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config);
void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config);
int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config,
u32 timer, bool tx_clock_stop);
@@ -489,6 +552,39 @@ void ksz_phylink_mac_link_down(struct phylink_config *config,
unsigned int mode,
phy_interface_t interface);
+int ksz_port_mirror_add(struct dsa_switch *ds, int port,
+ struct dsa_mall_mirror_tc_entry *mirror,
+ bool ingress, struct netlink_ext_ack *extack);
+void ksz_port_mirror_del(struct dsa_switch *ds, int port,
+ struct dsa_mall_mirror_tc_entry *mirror);
+int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu);
+int ksz_max_mtu(struct dsa_switch *ds, int port);
+
+bool ksz_support_eee(struct dsa_switch *ds, int port);
+int ksz_set_mac_eee(struct dsa_switch *ds, int port,
+ struct ethtool_keee *e);
+
+int ksz_cls_flower_add(struct dsa_switch *ds, int port,
+ struct flow_cls_offload *cls, bool ingress);
+int ksz_cls_flower_del(struct dsa_switch *ds, int port,
+ struct flow_cls_offload *cls, bool ingress);
+int ksz_setup_tc(struct dsa_switch *ds, int port,
+ enum tc_setup_type type, void *type_data);
+
+void ksz_get_wol(struct dsa_switch *ds, int port,
+ struct ethtool_wolinfo *wol);
+int ksz_set_wol(struct dsa_switch *ds, int port,
+ struct ethtool_wolinfo *wol);
+int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
+ const unsigned char *addr);
+int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr,
+ struct netlink_ext_ack *extack);
+int ksz_hsr_leave(struct dsa_switch *ds, int port,
+ struct net_device *hsr);
+
+int ksz_suspend(struct dsa_switch *ds);
+int ksz_resume(struct dsa_switch *ds);
+
/* Common register access functions */
static inline struct regmap *ksz_regmap_8(struct ksz_device *dev)
{
diff --git a/drivers/net/dsa/microchip/lan937x.h b/drivers/net/dsa/microchip/lan937x.h
index c5e745a9f47f1..d12483f9081d8 100644
--- a/drivers/net/dsa/microchip/lan937x.h
+++ b/drivers/net/dsa/microchip/lan937x.h
@@ -8,5 +8,6 @@
extern const struct ksz_dev_ops lan937x_dev_ops;
extern const struct phylink_mac_ops lan937x_phylink_mac_ops;
+extern const struct dsa_switch_ops lan937x_switch_ops;
#endif
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 4846ae2a2d69a..ff931b1143a52 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -15,6 +15,7 @@
#include "lan937x_reg.h"
#include "ksz_common.h"
+#include "ksz_dcb.h"
#include "ksz9477.h"
#include "lan937x.h"
@@ -712,6 +713,67 @@ const struct ksz_dev_ops lan937x_dev_ops = {
.exit = lan937x_switch_exit,
};
+const struct dsa_switch_ops lan937x_switch_ops = {
+ .get_tag_protocol = ksz_get_tag_protocol,
+ .connect_tag_protocol = ksz_connect_tag_protocol,
+ .get_phy_flags = ksz_get_phy_flags,
+ .setup = ksz_setup,
+ .teardown = ksz_teardown,
+ .phy_read = ksz_phy_read16,
+ .phy_write = ksz_phy_write16,
+ .phylink_get_caps = ksz_phylink_get_caps,
+ .port_setup = ksz_port_setup,
+ .set_ageing_time = ksz_set_ageing_time,
+ .get_strings = ksz_get_strings,
+ .get_ethtool_stats = ksz_get_ethtool_stats,
+ .get_sset_count = ksz_sset_count,
+ .port_bridge_join = ksz_port_bridge_join,
+ .port_bridge_leave = ksz_port_bridge_leave,
+ .port_hsr_join = ksz_hsr_join,
+ .port_hsr_leave = ksz_hsr_leave,
+ .port_set_mac_address = ksz_port_set_mac_address,
+ .port_stp_state_set = ksz_port_stp_state_set,
+ .port_teardown = ksz_port_teardown,
+ .port_pre_bridge_flags = ksz_port_pre_bridge_flags,
+ .port_bridge_flags = ksz_port_bridge_flags,
+ .port_fast_age = ksz_port_fast_age,
+ .port_vlan_filtering = ksz_port_vlan_filtering,
+ .port_vlan_add = ksz_port_vlan_add,
+ .port_vlan_del = ksz_port_vlan_del,
+ .port_fdb_dump = ksz_port_fdb_dump,
+ .port_fdb_add = ksz_port_fdb_add,
+ .port_fdb_del = ksz_port_fdb_del,
+ .port_mdb_add = ksz_port_mdb_add,
+ .port_mdb_del = ksz_port_mdb_del,
+ .port_mirror_add = ksz_port_mirror_add,
+ .port_mirror_del = ksz_port_mirror_del,
+ .get_stats64 = ksz_get_stats64,
+ .get_pause_stats = ksz_get_pause_stats,
+ .port_change_mtu = ksz_change_mtu,
+ .port_max_mtu = ksz_max_mtu,
+ .get_wol = ksz_get_wol,
+ .set_wol = ksz_set_wol,
+ .suspend = ksz_suspend,
+ .resume = ksz_resume,
+ .get_ts_info = ksz_get_ts_info,
+ .port_hwtstamp_get = ksz_hwtstamp_get,
+ .port_hwtstamp_set = ksz_hwtstamp_set,
+ .port_txtstamp = ksz_port_txtstamp,
+ .port_rxtstamp = ksz_port_rxtstamp,
+ .cls_flower_add = ksz_cls_flower_add,
+ .cls_flower_del = ksz_cls_flower_del,
+ .port_setup_tc = ksz_setup_tc,
+ .support_eee = ksz_support_eee,
+ .set_mac_eee = ksz_set_mac_eee,
+ .port_get_default_prio = ksz_port_get_default_prio,
+ .port_set_default_prio = ksz_port_set_default_prio,
+ .port_get_dscp_prio = ksz_port_get_dscp_prio,
+ .port_add_dscp_prio = ksz_port_add_dscp_prio,
+ .port_del_dscp_prio = ksz_port_del_dscp_prio,
+ .port_get_apptrust = ksz_port_get_apptrust,
+ .port_set_apptrust = ksz_port_set_apptrust,
+};
+
MODULE_AUTHOR("Arun Ramadoss <arun.ramadoss@microchip.com>");
MODULE_DESCRIPTION("Microchip LAN937x Series Switch DSA Driver");
MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 5/9] net: dsa: microchip: move phylink_mac_ops to individual drivers
From: Bastien Curutchet @ 2026-05-05 14:25 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric), Vladimir Oltean
In-Reply-To: <20260505-clean-ksz-driver-v1-0-05d70fa42461@bootlin.com>
From: Vladimir Oltean <vladimir.oltean@nxp.com>
Similar to ksz_dev_ops, struct phylink_mac_ops shouldn't be part of
the common code. Instead, the common code should provide callable
functionality.
Invert the paradigm and export the common aspects from ksz_common.c, and
move the chip-specific stuff in individual drivers.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 36 +++++-
drivers/net/dsa/microchip/ksz8.h | 7 +-
drivers/net/dsa/microchip/ksz9477.c | 126 ++++++++++++++++++++
drivers/net/dsa/microchip/ksz9477.h | 8 ++
drivers/net/dsa/microchip/ksz_common.c | 194 ++-----------------------------
drivers/net/dsa/microchip/ksz_common.h | 10 ++
drivers/net/dsa/microchip/lan937x.h | 1 +
drivers/net/dsa/microchip/lan937x_main.c | 8 ++
8 files changed, 196 insertions(+), 194 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index 56560f60223a1..f311901c693f8 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -1870,10 +1870,12 @@ static void ksz8_cpu_port_link_up(struct ksz_device *dev, int speed, int duplex,
SW_10_MBIT, ctrl);
}
-void ksz8_phylink_mac_link_up(struct phylink_config *config,
- struct phy_device *phydev, unsigned int mode,
- phy_interface_t interface, int speed, int duplex,
- bool tx_pause, bool rx_pause)
+static void ksz8_phylink_mac_link_up(struct phylink_config *config,
+ struct phy_device *phydev,
+ unsigned int mode,
+ phy_interface_t interface,
+ int speed, int duplex,
+ bool tx_pause, bool rx_pause)
{
struct dsa_port *dp = dsa_phylink_to_port(config);
struct ksz_device *dev = dp->ds->priv;
@@ -2097,6 +2099,32 @@ static void ksz8_switch_exit(struct ksz_device *dev)
ksz8_reset_switch(dev);
}
+static void ksz88x3_phylink_mac_config(struct phylink_config *config,
+ unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ struct dsa_port *dp = dsa_phylink_to_port(config);
+ struct ksz_device *dev = dp->ds->priv;
+
+ dev->ports[dp->index].manual_flow = !(state->pause & MLO_PAUSE_AN);
+}
+
+const struct phylink_mac_ops ksz88x3_phylink_mac_ops = {
+ .mac_config = ksz88x3_phylink_mac_config,
+ .mac_link_down = ksz_phylink_mac_link_down,
+ .mac_link_up = ksz8_phylink_mac_link_up,
+ .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
+ .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
+};
+
+const struct phylink_mac_ops ksz8_phylink_mac_ops = {
+ .mac_config = ksz_phylink_mac_config,
+ .mac_link_down = ksz_phylink_mac_link_down,
+ .mac_link_up = ksz8_phylink_mac_link_up,
+ .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
+ .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
+};
+
const struct ksz_dev_ops ksz8463_dev_ops = {
.setup = ksz8_setup,
.get_port_addr = ksz8463_get_port_addr,
diff --git a/drivers/net/dsa/microchip/ksz8.h b/drivers/net/dsa/microchip/ksz8.h
index 4b798ce29daaf..2d787d6d96b05 100644
--- a/drivers/net/dsa/microchip/ksz8.h
+++ b/drivers/net/dsa/microchip/ksz8.h
@@ -12,13 +12,10 @@
#include <net/dsa.h>
#include "ksz_common.h"
-void ksz8_phylink_mac_link_up(struct phylink_config *config,
- struct phy_device *phydev, unsigned int mode,
- phy_interface_t interface, int speed, int duplex,
- bool tx_pause, bool rx_pause);
-
extern const struct ksz_dev_ops ksz8463_dev_ops;
extern const struct ksz_dev_ops ksz87xx_dev_ops;
extern const struct ksz_dev_ops ksz88xx_dev_ops;
+extern const struct phylink_mac_ops ksz88x3_phylink_mac_ops;
+extern const struct phylink_mac_ops ksz8_phylink_mac_ops;
#endif
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 3275996cda962..3fd2174364acf 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1609,6 +1609,132 @@ static void ksz9477_switch_exit(struct ksz_device *dev)
ksz9477_reset_switch(dev);
}
+static void ksz9477_set_gbit(struct ksz_device *dev, int port, bool gbit)
+{
+ const u8 *bitval = dev->info->xmii_ctrl1;
+ const u16 *regs = dev->info->regs;
+ u8 data8;
+
+ ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
+
+ data8 &= ~P_GMII_1GBIT_M;
+
+ if (gbit)
+ data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]);
+ else
+ data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]);
+
+ /* Write the updated value */
+ ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8);
+}
+
+static void ksz9477_set_100_10mbit(struct ksz_device *dev, int port, int speed)
+{
+ const u8 *bitval = dev->info->xmii_ctrl0;
+ const u16 *regs = dev->info->regs;
+ u8 data8;
+
+ ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8);
+
+ data8 &= ~P_MII_100MBIT_M;
+
+ if (speed == SPEED_100)
+ data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]);
+ else
+ data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]);
+
+ /* Write the updated value */
+ ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8);
+}
+
+static void ksz9477_port_set_xmii_speed(struct ksz_device *dev, int port,
+ int speed)
+{
+ if (speed == SPEED_1000)
+ ksz9477_set_gbit(dev, port, true);
+ else
+ ksz9477_set_gbit(dev, port, false);
+
+ if (speed == SPEED_100 || speed == SPEED_10)
+ ksz9477_set_100_10mbit(dev, port, speed);
+}
+
+static void ksz9477_duplex_flowctrl(struct ksz_device *dev, int port, int duplex,
+ bool tx_pause, bool rx_pause)
+{
+ const u8 *bitval = dev->info->xmii_ctrl0;
+ const u32 *masks = dev->info->masks;
+ const u16 *regs = dev->info->regs;
+ u8 mask;
+ u8 val;
+
+ mask = P_MII_DUPLEX_M | masks[P_MII_TX_FLOW_CTRL] |
+ masks[P_MII_RX_FLOW_CTRL];
+
+ if (duplex == DUPLEX_FULL)
+ val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]);
+ else
+ val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]);
+
+ if (tx_pause)
+ val |= masks[P_MII_TX_FLOW_CTRL];
+
+ if (rx_pause)
+ val |= masks[P_MII_RX_FLOW_CTRL];
+
+ ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val);
+}
+
+void ksz9477_phylink_mac_link_up(struct phylink_config *config,
+ struct phy_device *phydev,
+ unsigned int mode,
+ phy_interface_t interface,
+ int speed, int duplex, bool tx_pause,
+ bool rx_pause)
+{
+ struct dsa_port *dp = dsa_phylink_to_port(config);
+ struct ksz_device *dev = dp->ds->priv;
+ int port = dp->index;
+ struct ksz_port *p;
+
+ p = &dev->ports[port];
+
+ /* Internal PHYs */
+ if (dev->info->internal_phy[port])
+ return;
+
+ p->speed = speed;
+
+ ksz9477_port_set_xmii_speed(dev, port, speed);
+
+ ksz9477_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause);
+}
+
+static struct phylink_pcs *
+ksz9477_phylink_mac_select_pcs(struct phylink_config *config,
+ phy_interface_t interface)
+{
+ struct dsa_port *dp = dsa_phylink_to_port(config);
+ struct ksz_device *dev = dp->ds->priv;
+ struct ksz_port *p = &dev->ports[dp->index];
+
+ if (ksz_is_sgmii_port(dev, dp->index) &&
+ (interface == PHY_INTERFACE_MODE_SGMII ||
+ interface == PHY_INTERFACE_MODE_1000BASEX))
+ return p->pcs;
+
+ return NULL;
+}
+
+const struct phylink_mac_ops ksz9477_phylink_mac_ops = {
+ .mac_config = ksz_phylink_mac_config,
+ .mac_link_down = ksz_phylink_mac_link_down,
+ .mac_link_up = ksz9477_phylink_mac_link_up,
+ .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
+ .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
+ .mac_select_pcs = ksz9477_phylink_mac_select_pcs,
+};
+
const struct ksz_dev_ops ksz9477_dev_ops = {
.setup = ksz9477_setup,
.get_port_addr = ksz9477_get_port_addr,
diff --git a/drivers/net/dsa/microchip/ksz9477.h b/drivers/net/dsa/microchip/ksz9477.h
index 30ab0c8807dbc..26a91f1a4c871 100644
--- a/drivers/net/dsa/microchip/ksz9477.h
+++ b/drivers/net/dsa/microchip/ksz9477.h
@@ -84,6 +84,14 @@ void ksz9477_acl_match_process_l2(struct ksz_device *dev, int port,
u16 ethtype, u8 *src_mac, u8 *dst_mac,
unsigned long cookie, u32 prio);
+void ksz9477_phylink_mac_link_up(struct phylink_config *config,
+ struct phy_device *phydev,
+ unsigned int mode,
+ phy_interface_t interface,
+ int speed, int duplex, bool tx_pause,
+ bool rx_pause);
+
extern const struct ksz_dev_ops ksz9477_dev_ops;
+extern const struct phylink_mac_ops ksz9477_phylink_mac_ops;
#endif
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 88446bc32465f..308740829e76c 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -256,16 +256,6 @@ static const struct ksz_drive_strength ksz88x3_drive_strengths[] = {
{ KSZ8873_DRIVE_STRENGTH_16MA, 16000 },
};
-static void ksz88x3_phylink_mac_config(struct phylink_config *config,
- unsigned int mode,
- const struct phylink_link_state *state);
-static void ksz_phylink_mac_config(struct phylink_config *config,
- unsigned int mode,
- const struct phylink_link_state *state);
-static void ksz_phylink_mac_link_down(struct phylink_config *config,
- unsigned int mode,
- phy_interface_t interface);
-
/**
* ksz_phylink_mac_disable_tx_lpi() - Callback to signal LPI support (Dummy)
* @config: phylink config structure
@@ -273,7 +263,7 @@ static void ksz_phylink_mac_link_down(struct phylink_config *config,
* This function is a dummy handler. See ksz_phylink_mac_enable_tx_lpi() for
* a detailed explanation of EEE/LPI handling in KSZ switches.
*/
-static void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config)
+void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config)
{
}
@@ -310,68 +300,12 @@ static void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config)
*
* Returns: 0 (Always success)
*/
-static int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config,
- u32 timer, bool tx_clock_stop)
+int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config,
+ u32 timer, bool tx_clock_stop)
{
return 0;
}
-static const struct phylink_mac_ops ksz88x3_phylink_mac_ops = {
- .mac_config = ksz88x3_phylink_mac_config,
- .mac_link_down = ksz_phylink_mac_link_down,
- .mac_link_up = ksz8_phylink_mac_link_up,
- .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
- .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
-};
-
-static const struct phylink_mac_ops ksz8_phylink_mac_ops = {
- .mac_config = ksz_phylink_mac_config,
- .mac_link_down = ksz_phylink_mac_link_down,
- .mac_link_up = ksz8_phylink_mac_link_up,
- .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
- .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
-};
-
-static void ksz9477_phylink_mac_link_up(struct phylink_config *config,
- struct phy_device *phydev,
- unsigned int mode,
- phy_interface_t interface,
- int speed, int duplex, bool tx_pause,
- bool rx_pause);
-
-static struct phylink_pcs *
-ksz_phylink_mac_select_pcs(struct phylink_config *config,
- phy_interface_t interface)
-{
- struct dsa_port *dp = dsa_phylink_to_port(config);
- struct ksz_device *dev = dp->ds->priv;
- struct ksz_port *p = &dev->ports[dp->index];
-
- if (ksz_is_sgmii_port(dev, dp->index) &&
- (interface == PHY_INTERFACE_MODE_SGMII ||
- interface == PHY_INTERFACE_MODE_1000BASEX))
- return p->pcs;
-
- return NULL;
-}
-
-static const struct phylink_mac_ops ksz9477_phylink_mac_ops = {
- .mac_config = ksz_phylink_mac_config,
- .mac_link_down = ksz_phylink_mac_link_down,
- .mac_link_up = ksz9477_phylink_mac_link_up,
- .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
- .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
- .mac_select_pcs = ksz_phylink_mac_select_pcs,
-};
-
-static const struct phylink_mac_ops lan937x_phylink_mac_ops = {
- .mac_config = ksz_phylink_mac_config,
- .mac_link_down = ksz_phylink_mac_link_down,
- .mac_link_up = ksz9477_phylink_mac_link_up,
- .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
- .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
-};
-
static const u16 ksz8463_regs[] = {
[REG_SW_MAC_ADDR] = 0x10,
[REG_IND_CTRL_0] = 0x30,
@@ -3068,9 +3002,9 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
return 0;
}
-static void ksz_phylink_mac_link_down(struct phylink_config *config,
- unsigned int mode,
- phy_interface_t interface)
+void ksz_phylink_mac_link_down(struct phylink_config *config,
+ unsigned int mode,
+ phy_interface_t interface)
{
struct dsa_port *dp = dsa_phylink_to_port(config);
struct ksz_device *dev = dp->ds->priv;
@@ -3657,19 +3591,9 @@ phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit)
return interface;
}
-static void ksz88x3_phylink_mac_config(struct phylink_config *config,
- unsigned int mode,
- const struct phylink_link_state *state)
-{
- struct dsa_port *dp = dsa_phylink_to_port(config);
- struct ksz_device *dev = dp->ds->priv;
-
- dev->ports[dp->index].manual_flow = !(state->pause & MLO_PAUSE_AN);
-}
-
-static void ksz_phylink_mac_config(struct phylink_config *config,
- unsigned int mode,
- const struct phylink_link_state *state)
+void ksz_phylink_mac_config(struct phylink_config *config,
+ unsigned int mode,
+ const struct phylink_link_state *state)
{
struct dsa_port *dp = dsa_phylink_to_port(config);
struct ksz_device *dev = dp->ds->priv;
@@ -3712,106 +3636,6 @@ bool ksz_get_gbit(struct ksz_device *dev, int port)
return gbit;
}
-static void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit)
-{
- const u8 *bitval = dev->info->xmii_ctrl1;
- const u16 *regs = dev->info->regs;
- u8 data8;
-
- ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
-
- data8 &= ~P_GMII_1GBIT_M;
-
- if (gbit)
- data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]);
- else
- data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]);
-
- /* Write the updated value */
- ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8);
-}
-
-static void ksz_set_100_10mbit(struct ksz_device *dev, int port, int speed)
-{
- const u8 *bitval = dev->info->xmii_ctrl0;
- const u16 *regs = dev->info->regs;
- u8 data8;
-
- ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8);
-
- data8 &= ~P_MII_100MBIT_M;
-
- if (speed == SPEED_100)
- data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]);
- else
- data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]);
-
- /* Write the updated value */
- ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8);
-}
-
-static void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed)
-{
- if (speed == SPEED_1000)
- ksz_set_gbit(dev, port, true);
- else
- ksz_set_gbit(dev, port, false);
-
- if (speed == SPEED_100 || speed == SPEED_10)
- ksz_set_100_10mbit(dev, port, speed);
-}
-
-static void ksz_duplex_flowctrl(struct ksz_device *dev, int port, int duplex,
- bool tx_pause, bool rx_pause)
-{
- const u8 *bitval = dev->info->xmii_ctrl0;
- const u32 *masks = dev->info->masks;
- const u16 *regs = dev->info->regs;
- u8 mask;
- u8 val;
-
- mask = P_MII_DUPLEX_M | masks[P_MII_TX_FLOW_CTRL] |
- masks[P_MII_RX_FLOW_CTRL];
-
- if (duplex == DUPLEX_FULL)
- val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]);
- else
- val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]);
-
- if (tx_pause)
- val |= masks[P_MII_TX_FLOW_CTRL];
-
- if (rx_pause)
- val |= masks[P_MII_RX_FLOW_CTRL];
-
- ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val);
-}
-
-static void ksz9477_phylink_mac_link_up(struct phylink_config *config,
- struct phy_device *phydev,
- unsigned int mode,
- phy_interface_t interface,
- int speed, int duplex, bool tx_pause,
- bool rx_pause)
-{
- struct dsa_port *dp = dsa_phylink_to_port(config);
- struct ksz_device *dev = dp->ds->priv;
- int port = dp->index;
- struct ksz_port *p;
-
- p = &dev->ports[port];
-
- /* Internal PHYs */
- if (dev->info->internal_phy[port])
- return;
-
- p->speed = speed;
-
- ksz_port_set_xmii_speed(dev, port, speed);
-
- ksz_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause);
-}
-
static int ksz_switch_detect(struct ksz_device *dev)
{
u8 id1, id2, id4;
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index cf2d0d91f1732..519e080c8910e 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -479,6 +479,16 @@ void ksz_switch_macaddr_put(struct dsa_switch *ds);
void ksz_switch_shutdown(struct ksz_device *dev);
int ksz_handle_wake_reason(struct ksz_device *dev, int port);
+void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config);
+int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config,
+ u32 timer, bool tx_clock_stop);
+void ksz_phylink_mac_config(struct phylink_config *config,
+ unsigned int mode,
+ const struct phylink_link_state *state);
+void ksz_phylink_mac_link_down(struct phylink_config *config,
+ unsigned int mode,
+ phy_interface_t interface);
+
/* Common register access functions */
static inline struct regmap *ksz_regmap_8(struct ksz_device *dev)
{
diff --git a/drivers/net/dsa/microchip/lan937x.h b/drivers/net/dsa/microchip/lan937x.h
index 48fc497750943..c5e745a9f47f1 100644
--- a/drivers/net/dsa/microchip/lan937x.h
+++ b/drivers/net/dsa/microchip/lan937x.h
@@ -7,5 +7,6 @@
#define __LAN937X_CFG_H
extern const struct ksz_dev_ops lan937x_dev_ops;
+extern const struct phylink_mac_ops lan937x_phylink_mac_ops;
#endif
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index ced381f67392b..4846ae2a2d69a 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -666,6 +666,14 @@ static void lan937x_switch_exit(struct ksz_device *dev)
lan937x_reset_switch(dev);
}
+const struct phylink_mac_ops lan937x_phylink_mac_ops = {
+ .mac_config = ksz_phylink_mac_config,
+ .mac_link_down = ksz_phylink_mac_link_down,
+ .mac_link_up = ksz9477_phylink_mac_link_up,
+ .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
+ .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
+};
+
const struct ksz_dev_ops lan937x_dev_ops = {
.setup = lan937x_setup,
.teardown = lan937x_teardown,
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 4/9] net: dsa: microchip: move KSZ9477 and LAN937 ksz_dev_ops to individual drivers
From: Bastien Curutchet @ 2026-05-05 14:25 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric), Vladimir Oltean
In-Reply-To: <20260505-clean-ksz-driver-v1-0-05d70fa42461@bootlin.com>
From: Vladimir Oltean <vladimir.oltean@nxp.com>
The ksz_dev_ops() are specific to each switch family so they should
belong to the individual drivers instead of the common section.
Move the ksz_dev_ops() definitions of the KSZ9477 and the LAN937 to
their individual drivers.
Set static the functions that aren't exported anymore.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz9477.c | 66 +++++++++++++++++++++------
drivers/net/dsa/microchip/ksz9477.h | 15 +------
drivers/net/dsa/microchip/ksz_common.c | 76 --------------------------------
drivers/net/dsa/microchip/lan937x.h | 19 +-------
drivers/net/dsa/microchip/lan937x_main.c | 72 +++++++++++++++++++++++-------
5 files changed, 110 insertions(+), 138 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index d3c23dcaea8ca..3275996cda962 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -43,7 +43,7 @@ static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
bits, set ? bits : 0);
}
-int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu)
+static int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu)
{
u16 frame_size;
@@ -308,7 +308,7 @@ static int ksz9477_pcs_write(struct mii_bus *bus, int phy, int mmd, int reg,
return 0;
}
-int ksz9477_pcs_create(struct ksz_device *dev)
+static int ksz9477_pcs_create(struct ksz_device *dev)
{
int port = ksz_get_sgmii_port(dev);
struct ksz_port *p = &dev->ports[port];
@@ -341,7 +341,7 @@ int ksz9477_pcs_create(struct ksz_device *dev)
return 0;
}
-int ksz9477_reset_switch(struct ksz_device *dev)
+static int ksz9477_reset_switch(struct ksz_device *dev)
{
u8 data8;
u32 data32;
@@ -516,7 +516,7 @@ static void ksz9477_r_phy_quirks(struct ksz_device *dev, u16 addr, u16 reg,
*data &= ~(BMSR_ESTATEN | BMSR_ERCAP);
}
-int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
+static int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
{
u16 val = 0xffff;
int ret;
@@ -572,7 +572,7 @@ int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
return 0;
}
-int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
+static int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
{
u32 mask, val32;
@@ -1150,8 +1150,8 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
return interface;
}
-void ksz9477_get_caps(struct ksz_device *dev, int port,
- struct phylink_config *config)
+static void ksz9477_get_caps(struct ksz_device *dev, int port,
+ struct phylink_config *config)
{
config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE |
MAC_SYM_PAUSE;
@@ -1168,7 +1168,7 @@ void ksz9477_get_caps(struct ksz_device *dev, int port,
}
}
-int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
+static int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
{
u32 secs = msecs / 1000;
u8 data, mult, value;
@@ -1234,7 +1234,7 @@ void ksz9477_port_queue_split(struct ksz_device *dev, int port)
ksz_prmw8(dev, port, REG_PORT_CTRL_0, PORT_QUEUE_SPLIT_MASK, data);
}
-void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
+static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{
const u16 *regs = dev->info->regs;
struct dsa_switch *ds = dev->ds;
@@ -1289,7 +1289,7 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
ksz_pwrite8(dev, port, regs[REG_PORT_PME_CTRL], 0);
}
-void ksz9477_config_cpu_port(struct dsa_switch *ds)
+static void ksz9477_config_cpu_port(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
struct ksz_port *p;
@@ -1454,7 +1454,7 @@ int ksz9477_enable_stp_addr(struct ksz_device *dev)
return 0;
}
-int ksz9477_setup(struct dsa_switch *ds)
+static int ksz9477_setup(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
const u16 *regs = dev->info->regs;
@@ -1500,7 +1500,7 @@ u32 ksz9477_get_port_addr(int port, int offset)
return PORT_CTRL_ADDR(port, offset);
}
-int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val)
+static int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val)
{
val = val >> 8;
@@ -1584,7 +1584,7 @@ void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct net_device *hsr)
ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL, PORT_SRC_ADDR_FILTER, false);
}
-int ksz9477_switch_init(struct ksz_device *dev)
+static int ksz9477_switch_init(struct ksz_device *dev)
{
u8 data8;
int ret;
@@ -1604,11 +1604,49 @@ int ksz9477_switch_init(struct ksz_device *dev)
return 0;
}
-void ksz9477_switch_exit(struct ksz_device *dev)
+static void ksz9477_switch_exit(struct ksz_device *dev)
{
ksz9477_reset_switch(dev);
}
+const struct ksz_dev_ops ksz9477_dev_ops = {
+ .setup = ksz9477_setup,
+ .get_port_addr = ksz9477_get_port_addr,
+ .cfg_port_member = ksz9477_cfg_port_member,
+ .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
+ .port_setup = ksz9477_port_setup,
+ .set_ageing_time = ksz9477_set_ageing_time,
+ .r_phy = ksz9477_r_phy,
+ .w_phy = ksz9477_w_phy,
+ .r_mib_cnt = ksz9477_r_mib_cnt,
+ .r_mib_pkt = ksz9477_r_mib_pkt,
+ .r_mib_stat64 = ksz_r_mib_stats64,
+ .freeze_mib = ksz9477_freeze_mib,
+ .port_init_cnt = ksz9477_port_init_cnt,
+ .vlan_filtering = ksz9477_port_vlan_filtering,
+ .vlan_add = ksz9477_port_vlan_add,
+ .vlan_del = ksz9477_port_vlan_del,
+ .mirror_add = ksz9477_port_mirror_add,
+ .mirror_del = ksz9477_port_mirror_del,
+ .get_caps = ksz9477_get_caps,
+ .fdb_dump = ksz9477_fdb_dump,
+ .fdb_add = ksz9477_fdb_add,
+ .fdb_del = ksz9477_fdb_del,
+ .mdb_add = ksz9477_mdb_add,
+ .mdb_del = ksz9477_mdb_del,
+ .change_mtu = ksz9477_change_mtu,
+ .pme_write8 = ksz_write8,
+ .pme_pread8 = ksz_pread8,
+ .pme_pwrite8 = ksz_pwrite8,
+ .config_cpu_port = ksz9477_config_cpu_port,
+ .tc_cbs_set_cinc = ksz9477_tc_cbs_set_cinc,
+ .enable_stp_addr = ksz9477_enable_stp_addr,
+ .reset = ksz9477_reset_switch,
+ .init = ksz9477_switch_init,
+ .exit = ksz9477_switch_exit,
+ .pcs_create = ksz9477_pcs_create,
+};
+
MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>");
MODULE_DESCRIPTION("Microchip KSZ9477 Series Switch DSA Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/microchip/ksz9477.h b/drivers/net/dsa/microchip/ksz9477.h
index 0d1a6dfda23ea..30ab0c8807dbc 100644
--- a/drivers/net/dsa/microchip/ksz9477.h
+++ b/drivers/net/dsa/microchip/ksz9477.h
@@ -11,14 +11,9 @@
#include <net/dsa.h>
#include "ksz_common.h"
-int ksz9477_setup(struct dsa_switch *ds);
u32 ksz9477_get_port_addr(int port, int offset);
void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member);
void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port);
-void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port);
-int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs);
-int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
-int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt);
void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
u64 *dropped, u64 *cnt);
@@ -38,8 +33,6 @@ void ksz9477_port_mirror_del(struct ksz_device *dev, int port,
struct dsa_mall_mirror_tc_entry *mirror);
int ksz9477_errata_monitor(struct ksz_device *dev, int port,
u64 tx_late_col);
-void ksz9477_get_caps(struct ksz_device *dev, int port,
- struct phylink_config *config);
int ksz9477_fdb_dump(struct ksz_device *dev, int port,
dsa_fdb_dump_cb_t *cb, void *data);
int ksz9477_fdb_add(struct ksz_device *dev, int port,
@@ -50,13 +43,7 @@ int ksz9477_mdb_add(struct ksz_device *dev, int port,
const struct switchdev_obj_port_mdb *mdb, struct dsa_db db);
int ksz9477_mdb_del(struct ksz_device *dev, int port,
const struct switchdev_obj_port_mdb *mdb, struct dsa_db db);
-int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu);
-void ksz9477_config_cpu_port(struct dsa_switch *ds);
-int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val);
int ksz9477_enable_stp_addr(struct ksz_device *dev);
-int ksz9477_reset_switch(struct ksz_device *dev);
-int ksz9477_switch_init(struct ksz_device *dev);
-void ksz9477_switch_exit(struct ksz_device *dev);
void ksz9477_port_queue_split(struct ksz_device *dev, int port);
void ksz9477_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr);
void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct net_device *hsr);
@@ -97,6 +84,6 @@ void ksz9477_acl_match_process_l2(struct ksz_device *dev, int port,
u16 ethtype, u8 *src_mac, u8 *dst_mac,
unsigned long cookie, u32 prio);
-int ksz9477_pcs_create(struct ksz_device *dev);
+extern const struct ksz_dev_ops ksz9477_dev_ops;
#endif
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 4d7834149d0c0..88446bc32465f 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -364,44 +364,6 @@ static const struct phylink_mac_ops ksz9477_phylink_mac_ops = {
.mac_select_pcs = ksz_phylink_mac_select_pcs,
};
-static const struct ksz_dev_ops ksz9477_dev_ops = {
- .setup = ksz9477_setup,
- .get_port_addr = ksz9477_get_port_addr,
- .cfg_port_member = ksz9477_cfg_port_member,
- .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
- .port_setup = ksz9477_port_setup,
- .set_ageing_time = ksz9477_set_ageing_time,
- .r_phy = ksz9477_r_phy,
- .w_phy = ksz9477_w_phy,
- .r_mib_cnt = ksz9477_r_mib_cnt,
- .r_mib_pkt = ksz9477_r_mib_pkt,
- .r_mib_stat64 = ksz_r_mib_stats64,
- .freeze_mib = ksz9477_freeze_mib,
- .port_init_cnt = ksz9477_port_init_cnt,
- .vlan_filtering = ksz9477_port_vlan_filtering,
- .vlan_add = ksz9477_port_vlan_add,
- .vlan_del = ksz9477_port_vlan_del,
- .mirror_add = ksz9477_port_mirror_add,
- .mirror_del = ksz9477_port_mirror_del,
- .get_caps = ksz9477_get_caps,
- .fdb_dump = ksz9477_fdb_dump,
- .fdb_add = ksz9477_fdb_add,
- .fdb_del = ksz9477_fdb_del,
- .mdb_add = ksz9477_mdb_add,
- .mdb_del = ksz9477_mdb_del,
- .change_mtu = ksz9477_change_mtu,
- .pme_write8 = ksz_write8,
- .pme_pread8 = ksz_pread8,
- .pme_pwrite8 = ksz_pwrite8,
- .config_cpu_port = ksz9477_config_cpu_port,
- .tc_cbs_set_cinc = ksz9477_tc_cbs_set_cinc,
- .enable_stp_addr = ksz9477_enable_stp_addr,
- .reset = ksz9477_reset_switch,
- .init = ksz9477_switch_init,
- .exit = ksz9477_switch_exit,
- .pcs_create = ksz9477_pcs_create,
-};
-
static const struct phylink_mac_ops lan937x_phylink_mac_ops = {
.mac_config = ksz_phylink_mac_config,
.mac_link_down = ksz_phylink_mac_link_down,
@@ -410,44 +372,6 @@ static const struct phylink_mac_ops lan937x_phylink_mac_ops = {
.mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
};
-static const struct ksz_dev_ops lan937x_dev_ops = {
- .setup = lan937x_setup,
- .teardown = lan937x_teardown,
- .get_port_addr = ksz9477_get_port_addr,
- .cfg_port_member = ksz9477_cfg_port_member,
- .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
- .port_setup = lan937x_port_setup,
- .set_ageing_time = lan937x_set_ageing_time,
- .mdio_bus_preinit = lan937x_mdio_bus_preinit,
- .create_phy_addr_map = lan937x_create_phy_addr_map,
- .r_phy = lan937x_r_phy,
- .w_phy = lan937x_w_phy,
- .r_mib_cnt = ksz9477_r_mib_cnt,
- .r_mib_pkt = ksz9477_r_mib_pkt,
- .r_mib_stat64 = ksz_r_mib_stats64,
- .freeze_mib = ksz9477_freeze_mib,
- .port_init_cnt = ksz9477_port_init_cnt,
- .vlan_filtering = ksz9477_port_vlan_filtering,
- .vlan_add = ksz9477_port_vlan_add,
- .vlan_del = ksz9477_port_vlan_del,
- .mirror_add = ksz9477_port_mirror_add,
- .mirror_del = ksz9477_port_mirror_del,
- .get_caps = lan937x_phylink_get_caps,
- .setup_rgmii_delay = lan937x_setup_rgmii_delay,
- .fdb_dump = ksz9477_fdb_dump,
- .fdb_add = ksz9477_fdb_add,
- .fdb_del = ksz9477_fdb_del,
- .mdb_add = ksz9477_mdb_add,
- .mdb_del = ksz9477_mdb_del,
- .change_mtu = lan937x_change_mtu,
- .config_cpu_port = lan937x_config_cpu_port,
- .tc_cbs_set_cinc = lan937x_tc_cbs_set_cinc,
- .enable_stp_addr = ksz9477_enable_stp_addr,
- .reset = lan937x_reset_switch,
- .init = lan937x_switch_init,
- .exit = lan937x_switch_exit,
-};
-
static const u16 ksz8463_regs[] = {
[REG_SW_MAC_ADDR] = 0x10,
[REG_IND_CTRL_0] = 0x30,
diff --git a/drivers/net/dsa/microchip/lan937x.h b/drivers/net/dsa/microchip/lan937x.h
index df13ebbd356f9..48fc497750943 100644
--- a/drivers/net/dsa/microchip/lan937x.h
+++ b/drivers/net/dsa/microchip/lan937x.h
@@ -6,21 +6,6 @@
#ifndef __LAN937X_CFG_H
#define __LAN937X_CFG_H
-int lan937x_reset_switch(struct ksz_device *dev);
-int lan937x_setup(struct dsa_switch *ds);
-void lan937x_teardown(struct dsa_switch *ds);
-void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port);
-void lan937x_config_cpu_port(struct dsa_switch *ds);
-int lan937x_switch_init(struct ksz_device *dev);
-void lan937x_switch_exit(struct ksz_device *dev);
-int lan937x_mdio_bus_preinit(struct ksz_device *dev, bool side_mdio);
-int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio);
-int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
-int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
-int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu);
-void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
- struct phylink_config *config);
-void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port);
-int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs);
-int lan937x_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val);
+extern const struct ksz_dev_ops lan937x_dev_ops;
+
#endif
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 5a1496fff4452..ced381f67392b 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -137,7 +137,7 @@ static int lan937x_port_cfg(struct ksz_device *dev, int port, int offset,
*
* Return: 0 on success, error code on failure.
*/
-int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio)
+static int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio)
{
static const u8 *phy_addr_map;
u32 strap_val;
@@ -221,7 +221,7 @@ int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio)
*
* Return: 0 on success, error code on failure.
*/
-int lan937x_mdio_bus_preinit(struct ksz_device *dev, bool side_mdio)
+static int lan937x_mdio_bus_preinit(struct ksz_device *dev, bool side_mdio)
{
u16 data16;
int ret;
@@ -332,17 +332,17 @@ static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg,
return ksz_read16(dev, REG_VPHY_IND_DATA__2, val);
}
-int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
+static int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
{
return lan937x_internal_phy_read(dev, addr, reg, data);
}
-int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
+static int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
{
return lan937x_internal_phy_write(dev, addr, reg, val);
}
-int lan937x_reset_switch(struct ksz_device *dev)
+static int lan937x_reset_switch(struct ksz_device *dev)
{
u32 data32;
int ret;
@@ -373,7 +373,7 @@ int lan937x_reset_switch(struct ksz_device *dev)
return ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32);
}
-void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port)
+static void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{
const u32 *masks = dev->info->masks;
const u16 *regs = dev->info->regs;
@@ -409,7 +409,7 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port)
dev->dev_ops->cfg_port_member(dev, port, member);
}
-void lan937x_config_cpu_port(struct dsa_switch *ds)
+static void lan937x_config_cpu_port(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
struct dsa_port *dp;
@@ -428,7 +428,7 @@ void lan937x_config_cpu_port(struct dsa_switch *ds)
}
}
-int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu)
+static int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu)
{
struct dsa_switch *ds = dev->ds;
int ret;
@@ -459,7 +459,7 @@ int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu)
return 0;
}
-int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
+static int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
{
u8 data, mult, value8;
bool in_msec = false;
@@ -572,8 +572,8 @@ static void lan937x_set_rgmii_rx_delay(struct ksz_device *dev, int port)
lan937x_set_tune_adj(dev, port, REG_PORT_XMII_CTRL_4, val);
}
-void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
- struct phylink_config *config)
+static void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
+ struct phylink_config *config)
{
config->mac_capabilities = MAC_100FD;
@@ -587,7 +587,7 @@ void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
}
}
-void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port)
+static void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port)
{
struct ksz_port *p = &dev->ports[port];
@@ -604,19 +604,19 @@ void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port)
}
}
-int lan937x_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val)
+static int lan937x_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val)
{
return ksz_pwrite32(dev, port, REG_PORT_MTI_CREDIT_INCREMENT, val);
}
-int lan937x_switch_init(struct ksz_device *dev)
+static int lan937x_switch_init(struct ksz_device *dev)
{
dev->port_mask = (1 << dev->info->port_cnt) - 1;
return 0;
}
-int lan937x_setup(struct dsa_switch *ds)
+static int lan937x_setup(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
int ret;
@@ -656,16 +656,54 @@ int lan937x_setup(struct dsa_switch *ds)
SW_VPHY_DISABLE);
}
-void lan937x_teardown(struct dsa_switch *ds)
+static void lan937x_teardown(struct dsa_switch *ds)
{
}
-void lan937x_switch_exit(struct ksz_device *dev)
+static void lan937x_switch_exit(struct ksz_device *dev)
{
lan937x_reset_switch(dev);
}
+const struct ksz_dev_ops lan937x_dev_ops = {
+ .setup = lan937x_setup,
+ .teardown = lan937x_teardown,
+ .get_port_addr = ksz9477_get_port_addr,
+ .cfg_port_member = ksz9477_cfg_port_member,
+ .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
+ .port_setup = lan937x_port_setup,
+ .set_ageing_time = lan937x_set_ageing_time,
+ .mdio_bus_preinit = lan937x_mdio_bus_preinit,
+ .create_phy_addr_map = lan937x_create_phy_addr_map,
+ .r_phy = lan937x_r_phy,
+ .w_phy = lan937x_w_phy,
+ .r_mib_cnt = ksz9477_r_mib_cnt,
+ .r_mib_pkt = ksz9477_r_mib_pkt,
+ .r_mib_stat64 = ksz_r_mib_stats64,
+ .freeze_mib = ksz9477_freeze_mib,
+ .port_init_cnt = ksz9477_port_init_cnt,
+ .vlan_filtering = ksz9477_port_vlan_filtering,
+ .vlan_add = ksz9477_port_vlan_add,
+ .vlan_del = ksz9477_port_vlan_del,
+ .mirror_add = ksz9477_port_mirror_add,
+ .mirror_del = ksz9477_port_mirror_del,
+ .get_caps = lan937x_phylink_get_caps,
+ .setup_rgmii_delay = lan937x_setup_rgmii_delay,
+ .fdb_dump = ksz9477_fdb_dump,
+ .fdb_add = ksz9477_fdb_add,
+ .fdb_del = ksz9477_fdb_del,
+ .mdb_add = ksz9477_mdb_add,
+ .mdb_del = ksz9477_mdb_del,
+ .change_mtu = lan937x_change_mtu,
+ .config_cpu_port = lan937x_config_cpu_port,
+ .tc_cbs_set_cinc = lan937x_tc_cbs_set_cinc,
+ .enable_stp_addr = ksz9477_enable_stp_addr,
+ .reset = lan937x_reset_switch,
+ .init = lan937x_switch_init,
+ .exit = lan937x_switch_exit,
+};
+
MODULE_AUTHOR("Arun Ramadoss <arun.ramadoss@microchip.com>");
MODULE_DESCRIPTION("Microchip LAN937x Series Switch DSA Driver");
MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 3/9] net: dsa: microchip: move KSZ8 ksz_dev_ops to ksz8.c
From: Bastien Curutchet @ 2026-05-05 14:25 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric), Vladimir Oltean
In-Reply-To: <20260505-clean-ksz-driver-v1-0-05d70fa42461@bootlin.com>
From: Vladimir Oltean <vladimir.oltean@nxp.com>
The ksz_dev_ops() are specific to each switch family so they should
belong to the individual drivers instead of the common section.
Move the ksz_dev_ops() definitions of the KSZ8xxx to ksz8.c
Set static the functions that aren't exported anymore.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 200 +++++++++++++++++++++++++--------
drivers/net/dsa/microchip/ksz8.h | 51 +--------
drivers/net/dsa/microchip/ksz_common.c | 102 -----------------
3 files changed, 155 insertions(+), 198 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index dc29b028f8409..56560f60223a1 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -114,26 +114,26 @@ static int ksz8_ind_read8(struct ksz_device *dev, u8 table, u16 addr, u8 *val)
return ret;
}
-int ksz8_pme_write8(struct ksz_device *dev, u32 reg, u8 value)
+static int ksz8_pme_write8(struct ksz_device *dev, u32 reg, u8 value)
{
return ksz8_ind_write8(dev, (u8)(reg >> 8), (u8)(reg), value);
}
-int ksz8_pme_pread8(struct ksz_device *dev, int port, int offset, u8 *data)
+static int ksz8_pme_pread8(struct ksz_device *dev, int port, int offset, u8 *data)
{
u8 table = (u8)(offset >> 8 | (port + 1));
return ksz8_ind_read8(dev, table, (u8)(offset), data);
}
-int ksz8_pme_pwrite8(struct ksz_device *dev, int port, int offset, u8 data)
+static int ksz8_pme_pwrite8(struct ksz_device *dev, int port, int offset, u8 data)
{
u8 table = (u8)(offset >> 8 | (port + 1));
return ksz8_ind_write8(dev, table, (u8)(offset), data);
}
-int ksz8_reset_switch(struct ksz_device *dev)
+static int ksz8_reset_switch(struct ksz_device *dev)
{
if (ksz_is_ksz88x3(dev)) {
/* reset switch */
@@ -186,7 +186,7 @@ static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size)
return ksz_rmw8(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, ctrl2);
}
-int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu)
+static int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu)
{
u16 frame_size;
@@ -267,7 +267,7 @@ static int ksz8_port_queue_split(struct ksz_device *dev, int port, int queues)
return ksz_prmw8(dev, port, reg_2q, mask_2q, data_2q);
}
-void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
+static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
{
const u32 *masks;
const u16 *regs;
@@ -390,8 +390,8 @@ static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
}
}
-void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
- u64 *dropped, u64 *cnt)
+static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+ u64 *dropped, u64 *cnt)
{
if (is_ksz88xx(dev))
ksz8863_r_mib_pkt(dev, port, addr, dropped, cnt);
@@ -399,7 +399,7 @@ void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
ksz8795_r_mib_pkt(dev, port, addr, dropped, cnt);
}
-void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze)
+static void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze)
{
if (is_ksz88xx(dev))
return;
@@ -414,7 +414,7 @@ void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze)
ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false);
}
-void ksz8_port_init_cnt(struct ksz_device *dev, int port)
+static void ksz8_port_init_cnt(struct ksz_device *dev, int port)
{
struct ksz_port_mib *mib = &dev->ports[port].mib;
u64 *dropped;
@@ -939,7 +939,7 @@ static int ksz8_r_phy_bmcr(struct ksz_device *dev, u16 port, u16 *val)
return 0;
}
-int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
+static int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
{
u8 ctrl, link, val1, val2;
int processed = true;
@@ -1203,7 +1203,7 @@ static int ksz8_w_phy_bmcr(struct ksz_device *dev, u16 port, u16 val)
restart);
}
-int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
+static int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
{
const u16 *regs;
u8 ctrl, data;
@@ -1263,7 +1263,7 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
return 0;
}
-void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
+static void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
{
int offset = P_MIRROR_CTRL;
u8 data;
@@ -1276,7 +1276,7 @@ void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
ksz_pwrite8(dev, port, offset, data);
}
-void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
+static void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
{
u8 learn[DSA_MAX_PORTS];
int first, index, cnt;
@@ -1311,8 +1311,8 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
}
}
-int ksz8_fdb_dump(struct ksz_device *dev, int port,
- dsa_fdb_dump_cb_t *cb, void *data)
+static int ksz8_fdb_dump(struct ksz_device *dev, int port,
+ dsa_fdb_dump_cb_t *cb, void *data)
{
u8 mac[ETH_ALEN];
u8 src_port, fid;
@@ -1416,32 +1416,34 @@ static int ksz8_del_sta_mac(struct ksz_device *dev, int port,
return ksz8_w_sta_mac_table(dev, index, &alu);
}
-int ksz8_mdb_add(struct ksz_device *dev, int port,
- const struct switchdev_obj_port_mdb *mdb, struct dsa_db db)
+static int ksz8_mdb_add(struct ksz_device *dev, int port,
+ const struct switchdev_obj_port_mdb *mdb,
+ struct dsa_db db)
{
return ksz8_add_sta_mac(dev, port, mdb->addr, mdb->vid);
}
-int ksz8_mdb_del(struct ksz_device *dev, int port,
- const struct switchdev_obj_port_mdb *mdb, struct dsa_db db)
+static int ksz8_mdb_del(struct ksz_device *dev, int port,
+ const struct switchdev_obj_port_mdb *mdb,
+ struct dsa_db db)
{
return ksz8_del_sta_mac(dev, port, mdb->addr, mdb->vid);
}
-int ksz8_fdb_add(struct ksz_device *dev, int port, const unsigned char *addr,
- u16 vid, struct dsa_db db)
+static int ksz8_fdb_add(struct ksz_device *dev, int port,
+ const unsigned char *addr, u16 vid, struct dsa_db db)
{
return ksz8_add_sta_mac(dev, port, addr, vid);
}
-int ksz8_fdb_del(struct ksz_device *dev, int port, const unsigned char *addr,
- u16 vid, struct dsa_db db)
+static int ksz8_fdb_del(struct ksz_device *dev, int port,
+ const unsigned char *addr, u16 vid, struct dsa_db db)
{
return ksz8_del_sta_mac(dev, port, addr, vid);
}
-int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag,
- struct netlink_ext_ack *extack)
+static int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag,
+ struct netlink_ext_ack *extack)
{
if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
return -ENOTSUPP;
@@ -1470,9 +1472,9 @@ static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state)
}
}
-int ksz8_port_vlan_add(struct ksz_device *dev, int port,
- const struct switchdev_obj_port_vlan *vlan,
- struct netlink_ext_ack *extack)
+static int ksz8_port_vlan_add(struct ksz_device *dev, int port,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct netlink_ext_ack *extack)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
struct ksz_port *p = &dev->ports[port];
@@ -1542,8 +1544,8 @@ int ksz8_port_vlan_add(struct ksz_device *dev, int port,
return 0;
}
-int ksz8_port_vlan_del(struct ksz_device *dev, int port,
- const struct switchdev_obj_port_vlan *vlan)
+static int ksz8_port_vlan_del(struct ksz_device *dev, int port,
+ const struct switchdev_obj_port_vlan *vlan)
{
u16 data, pvid;
u8 fid, member, valid;
@@ -1574,9 +1576,9 @@ int ksz8_port_vlan_del(struct ksz_device *dev, int port,
return 0;
}
-int ksz8_port_mirror_add(struct ksz_device *dev, int port,
- struct dsa_mall_mirror_tc_entry *mirror,
- bool ingress, struct netlink_ext_ack *extack)
+static int ksz8_port_mirror_add(struct ksz_device *dev, int port,
+ struct dsa_mall_mirror_tc_entry *mirror,
+ bool ingress, struct netlink_ext_ack *extack)
{
int offset = P_MIRROR_CTRL;
@@ -1600,8 +1602,8 @@ int ksz8_port_mirror_add(struct ksz_device *dev, int port,
return 0;
}
-void ksz8_port_mirror_del(struct ksz_device *dev, int port,
- struct dsa_mall_mirror_tc_entry *mirror)
+static void ksz8_port_mirror_del(struct ksz_device *dev, int port,
+ struct dsa_mall_mirror_tc_entry *mirror)
{
int offset = P_MIRROR_CTRL;
u8 data;
@@ -1639,7 +1641,7 @@ static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port)
}
}
-void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
+static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{
const u16 *regs = dev->info->regs;
struct dsa_switch *ds = dev->ds;
@@ -1694,7 +1696,7 @@ static void ksz88x3_config_rmii_clk(struct ksz_device *dev)
KSZ88X3_PORT3_RMII_CLK_INTERNAL, rmii_clk_internal);
}
-void ksz8_config_cpu_port(struct dsa_switch *ds)
+static void ksz8_config_cpu_port(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
struct ksz_port *p;
@@ -1903,7 +1905,7 @@ static int ksz8_handle_global_errata(struct dsa_switch *ds)
return ret;
}
-int ksz8_enable_stp_addr(struct ksz_device *dev)
+static int ksz8_enable_stp_addr(struct ksz_device *dev)
{
struct alu_struct alu;
@@ -1917,7 +1919,7 @@ int ksz8_enable_stp_addr(struct ksz_device *dev)
return ksz8_w_sta_mac_table(dev, 0, &alu);
}
-int ksz8_setup(struct dsa_switch *ds)
+static int ksz8_setup(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
const u16 *regs = dev->info->regs;
@@ -1980,8 +1982,8 @@ int ksz8_setup(struct dsa_switch *ds)
return ret;
}
-void ksz8_get_caps(struct ksz_device *dev, int port,
- struct phylink_config *config)
+static void ksz8_get_caps(struct ksz_device *dev, int port,
+ struct phylink_config *config)
{
config->mac_capabilities = MAC_10 | MAC_100;
@@ -1998,12 +2000,12 @@ void ksz8_get_caps(struct ksz_device *dev, int port,
config->mac_capabilities |= MAC_ASYM_PAUSE;
}
-u32 ksz8_get_port_addr(int port, int offset)
+static u32 ksz8_get_port_addr(int port, int offset)
{
return PORT_CTRL_ADDR(port, offset);
}
-u32 ksz8463_get_port_addr(int port, int offset)
+static u32 ksz8463_get_port_addr(int port, int offset)
{
return offset + 0x18 * port;
}
@@ -2013,7 +2015,7 @@ static u16 ksz8463_get_phy_addr(u16 phy, u16 reg, u16 offset)
return offset + reg * 2 + phy * (P2MBCR - P1MBCR);
}
-int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
+static int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
{
u16 sw_reg = 0;
u16 data = 0;
@@ -2053,7 +2055,7 @@ int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
return 0;
}
-int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
+static int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
{
u16 sw_reg = 0;
int ret;
@@ -2081,7 +2083,7 @@ int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
return 0;
}
-int ksz8_switch_init(struct ksz_device *dev)
+static int ksz8_switch_init(struct ksz_device *dev)
{
dev->cpu_port = fls(dev->info->cpu_ports) - 1;
dev->phy_port_cnt = dev->info->port_cnt - 1;
@@ -2090,11 +2092,113 @@ int ksz8_switch_init(struct ksz_device *dev)
return 0;
}
-void ksz8_switch_exit(struct ksz_device *dev)
+static void ksz8_switch_exit(struct ksz_device *dev)
{
ksz8_reset_switch(dev);
}
+const struct ksz_dev_ops ksz8463_dev_ops = {
+ .setup = ksz8_setup,
+ .get_port_addr = ksz8463_get_port_addr,
+ .cfg_port_member = ksz8_cfg_port_member,
+ .flush_dyn_mac_table = ksz8_flush_dyn_mac_table,
+ .port_setup = ksz8_port_setup,
+ .r_phy = ksz8463_r_phy,
+ .w_phy = ksz8463_w_phy,
+ .r_mib_cnt = ksz8_r_mib_cnt,
+ .r_mib_pkt = ksz8_r_mib_pkt,
+ .r_mib_stat64 = ksz88xx_r_mib_stats64,
+ .freeze_mib = ksz8_freeze_mib,
+ .port_init_cnt = ksz8_port_init_cnt,
+ .fdb_dump = ksz8_fdb_dump,
+ .fdb_add = ksz8_fdb_add,
+ .fdb_del = ksz8_fdb_del,
+ .mdb_add = ksz8_mdb_add,
+ .mdb_del = ksz8_mdb_del,
+ .vlan_filtering = ksz8_port_vlan_filtering,
+ .vlan_add = ksz8_port_vlan_add,
+ .vlan_del = ksz8_port_vlan_del,
+ .mirror_add = ksz8_port_mirror_add,
+ .mirror_del = ksz8_port_mirror_del,
+ .get_caps = ksz8_get_caps,
+ .config_cpu_port = ksz8_config_cpu_port,
+ .enable_stp_addr = ksz8_enable_stp_addr,
+ .reset = ksz8_reset_switch,
+ .init = ksz8_switch_init,
+ .exit = ksz8_switch_exit,
+ .change_mtu = ksz8_change_mtu,
+};
+
+const struct ksz_dev_ops ksz87xx_dev_ops = {
+ .setup = ksz8_setup,
+ .get_port_addr = ksz8_get_port_addr,
+ .cfg_port_member = ksz8_cfg_port_member,
+ .flush_dyn_mac_table = ksz8_flush_dyn_mac_table,
+ .port_setup = ksz8_port_setup,
+ .r_phy = ksz8_r_phy,
+ .w_phy = ksz8_w_phy,
+ .r_mib_cnt = ksz8_r_mib_cnt,
+ .r_mib_pkt = ksz8_r_mib_pkt,
+ .r_mib_stat64 = ksz_r_mib_stats64,
+ .freeze_mib = ksz8_freeze_mib,
+ .port_init_cnt = ksz8_port_init_cnt,
+ .fdb_dump = ksz8_fdb_dump,
+ .fdb_add = ksz8_fdb_add,
+ .fdb_del = ksz8_fdb_del,
+ .mdb_add = ksz8_mdb_add,
+ .mdb_del = ksz8_mdb_del,
+ .vlan_filtering = ksz8_port_vlan_filtering,
+ .vlan_add = ksz8_port_vlan_add,
+ .vlan_del = ksz8_port_vlan_del,
+ .mirror_add = ksz8_port_mirror_add,
+ .mirror_del = ksz8_port_mirror_del,
+ .get_caps = ksz8_get_caps,
+ .config_cpu_port = ksz8_config_cpu_port,
+ .enable_stp_addr = ksz8_enable_stp_addr,
+ .reset = ksz8_reset_switch,
+ .init = ksz8_switch_init,
+ .exit = ksz8_switch_exit,
+ .change_mtu = ksz8_change_mtu,
+ .pme_write8 = ksz8_pme_write8,
+ .pme_pread8 = ksz8_pme_pread8,
+ .pme_pwrite8 = ksz8_pme_pwrite8,
+};
+
+const struct ksz_dev_ops ksz88xx_dev_ops = {
+ .setup = ksz8_setup,
+ .get_port_addr = ksz8_get_port_addr,
+ .cfg_port_member = ksz8_cfg_port_member,
+ .flush_dyn_mac_table = ksz8_flush_dyn_mac_table,
+ .port_setup = ksz8_port_setup,
+ .r_phy = ksz8_r_phy,
+ .w_phy = ksz8_w_phy,
+ .r_mib_cnt = ksz8_r_mib_cnt,
+ .r_mib_pkt = ksz8_r_mib_pkt,
+ .r_mib_stat64 = ksz88xx_r_mib_stats64,
+ .freeze_mib = ksz8_freeze_mib,
+ .port_init_cnt = ksz8_port_init_cnt,
+ .fdb_dump = ksz8_fdb_dump,
+ .fdb_add = ksz8_fdb_add,
+ .fdb_del = ksz8_fdb_del,
+ .mdb_add = ksz8_mdb_add,
+ .mdb_del = ksz8_mdb_del,
+ .vlan_filtering = ksz8_port_vlan_filtering,
+ .vlan_add = ksz8_port_vlan_add,
+ .vlan_del = ksz8_port_vlan_del,
+ .mirror_add = ksz8_port_mirror_add,
+ .mirror_del = ksz8_port_mirror_del,
+ .get_caps = ksz8_get_caps,
+ .config_cpu_port = ksz8_config_cpu_port,
+ .enable_stp_addr = ksz8_enable_stp_addr,
+ .reset = ksz8_reset_switch,
+ .init = ksz8_switch_init,
+ .exit = ksz8_switch_exit,
+ .change_mtu = ksz8_change_mtu,
+ .pme_write8 = ksz8_pme_write8,
+ .pme_pread8 = ksz8_pme_pread8,
+ .pme_pwrite8 = ksz8_pme_pwrite8,
+};
+
MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>");
MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/microchip/ksz8.h b/drivers/net/dsa/microchip/ksz8.h
index 52b7d944d9d97..4b798ce29daaf 100644
--- a/drivers/net/dsa/microchip/ksz8.h
+++ b/drivers/net/dsa/microchip/ksz8.h
@@ -12,58 +12,13 @@
#include <net/dsa.h>
#include "ksz_common.h"
-int ksz8_setup(struct dsa_switch *ds);
-u32 ksz8_get_port_addr(int port, int offset);
-void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member);
-void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port);
-void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port);
-int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
-int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
-void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt);
-void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
- u64 *dropped, u64 *cnt);
-void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze);
-void ksz8_port_init_cnt(struct ksz_device *dev, int port);
-int ksz8_fdb_dump(struct ksz_device *dev, int port,
- dsa_fdb_dump_cb_t *cb, void *data);
-int ksz8_fdb_add(struct ksz_device *dev, int port, const unsigned char *addr,
- u16 vid, struct dsa_db db);
-int ksz8_fdb_del(struct ksz_device *dev, int port, const unsigned char *addr,
- u16 vid, struct dsa_db db);
-int ksz8_mdb_add(struct ksz_device *dev, int port,
- const struct switchdev_obj_port_mdb *mdb, struct dsa_db db);
-int ksz8_mdb_del(struct ksz_device *dev, int port,
- const struct switchdev_obj_port_mdb *mdb, struct dsa_db db);
-int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag,
- struct netlink_ext_ack *extack);
-int ksz8_port_vlan_add(struct ksz_device *dev, int port,
- const struct switchdev_obj_port_vlan *vlan,
- struct netlink_ext_ack *extack);
-int ksz8_port_vlan_del(struct ksz_device *dev, int port,
- const struct switchdev_obj_port_vlan *vlan);
-int ksz8_port_mirror_add(struct ksz_device *dev, int port,
- struct dsa_mall_mirror_tc_entry *mirror,
- bool ingress, struct netlink_ext_ack *extack);
-void ksz8_port_mirror_del(struct ksz_device *dev, int port,
- struct dsa_mall_mirror_tc_entry *mirror);
-void ksz8_get_caps(struct ksz_device *dev, int port,
- struct phylink_config *config);
-void ksz8_config_cpu_port(struct dsa_switch *ds);
-int ksz8_enable_stp_addr(struct ksz_device *dev);
-int ksz8_reset_switch(struct ksz_device *dev);
-int ksz8_switch_init(struct ksz_device *dev);
-void ksz8_switch_exit(struct ksz_device *dev);
-int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu);
-int ksz8_pme_write8(struct ksz_device *dev, u32 reg, u8 value);
-int ksz8_pme_pread8(struct ksz_device *dev, int port, int offset, u8 *data);
-int ksz8_pme_pwrite8(struct ksz_device *dev, int port, int offset, u8 data);
void ksz8_phylink_mac_link_up(struct phylink_config *config,
struct phy_device *phydev, unsigned int mode,
phy_interface_t interface, int speed, int duplex,
bool tx_pause, bool rx_pause);
-u32 ksz8463_get_port_addr(int port, int offset);
-int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
-int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
+extern const struct ksz_dev_ops ksz8463_dev_ops;
+extern const struct ksz_dev_ops ksz87xx_dev_ops;
+extern const struct ksz_dev_ops ksz88xx_dev_ops;
#endif
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 144373e13bea3..4d7834149d0c0 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -332,108 +332,6 @@ static const struct phylink_mac_ops ksz8_phylink_mac_ops = {
.mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
};
-static const struct ksz_dev_ops ksz8463_dev_ops = {
- .setup = ksz8_setup,
- .get_port_addr = ksz8463_get_port_addr,
- .cfg_port_member = ksz8_cfg_port_member,
- .flush_dyn_mac_table = ksz8_flush_dyn_mac_table,
- .port_setup = ksz8_port_setup,
- .r_phy = ksz8463_r_phy,
- .w_phy = ksz8463_w_phy,
- .r_mib_cnt = ksz8_r_mib_cnt,
- .r_mib_pkt = ksz8_r_mib_pkt,
- .r_mib_stat64 = ksz88xx_r_mib_stats64,
- .freeze_mib = ksz8_freeze_mib,
- .port_init_cnt = ksz8_port_init_cnt,
- .fdb_dump = ksz8_fdb_dump,
- .fdb_add = ksz8_fdb_add,
- .fdb_del = ksz8_fdb_del,
- .mdb_add = ksz8_mdb_add,
- .mdb_del = ksz8_mdb_del,
- .vlan_filtering = ksz8_port_vlan_filtering,
- .vlan_add = ksz8_port_vlan_add,
- .vlan_del = ksz8_port_vlan_del,
- .mirror_add = ksz8_port_mirror_add,
- .mirror_del = ksz8_port_mirror_del,
- .get_caps = ksz8_get_caps,
- .config_cpu_port = ksz8_config_cpu_port,
- .enable_stp_addr = ksz8_enable_stp_addr,
- .reset = ksz8_reset_switch,
- .init = ksz8_switch_init,
- .exit = ksz8_switch_exit,
- .change_mtu = ksz8_change_mtu,
-};
-
-static const struct ksz_dev_ops ksz88xx_dev_ops = {
- .setup = ksz8_setup,
- .get_port_addr = ksz8_get_port_addr,
- .cfg_port_member = ksz8_cfg_port_member,
- .flush_dyn_mac_table = ksz8_flush_dyn_mac_table,
- .port_setup = ksz8_port_setup,
- .r_phy = ksz8_r_phy,
- .w_phy = ksz8_w_phy,
- .r_mib_cnt = ksz8_r_mib_cnt,
- .r_mib_pkt = ksz8_r_mib_pkt,
- .r_mib_stat64 = ksz88xx_r_mib_stats64,
- .freeze_mib = ksz8_freeze_mib,
- .port_init_cnt = ksz8_port_init_cnt,
- .fdb_dump = ksz8_fdb_dump,
- .fdb_add = ksz8_fdb_add,
- .fdb_del = ksz8_fdb_del,
- .mdb_add = ksz8_mdb_add,
- .mdb_del = ksz8_mdb_del,
- .vlan_filtering = ksz8_port_vlan_filtering,
- .vlan_add = ksz8_port_vlan_add,
- .vlan_del = ksz8_port_vlan_del,
- .mirror_add = ksz8_port_mirror_add,
- .mirror_del = ksz8_port_mirror_del,
- .get_caps = ksz8_get_caps,
- .config_cpu_port = ksz8_config_cpu_port,
- .enable_stp_addr = ksz8_enable_stp_addr,
- .reset = ksz8_reset_switch,
- .init = ksz8_switch_init,
- .exit = ksz8_switch_exit,
- .change_mtu = ksz8_change_mtu,
- .pme_write8 = ksz8_pme_write8,
- .pme_pread8 = ksz8_pme_pread8,
- .pme_pwrite8 = ksz8_pme_pwrite8,
-};
-
-static const struct ksz_dev_ops ksz87xx_dev_ops = {
- .setup = ksz8_setup,
- .get_port_addr = ksz8_get_port_addr,
- .cfg_port_member = ksz8_cfg_port_member,
- .flush_dyn_mac_table = ksz8_flush_dyn_mac_table,
- .port_setup = ksz8_port_setup,
- .r_phy = ksz8_r_phy,
- .w_phy = ksz8_w_phy,
- .r_mib_cnt = ksz8_r_mib_cnt,
- .r_mib_pkt = ksz8_r_mib_pkt,
- .r_mib_stat64 = ksz_r_mib_stats64,
- .freeze_mib = ksz8_freeze_mib,
- .port_init_cnt = ksz8_port_init_cnt,
- .fdb_dump = ksz8_fdb_dump,
- .fdb_add = ksz8_fdb_add,
- .fdb_del = ksz8_fdb_del,
- .mdb_add = ksz8_mdb_add,
- .mdb_del = ksz8_mdb_del,
- .vlan_filtering = ksz8_port_vlan_filtering,
- .vlan_add = ksz8_port_vlan_add,
- .vlan_del = ksz8_port_vlan_del,
- .mirror_add = ksz8_port_mirror_add,
- .mirror_del = ksz8_port_mirror_del,
- .get_caps = ksz8_get_caps,
- .config_cpu_port = ksz8_config_cpu_port,
- .enable_stp_addr = ksz8_enable_stp_addr,
- .reset = ksz8_reset_switch,
- .init = ksz8_switch_init,
- .exit = ksz8_switch_exit,
- .change_mtu = ksz8_change_mtu,
- .pme_write8 = ksz8_pme_write8,
- .pme_pread8 = ksz8_pme_pread8,
- .pme_pwrite8 = ksz8_pme_pwrite8,
-};
-
static void ksz9477_phylink_mac_link_up(struct phylink_config *config,
struct phy_device *phydev,
unsigned int mode,
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 2/9] net: dsa: microchip: remove unused port_cleanup() callback
From: Bastien Curutchet (Schneider Electric) @ 2026-05-05 14:25 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
In-Reply-To: <20260505-clean-ksz-driver-v1-0-05d70fa42461@bootlin.com>
ksz_dev_ops :: port_cleanup() isn't used anywhere.
Remove it.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz_common.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 18f13ee9c7b68..cf2d0d91f1732 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -363,7 +363,6 @@ struct ksz_dev_ops {
u32 (*get_port_addr)(int port, int offset);
void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
- void (*port_cleanup)(struct ksz_device *dev, int port);
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
int (*set_ageing_time)(struct ksz_device *dev, unsigned int msecs);
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox