* Re: [PATCH rdma-next v3] RDMA/mlx5: quiesce CQ polling before device shutdown on reboot
From: Leon Romanovsky @ 2026-07-16 10:50 UTC (permalink / raw)
To: Chenguang Zhao
Cc: jgg, andrew+netdev, davem, edumazet, kuba, pabeni, linux-rdma,
netdev, tariqt, mbloch, dtatulea, shayd, moshe, Chenguang Zhao
In-Reply-To: <c2c5dda9-3228-44a3-a4c9-89e8cc4501bc@linux.dev>
On Thu, Jul 16, 2026 at 05:03:37PM +0800, Chenguang Zhao wrote:
> Hi, Leon
> reboot -f skips orderly shutdown and goes directly to:
>
> kernel_restart_prepare() -> device_shutdown() -> mlx5 shutdown
> Upper layers may still hold live CQs, while ib-comp-wq keeps
> polling — a use-after-free race.
The point is that this flow is neither RDMA- nor mlx5-specific, and it
works as expected. mlx5 shutdown() stops the FW/HW, while the kernel
stops and tears down the running threads.
>
> Normal reboot usually works because userspace has already
> torn down RDMA and called ib_free_cq().
There is no difference, from the kernel's perspective, between a
normal and a forced reboot, except that the former bypasses
userspace shutdown.
Thanks
>
> Thanks
>
> 在 2026/7/16 16:42, Leon Romanovsky 写道:
> > On Wed, Jul 15, 2026 at 04:23:07PM +0800, Chenguang Zhao wrote:
> >> From: Chenguang Zhao <zhaochenguang@kylinos.cn>
> >>
> >> On reboot -f with NFS over RDMA, mlx5 shutdown can tear the device
> >> down while ib-comp-wq still polls live CQs, leading to UAF in
> >> wr_cqe->done().
> >>
> >> Mark the device shutting down before teardown, flush completion
> >> workqueues so in-flight pollers observe the flag, skip SYS_ERROR
> >> completion delivery, and make poll/arm CQ a no-op under the CQ lock
> >> while shutting down.
> >>
> >> Signed-off-by: Chenguang Zhao <zhaochenguang@kylinos.cn>
> >> ---
> >> changelog:
> >> - Fix the race on MLX5_INTERFACE_STATE_SHUTTING_DOWN: set the
> >> flag, then flush ib-comp / mlx5_ib event workqueues via an
> >> mlx5_ib quiesce hook before fast_unload/teardown.
> >> - Check shutting-down under cq->lock in mlx5_ib_poll_cq/arm_cq.
> >> - Export ib_comp_wq and ib_comp_unbound_wq so modular mlx5_ib
> >> can flush them.
> >>
> >> v2:
> >> https://lore.kernel.org/all/20260714075558.1420384-1-chenguang.zhao@linux.dev/
> >>
> >> v1:
> >> https://lore.kernel.org/all/20260702073422.279820-1-chenguang.zhao@linux.dev/
> >>
> >> drivers/infiniband/core/device.c | 2 ++
> >> drivers/infiniband/hw/mlx5/cq.c | 11 ++++++++++
> >> drivers/infiniband/hw/mlx5/main.c | 20 +++++++++++++++++++
> >> .../net/ethernet/mellanox/mlx5/core/health.c | 3 +++
> >> .../net/ethernet/mellanox/mlx5/core/main.c | 10 ++++++++++
> >> .../mellanox/mlx5/core/sf/dev/driver.c | 3 +++
> >> include/linux/mlx5/driver.h | 11 ++++++++++
> >> 7 files changed, 60 insertions(+)
> > <...>
> >
> >> +static void mlx5_ib_shutdown_quiesce(void)
> >> +{
> >> + flush_workqueue(ib_comp_wq);
> >> + flush_workqueue(ib_comp_unbound_wq);
> >> + flush_workqueue(mlx5_ib_event_wq);
> >> +}
> > These workqueues are shared by all IB drivers and the core. Drivers
> > must not flush or destroy them.
> >
> > Why this is not FW issue?
> >
> > Thanks
^ permalink raw reply
* Re: [PATCH v4 0/2] bpf, sockmap: handle spurious tcp_msg_wait_data() wakeup
From: Jiayuan Chen @ 2026-07-16 10:48 UTC (permalink / raw)
To: Nnamdi Onyeyiri
Cc: bpf, davem, edumazet, horms, jakub, john.fastabend, kuba, kuniyu,
ncardwell, netdev, pabeni, sashiko-reviews
In-Reply-To: <aliwTlOayzvvlN10@localhost.localdomain>
On 7/16/26 6:24 PM, Nnamdi Onyeyiri wrote:
> On Thu, Jul 16, 2026 at 09:30:30AM +0800, Jiayuan Chen wrote:
>> Please do not send a patch by replying to an old thread.
>>
>> ...
>>
>> Please use a commit subject like "selftests/bpf: add selftest xxx" for the
>> selftest patch.
>>
> Sorry, I'll resubmit with these changes.
>
>> Please use existing test frameworks such as sockmap_basic.c or
>> sockmap_strp.c.
>>
> Just to clarify, do you mean I should add the new tests to one of these
> existing files? Or that I should add a new file, but write the test in the
> same way as sockmap_basic.c implements them?
>
> Thanks!
Using existing files is enough I guess.
I didn't read your selftest files fully, but I don't think a selftest
with 299+ lines is a good idea for reproducing a single problem.
I think you should try to shorten it to a reasonable size, e.g., by
reusing helpers.
^ permalink raw reply
* Re: [PATCH v3 net 3/6] xsk: provide sufficient space in pool->tx_descs
From: Maciej Fijalkowski @ 2026-07-16 10:47 UTC (permalink / raw)
To: Jason Xing
Cc: netdev, bpf, magnus.karlsson, stfomichev, kuba, pabeni, horms,
bjorn
In-Reply-To: <CAL+tcoDc-a=Tx3VGfjnPoLq2hWaGCBjUe+NzHeaz=QPvjWEXjA@mail.gmail.com>
On Thu, Jul 16, 2026 at 11:29:49AM +0200, Jason Xing wrote:
> On Tue, Jul 14, 2026 at 4:08 PM Maciej Fijalkowski
> <maciej.fijalkowski@intel.com> wrote:
> >
> > The temporary Tx descriptor array in an XSK buffer pool is currently
> > sized from the Tx ring of the socket that creates the pool.
> >
> > This is insufficient for shared-UMEM Tx. A later socket may have a
> > larger Tx ring and submit a valid multi-buffer packet containing more
> > descriptors than the first socket's ring, while still remaining within
> > the device's xdp_zc_max_segs limit.
> >
> > A packet-framed batch parser bounded by the temporary array cannot reach
> > the end-of-packet descriptor in that case. It leaves the packet on the
> > Tx ring and encounters the same packet on every subsequent attempt,
> > stalling Tx processing for that socket.
> >
> > Size the temporary descriptor array to the larger of the first Tx ring
> > and the device's xdp_zc_max_segs capability. This keeps the array large
> > enough to inspect one maximum-sized valid packet. Larger shared Tx rings
> > do not require further resizing, as they can be processed over multiple
> > batches.
> >
> > Following commit will actually address the data path side.
> >
> > Fixes: d5581966040f ("xsk: support ZC Tx multi-buffer in batch API")
> > Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
>
> Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
>
> I noticed there is one interesting comment[1] from sashiko, which
> actually I think is valid. Probably we don't need to do it in the fix,
> but we might need to target -next branch. Now the tx_descs is limited
> by the first tx ring.
>
> [1]:
> "...since tx_descs is not
> reallocated if it already exists, the array size is permanently frozen
> to the first socket's size.
>
> Should the array be resized to accommodate the largest shared ring, or
> should the batch readers be updated to cap their reads to the array's
> actual size?"
My take here is that this set will not break the user space by providing
at least pool->xdp_zc_max_segs at pool->tx_descs. Let us rely at least a
bit on user's intelligence here - if you would attach one short ring for
whatever reason among with bigger ring to the very same umem and whine
your performance suck, then I'd say it's on you :P
Hope this makes sense!
>
> Thanks,
> Jason
>
> > ---
> > include/net/xsk_buff_pool.h | 6 ++++--
> > net/xdp/xsk.c | 10 +++++++---
> > net/xdp/xsk_buff_pool.c | 12 ++++++++----
> > 3 files changed, 19 insertions(+), 9 deletions(-)
> >
> > diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h
> > index ccb3b350001f..f5e737a83055 100644
> > --- a/include/net/xsk_buff_pool.h
> > +++ b/include/net/xsk_buff_pool.h
> > @@ -102,12 +102,14 @@ struct xsk_buff_pool {
> >
> > /* AF_XDP core. */
> > struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,
> > - struct xdp_umem *umem);
> > + struct xdp_umem *umem,
> > + u32 max_segs);
> > int xp_assign_dev(struct xsk_buff_pool *pool, struct net_device *dev,
> > u16 queue_id, u16 flags);
> > int xp_assign_dev_shared(struct xsk_buff_pool *pool, struct xdp_sock *umem_xs,
> > struct net_device *dev, u16 queue_id);
> > -int xp_alloc_tx_descs(struct xsk_buff_pool *pool, struct xdp_sock *xs);
> > +int xp_alloc_tx_descs(struct xsk_buff_pool *pool, struct xdp_sock *xs,
> > + u32 max_segs);
> > void xp_destroy(struct xsk_buff_pool *pool);
> > void xp_get_pool(struct xsk_buff_pool *pool);
> > bool xp_put_pool(struct xsk_buff_pool *pool);
> > diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
> > index 43791647cf18..385a3f4a1b32 100644
> > --- a/net/xdp/xsk.c
> > +++ b/net/xdp/xsk.c
> > @@ -1525,7 +1525,8 @@ static int xsk_bind(struct socket *sock, struct sockaddr_unsized *addr, int addr
> > * and/or device.
> > */
> > xs->pool = xp_create_and_assign_umem(xs,
> > - umem_xs->umem);
> > + umem_xs->umem,
> > + dev->xdp_zc_max_segs);
> > if (!xs->pool) {
> > err = -ENOMEM;
> > sockfd_put(sock);
> > @@ -1557,7 +1558,8 @@ static int xsk_bind(struct socket *sock, struct sockaddr_unsized *addr, int addr
> > * utilizes
> > */
> > if (xs->tx && !xs->pool->tx_descs) {
> > - err = xp_alloc_tx_descs(xs->pool, xs);
> > + err = xp_alloc_tx_descs(xs->pool, xs,
> > + dev->xdp_zc_max_segs);
> > if (err) {
> > xp_put_pool(xs->pool);
> > xs->pool = NULL;
> > @@ -1575,7 +1577,9 @@ static int xsk_bind(struct socket *sock, struct sockaddr_unsized *addr, int addr
> > goto out_unlock;
> > } else {
> > /* This xsk has its own umem. */
> > - xs->pool = xp_create_and_assign_umem(xs, xs->umem);
> > + xs->pool = xp_create_and_assign_umem(xs, xs->umem,
> > + dev->xdp_zc_max_segs);
> > +
> > if (!xs->pool) {
> > err = -ENOMEM;
> > goto out_unlock;
> > diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
> > index 1f28a9641571..12c9fb29af05 100644
> > --- a/net/xdp/xsk_buff_pool.c
> > +++ b/net/xdp/xsk_buff_pool.c
> > @@ -42,9 +42,12 @@ void xp_destroy(struct xsk_buff_pool *pool)
> > kvfree(pool);
> > }
> >
> > -int xp_alloc_tx_descs(struct xsk_buff_pool *pool, struct xdp_sock *xs)
> > +int xp_alloc_tx_descs(struct xsk_buff_pool *pool, struct xdp_sock *xs,
> > + u32 max_segs)
> > {
> > - pool->tx_descs = kvzalloc_objs(*pool->tx_descs, xs->tx->nentries);
> > + u32 nentries = max(xs->tx->nentries, max_segs);
> > +
> > + pool->tx_descs = kvzalloc_objs(*pool->tx_descs, nentries);
> > if (!pool->tx_descs)
> > return -ENOMEM;
> >
> > @@ -52,7 +55,8 @@ int xp_alloc_tx_descs(struct xsk_buff_pool *pool, struct xdp_sock *xs)
> > }
> >
> > struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,
> > - struct xdp_umem *umem)
> > + struct xdp_umem *umem,
> > + u32 max_segs)
> > {
> > bool unaligned = umem->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG;
> > struct xsk_buff_pool *pool;
> > @@ -69,7 +73,7 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,
> > goto out;
> >
> > if (xs->tx)
> > - if (xp_alloc_tx_descs(pool, xs))
> > + if (xp_alloc_tx_descs(pool, xs, max_segs))
> > goto out;
> >
> > pool->chunk_mask = ~((u64)umem->chunk_size - 1);
> > --
> > 2.43.0
> >
^ permalink raw reply
* Re: [PATCH iwl-net v1] i40e: fix set_ringparam error path freeing live Tx rings
From: Simon Horman @ 2026-07-16 10:42 UTC (permalink / raw)
To: aleksandr.loktionov
Cc: Simon Horman, intel-wired-lan, anthony.l.nguyen, netdev
In-Reply-To: <20260710065530.4138116-1-aleksandr.loktionov@intel.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
--- Patch [1]: [PATCH iwl-net v1] i40e: fix set_ringparam error path freeing live Tx rings ---
commit 7042e7b9f58a75bdb26437aed842a7b6780df035
Author: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
i40e: fix set_ringparam error path freeing live Tx rings
This commit fixes an issue in the i40e_set_ringparam() error path where it
mistakenly frees live, NAPI-active TX rings instead of the temporary rings
allocated for a configuration change. It does this by passing the address of
the temporary rings instead of the live ring pointer.
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> index 3da9ec49cc745..6d2b076049f7e 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
> @@ -2249,7 +2249,7 @@ static int i40e_set_ringparam(struct net_device *netdev,
> if (tx_rings) {
> for (i = 0; i < tx_alloc_queue_pairs; i++) {
> if (i40e_active_tx_ring_index(vsi, i))
> - i40e_free_tx_resources(vsi->tx_rings[i]);
> + i40e_free_tx_resources(&tx_rings[i]);
[Severity: High]
This is a pre-existing issue, but does calling i40e_free_tx_resources() on
the cloned &tx_rings[i] inadvertently reset the Byte Queue Limits (BQL)
state on the live TX queues?
Because the temporary rings are shallow copies of the live rings, they
inherit the netdev and queue_index fields. When i40e_free_tx_resources()
cleans up the temporary rings, it calls i40e_clean_tx_ring():
drivers/net/ethernet/intel/i40e/i40e_txrx.c:i40e_clean_tx_ring() {
...
netdev_tx_reset_queue(txring_txq(tx_ring));
...
}
Since i40e_down() has not yet been called on this error path, the live
queue is still actively transmitting. Locklessly resetting BQL here
zeroes num_queued. When the hardware subsequently completes the
already-queued packets, won't dql_completed() underflow and trigger
a BUG_ON()?
The same issue also seems to be present in the earlier error path if
i40e_setup_tx_descriptors() fails.
> }
> kfree(tx_rings);
> tx_rings = NULL;
^ permalink raw reply
* Re: ipv4: icmp: icmp_route_lookup() relookups pick wrong netdev with policy routing + strict rp_filter
From: Muhammad Ziad @ 2026-07-16 10:40 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, David Ahern, Jakub Kicinski, Paolo Abeni, David S. Miller,
linux-kernel
In-Reply-To: <CANn89iK8JzQ9cUf+81yCTqo+AXeJFiKZ1B4xBu34Njaih5+viw@mail.gmail.com>
Thank you for the fix, Eric. Applying the other selectors from skb_in
makes sense to me, but I'm not sure if instead we should copy them
from fl4_dec?
The mark param e.g. is gated by IP4_REPLY_MARK() on fwmark_reflect,
which could be different from skb_in->mark.
On Thu, Jul 16, 2026 at 3:51 AM Eric Dumazet <edumazet@google.com> wrote:
>
> On Wed, Jul 15, 2026 at 5:43 PM Eric Dumazet <edumazet@google.com> wrote:
> >
> > On Wed, Jul 15, 2026 at 5:30 PM Muhammad Ziad <muhzi100@gmail.com> wrote:
> > >
> > > Hello,
> > >
> > > There appears to be a bug in mainline Linux in ICMP reverse-path
> > > relookup logic inside icmp_route_lookup() (called by __icmp_send())
> > > when strict rp_filter setting is in place.
> > >
> > > When Linux forwards a packet between two interfaces and needs to
> > > generate an ICMP error, icmp_route_lookup() performs a "secondary"
> > > reverse-path lookup to find a suitable route back towards the original
> > > source via ip_route_input(). To simulate the reverse path, the kernel
> > > derives the incoming netdev by calling ip_route_output_key() with a
> > > decoy flow that has *only* daddr assigned in it:
> > >
> > > struct flowi4 fl4_2 = {};
> > > fl4_2.daddr = fl4_dec.saddr;
> > > rt2 = ip_route_output_key(net, &fl4_2); /* no saddr */
> > > ...
> > > ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr,
> > > dscp, rt2->dst.dev);
> > >
> > > This can lead to a mismatch between rt2->dst.dev and the netdev the
> > > real reverse packet would use once routing policy rules are in
> > > effect. With strict rp_filter, passing the wrong netdev to
> > > ip_route_input() causes the relookup to fail and a "martian source"
> > > message to be logged, after which icmp_route_lookup() falls back to
> > > the earlier output route lookup (relookup_failed).
> > >
> > > In such a scenario, I would expect the relookup to use a canonical
> > > netdev and the kernel to not produce spurious "martian source" log
> > > messages as a result. This suggests the decoy flow would possibly
> > > need to carry saddr too so that ip_route_output_key() is able to
> > > resolve the right netdev.
> > >
> > > I tested this on: Ubuntu kernel 6.17.0-35-generic.
> > >
> > > Here is a reproducer script that sets up two net namespaces: a
> > > "forwarder" with two routes to the same dst in separate routing tables
> > > picked according to saddr, and a "sender" netns behind it which sends
> > > a ping with ttl=1 via the forwarder forcing it to generate an ICMP
> > > error as a response which leads to the result explained above:
> > >
> > > #!/bin/bash
> > >
> > > if [ "${forwarder_ns:-}" != "1" ]; then
> > > exec env forwarder_ns=1 unshare -Urn bash "$0" "$@"
> > > fi
> > >
> > > SRC=10.0.1.2
> > > DST=198.51.100.5
> > >
> > > # Current netns is the "forwarder".
> > > # Create a second namespace for the sender.
> > > unshare -n sleep 120 &
> > > cpid=$!
> > > trap 'kill "$cpid" 2>/dev/null || true' EXIT
> > > in_ns() { nsenter -t "$cpid" -n "$@"; }
> > >
> > > # veth r0(router) <-> s0(src)
> > > ip link add s0 type veth peer name r0
> > > ip link set s0 netns "$cpid"
> > > ip link set lo up
> > > ip link set r0 up
> > > ip addr add 10.0.1.1/24 dev r0
> > > ip link add dumA type dummy
> > > ip addr add 203.0.113.1/24 dev dumA
> > > ip link set dumA up
> > > ip link add dumB type dummy
> > > ip addr add 192.0.2.1/24 dev dumB
> > > ip link set dumB up
> > >
> > > sysctl -q -w net.ipv4.ip_forward=1
> > > for c in all default r0 dumA dumB; do
> > > sysctl -q -w "net.ipv4.conf.$c.rp_filter=1"
> > > sysctl -q -w "net.ipv4.conf.$c.log_martians=1"
> > > done
> > >
> > > # Destination reachable two ways.
> > > # Policy rule diverts traffic FROM src to dumB
> > > ip route add 198.51.100.0/24 dev dumA
> > > ip route add 198.51.100.0/24 dev dumB table 100
> > > ip rule add from "$SRC" lookup 100
> > >
> > > # sender namespace setup.
> > > in_ns ip link set lo up
> > > in_ns ip link set s0 up
> > > in_ns ip addr add 10.0.1.2/24 dev s0
> > > in_ns ip route add default via 10.0.1.1
> > >
> > > # This will trigger a "martian source" log.
> > > in_ns ping -q -c1 -W2 -t1 "$DST" &>/dev/null
> > >
> > >
> > > Happy to test patches or provide additional traces, if needed.
> > >
> > > Thank you,
> > > Mohamed Ghazy
> >
> > Thanks for the report.
> >
> > It seems we are lacking more than saddr setting :/
> >
> > Could you test
> >
> > diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
> > index 23e921d313b36b00d8ae5e14846527220c9db32b..6277e1bf85f304678ff167e8fd2b9239f155ce42
> > 100644
> > --- a/net/ipv4/icmp.c
> > +++ b/net/ipv4/icmp.c
> > @@ -548,10 +548,17 @@ static struct rtable *icmp_route_lookup(struct
> > net *net, struct flowi4 *fl4,
> > if (IS_ERR(rt2))
> > err = PTR_ERR(rt2);
> > } else {
> > - struct flowi4 fl4_2 = {};
> > + /* TODO: populate
> > + .flowi4_dscp = dscp,
> > + .flowi4_mark = mark,
> > + .flowi4_uid = sock_net_uid(net, NULL),
> > + */
> > + struct flowi4 fl4_2 = {
> > + .daddr = fl4_dec.saddr,
> > + .saddr = fl4_dec.daddr,
> > + };
> > unsigned long orefdst;
> >
> > - fl4_2.daddr = fl4_dec.saddr;
> > rt2 = ip_route_output_key(net, &fl4_2);
> > if (IS_ERR(rt2)) {
> > err = PTR_ERR(rt2);
>
> I have tested the following fix, PTAL, thanks.
>
> diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
> index 23e921d313b36b00d8ae5e14846527220c9db32b..2259f643cb0d43ea54819dd831c79807413e0d69
> 100644
> --- a/net/ipv4/icmp.c
> +++ b/net/ipv4/icmp.c
> @@ -548,10 +548,16 @@ static struct rtable *icmp_route_lookup(struct
> net *net, struct flowi4 *fl4,
> if (IS_ERR(rt2))
> err = PTR_ERR(rt2);
> } else {
> - struct flowi4 fl4_2 = {};
> + struct flowi4 fl4_2 = {
> + .daddr = fl4_dec.saddr,
> + .saddr = fl4_dec.daddr,
> + .flowi4_dscp = dscp,
> + .flowi4_proto = IPPROTO_ICMP,
> + .flowi4_mark = mark,
> + .flowi4_uid = sock_net_uid(net, NULL),
> + };
> unsigned long orefdst;
>
> - fl4_2.daddr = fl4_dec.saddr;
> rt2 = ip_route_output_key(net, &fl4_2);
> if (IS_ERR(rt2)) {
> err = PTR_ERR(rt2);
^ permalink raw reply
* Re: [PATCH v1 net 0/2] net: Fix two issues in sk_clone() error path.
From: Simon Horman @ 2026-07-16 10:29 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Willem de Bruijn, Octavian Purdila, Daniel Borkmann,
Alexei Starovoitov, Martin KaFai Lau, Kuniyuki Iwashima, netdev
In-Reply-To: <20260709183315.965751-1-kuniyu@google.com>
On Thu, Jul 09, 2026 at 06:31:38PM +0000, Kuniyuki Iwashima wrote:
> Sashiko reported issues in the sk_clone() error path.
>
> https://lore.kernel.org/bpf/20260709032007.9E4D61F000E9@smtp.kernel.org/
>
> This series fixes them.
>
> Note that Sashiko may point out the same issue for sk_bpf_storage,
> but the fix was already merged in the bpf tree:
>
> 7cbd0c4cebe4 ("bpf: Fix UAF in sock clone early bailouts")
>
>
> Kuniyuki Iwashima (2):
> soreuseport: Clear sk_reuseport_cb before failure in sk_clone().
> net: Call net_enable_timestamp() before failure in sk_clone().
For the series:
Reviewed-by: Simon Horman <horms@kernel.org>
^ permalink raw reply
* Re: [PATCH v4 0/2] bpf, sockmap: handle spurious tcp_msg_wait_data() wakeup
From: Nnamdi Onyeyiri @ 2026-07-16 10:24 UTC (permalink / raw)
To: Jiayuan Chen
Cc: bpf, davem, edumazet, horms, jakub, john.fastabend, kuba, kuniyu,
ncardwell, netdev, pabeni, sashiko-reviews
In-Reply-To: <95e690bf-2eed-469f-93ef-6ae3fb2a7162@linux.dev>
On Thu, Jul 16, 2026 at 09:30:30AM +0800, Jiayuan Chen wrote:
>
> Please do not send a patch by replying to an old thread.
>
> ...
>
> Please use a commit subject like "selftests/bpf: add selftest xxx" for the
> selftest patch.
>
Sorry, I'll resubmit with these changes.
>
> Please use existing test frameworks such as sockmap_basic.c or
> sockmap_strp.c.
>
Just to clarify, do you mean I should add the new tests to one of these
existing files? Or that I should add a new file, but write the test in the
same way as sockmap_basic.c implements them?
Thanks!
^ permalink raw reply
* [PATCH net v2] phonet: check register_netdevice_notifier() error in phonet_device_init()
From: Minhong He @ 2026-07-16 10:15 UTC (permalink / raw)
To: courmisch, davem, edumazet, kuba, pabeni, horms,
remi.denis-courmont
Cc: netdev, linux-kernel, Minhong He
phonet_device_init() registers a netdevice notifier before calling
phonet_netlink_register(), but does not check whether notifier
registration succeeded. On failure, netlink setup still proceeds and
init may return success without the notifier in place.
Check the notifier registration error and unwind only the resources
that were already registered (proc entry and pernet), without calling
unregister_netdevice_notifier() for a notifier that was never
registered.
Fixes: f8ff60283de2 ("Phonet: network device and address handling")
Signed-off-by: Minhong He <heminhong@kylinos.cn>
---
v2:
- On notifier registration failure, unwind only proc/pernet; do not call
phonet_device_exit() / unregister_netdevice_notifier() for a notifier
that was never registered.
v1: https://lore.kernel.org/netdev/20260713075212.431455-1-heminhong@kylinos.cn/
net/phonet/pn_dev.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index ad44831d6745..e6c31cfdad9a 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -356,7 +356,12 @@ int __init phonet_device_init(void)
proc_create_net("pnresource", 0, init_net.proc_net, &pn_res_seq_ops,
sizeof(struct seq_net_private));
- register_netdevice_notifier(&phonet_device_notifier);
+ err = register_netdevice_notifier(&phonet_device_notifier);
+ if (err) {
+ remove_proc_entry("pnresource", init_net.proc_net);
+ unregister_pernet_subsys(&phonet_net_ops);
+ return err;
+ }
err = phonet_netlink_register();
if (err)
phonet_device_exit();
--
2.25.1
^ permalink raw reply related
* Re: [PATCH net] mac802154: llsec: reject frames shorter than the authentication tag
From: Simon Horman @ 2026-07-16 10:09 UTC (permalink / raw)
To: Doruk Tan Ozturk
Cc: alex.aring, stefan, miquel.raynal, davem, edumazet, kuba, pabeni,
phoebe.buckheister, linux-wpan, netdev, linux-kernel, stable
In-Reply-To: <20260709131246.44517-1-doruk@0sec.ai>
On Thu, Jul 09, 2026 at 03:12:46PM +0200, Doruk Tan Ozturk wrote:
> llsec_do_decrypt_auth() computes the associated-data length for the
> AEAD request as
>
> assoclen += datalen - authlen;
>
> where datalen is the number of bytes after the MAC header and authlen
> (4, 8 or 16) is the length of the authentication tag. Nothing verifies
> that the frame actually carries at least authlen payload bytes. A
> secured frame whose payload is shorter than the tag makes
> datalen - authlen negative; assoclen is then passed to
> aead_request_set_ad() as an unsigned value close to 4 GiB, so
> crypto_aead_decrypt() walks far off the end of the scatterlist that
> only spans the real frame.
>
> The frame is fully attacker-controlled and reaches this path from any
> IEEE 802.15.4 peer in radio range. Reject frames whose payload is
> shorter than the authentication tag before the subtraction.
>
> Dynamically reproduced on a KASAN kernel as a general-protection-fault
> in the AEAD scatterwalk, and the fix confirmed.
>
> Fixes: 4c14a2fb5d14 ("mac802154: add llsec decryption method")
> Cc: stable@vger.kernel.org
> Reported-by: Doruk Tan Ozturk <doruk@0sec.ai>
> Assisted-by: 0sec:claude-opus-4-8
> Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
Reviewed-by: Simon Horman <horms@kernel.org>
^ permalink raw reply
* Re: [PATCH net-next v2 2/3] net: ti: icssm-prueth: Add priority based RX IRQ handlers
From: Parvathi Pudi @ 2026-07-16 10:09 UTC (permalink / raw)
To: Paolo Abeni
Cc: parvathi, andrew+netdev, davem, edumazet, kuba, danishanwar,
rogerq, pmohan, afd, basharath, arnd, linux-kernel, netdev,
linux-arm-kernel, pratheesh, j-rameshbabu, Vignesh Raghavendra,
praneeth, srk, rogerq, m-malladi, krishna, mohan
In-Reply-To: <20260706091328.134740-1-pabeni@redhat.com>
Hi,
> From: AI Reviewer <ai@example.com>
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> Full review at: https://sashiko.dev/
> ---
> net: ti: icssm-prueth: Add priority based RX IRQ handlers
>
> This patch adds support for priority based interrupt handling for the STP/
> RSTP Switch, HSR and PRP protocols along with extra logic to address first
> come first served to avoid port dominance. The driver will read the RX HW
> timestamp from the frame to achieve wire-arrival ordering.
>
>> diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth.c
>> b/drivers/net/ethernet/ti/icssm/icssm_prueth.c
>> --- a/drivers/net/ethernet/ti/icssm/icssm_prueth.c
>> +++ b/drivers/net/ethernet/ti/icssm/icssm_prueth.c
> [ ... ]
>> @@ -1188,26 +1188,26 @@ static int icssm_emac_ndo_stop(struct net_device *ndev)
>> /* disable the mac port */
>> icssm_prueth_port_enable(emac, false);
>>
>> + netif_stop_queue(ndev);
>> +
>> /* stop PHY */
>> phy_stop(emac->phydev);
>>
>> - napi_disable(&emac->napi);
>> hrtimer_cancel(&emac->tx_hrtimer);
>>
> [ ... ]
>> /* stop the PRU */
>> if (!PRUETH_IS_EMAC(prueth))
>> icssm_prueth_sw_shutdown_prus(emac, ndev);
>>
>> if (prueth_is_lre(prueth))
>> icssm_prueth_lre_cleanup(prueth);
>
> [Severity: High]
> This is a pre-existing issue, but is the LRE duplicate detection timer
> prematurely canceled when a single port goes down?
>
> In icssm_emac_ndo_stop, icssm_prueth_lre_cleanup is called unconditionally
> when any interface is brought down.
>
> If one port in the HSR/PRP bridge goes down while the other remains active,
> this cancels the shared tbl_check_timer, potentially causing duplicate
> frames to stop being detected and dropped by the hardware.
>
We will address this in the next version.
>> diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth_common.c
>> b/drivers/net/ethernet/ti/icssm/icssm_prueth_common.c
>> new file mode 100644
>> --- /dev/null
>> +++ b/drivers/net/ethernet/ti/icssm/icssm_prueth_common.c
>> @@ -0,0 +1,286 @@
> [ ... ]
>> +static int icssm_prueth_common_emac_rx_packets(struct prueth_emac *emac,
>> + int quota, u8 qid1, u8 qid2)
>> +{
> [ ... ]
>> + if ((*pkt_info_p).length < EMAC_MIN_PKTLEN) {
>> + /* Undersized frame: firmware should have filtered
>> + * these before they reach the host queue. Advance
>> + * the read pointer to skip it.
>> + */
>> + update_rd_ptr = *bd_wr_ptr_p;
>> + ndevstats_p->rx_length_errors++;
>
> [Severity: High]
> This is a pre-existing issue, but does this error path flush the entire
> pending RX queue?
>
> When the driver detects an undersized or oversized packet, it attempts to
> skip it by updating the read pointer. However, setting update_rd_ptr to
> *bd_wr_ptr_p appears to assign the hardware's write pointer (the very end of
> the queue), rather than advancing by one descriptor.
>
> Could this discard all pending descriptors instead of just the malformed one?
>
Yes, it flushes the pending queue. This behavior is pre-existing for the plain
EMAC RX path. Since it's not something introduced by these patches, we'd like
to evaluate it and fix it separately rather than bundle it into this series.
> [Severity: High]
> Does this introduce a race condition on the network statistics?
>
> This patch introduces split NAPI polling with separate priority threads
> (napi_hpq and napi_lpq) that process the high and low priority queues across
> both physical ports. These NAPI instances can be scheduled on different CPUs
> concurrently.
>
> Both instances invoke icssm_prueth_common_emac_rx_packets, which updates raw
> unsigned long statistics like ndevstats_p->rx_length_errors (and 64-bit
> stats like emac->stats.rx_bytes in icssm_emac_rx_packet) using += without
> atomic instructions or locks.
>
> On 32-bit platforms, could this cause lost updates for concurrent writers, or
> torn reads when read by ndo_get_stats64?
>
We are in the process of reviewing this comment and checking the statistics update
path with the split NAPI polling changes. We will incorporate any necessary updates
in the next version of the patch series.
>> + } else if ((*pkt_info_p).length > EMAC_MAX_FRM_SUPPORT) {
>> + /* Oversized frame: firmware should have filtered
>> + * these before they reach the host queue. Advance
>> + * the read pointer to skip it.
>> + */
>> + update_rd_ptr = *bd_wr_ptr_p;
>> + ndevstats_p->rx_length_errors++;
>> + } else {
>> + update_rd_ptr = *bd_rd_ptr_p;
>> + ret = icssm_emac_rx_packet(emac_p, &update_rd_ptr,
>> + pkt_info_p, rxqueue_p);
>> + if (ret)
>> + return used;
>
> [Severity: High]
> This is a pre-existing issue, but does a memory allocation failure in this RX
> path cause a permanent RX queue stall?
>
> If icssm_emac_rx_packet fails to allocate an SKB, it returns -ENOMEM. The
> driver immediately aborts the NAPI polling loop without updating the hardware
> read pointer or consuming the packet.
>
> Because it returns used (which is less than budget), it triggers
> napi_complete_done() which re-enables the RX interrupt. Since the packet is
> still pending in the hardware queue, the interrupt fires again immediately in
> an infinite loop.
>
This appears to be a pre-existing issue in the RX path and is not introduced by
this patch series. We'll investigate the reported behavior separately and address
it in a dedicated patch series if changes are required.
>> diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth_lre.c
>> b/drivers/net/ethernet/ti/icssm/icssm_prueth_lre.c
>> --- a/drivers/net/ethernet/ti/icssm/icssm_prueth_lre.c
>> +++ b/drivers/net/ethernet/ti/icssm/icssm_prueth_lre.c
>> @@ -152,6 +152,14 @@ static void icssm_prueth_lre_protocol_init(struct prueth
>> *prueth)
>> dram1 + ICSS_LRE_SUP_ADDR_LOW);
>> }
>>
>> +static void icssm_prueth_lre_config_packet_timestamping(struct prueth *prueth)
>> +{
>> + void __iomem *sram = prueth->mem[PRUETH_MEM_SHARED_RAM].va;
>> +
>> + writeb(1, sram + ICSS_LRE_PRIORITY_INTRS_STATUS_OFFSET);
>> + writeb(1, sram + ICSS_LRE_TIMESTAMP_PKTS_STATUS_OFFSET);
>> +}
>> +
> [ ... ]
>> @@ -202,6 +210,11 @@ void icssm_prueth_lre_config(struct prueth *prueth)
>> icssm_prueth_lre_init(prueth);
>> icssm_prueth_lre_dbg_init(prueth);
>> icssm_prueth_lre_protocol_init(prueth);
>> + /* Enable per-packet timestamping so the driver can order
>> + * received frames by arrival time across the two slave ports.
>> + */
>> + icssm_prueth_lre_config_packet_timestamping(prueth);
>> +
>> }
>
> [Severity: High]
> Does this fail to enable hardware timestamping in Switch mode?
>
> The patch introduces timestamp-based packet ordering for Switch, HSR, and PRP
> modes, requiring configuration via ICSS_LRE_PRIORITY_INTRS_STATUS_OFFSET and
> ICSS_LRE_TIMESTAMP_PKTS_STATUS_OFFSET.
>
> However, icssm_prueth_lre_config_packet_timestamping is only called from
> icssm_prueth_lre_config, which is gated by prueth_is_lre() (only true for HSR
> and PRP).
>
> In Switch mode, these registers appear to never be written, potentially
> leaving timestamps disabled in firmware and breaking the wire-arrival
> ordering logic.
>
We will address this in the next version.
> [Severity: High]
> This is a pre-existing issue, but are the dynamically allocated FDB learning
> work items tracked for cleanup?
>
> When learning a new source MAC address in icssm_prueth_sw_learn_fdb()
> (drivers/net/ethernet/ti/icssm/icssm_prueth_switch.c), the driver dynamically
> allocates a struct icssm_prueth_sw_fdb_work and queues it.
>
> If these are not tracked in a list, unloading the module could leave pending
> work items that execute unmapped memory, potentially causing a kernel panic.
>
As this is a pre-existing issue related to the FDB implementation, we'll address
it as a separate patch series rather than merging it into this series. This avoids
expanding the scope of the current patch series.
> [Severity: High]
> This is a pre-existing issue, but can the unbounded GFP_ATOMIC allocations
> for FDB learning lead to memory exhaustion?
>
> Every received frame with an unlearned source MAC address triggers
> icssm_prueth_sw_learn_fdb(), which uses kzalloc_obj(..., GFP_ATOMIC) without
> rate limiting.
>
> A continuous flood of frames with randomized source MAC addresses could
> trigger thousands of allocations per second, potentially exhausting the
> kernel's atomic memory pools.
> --
As this is a pre-existing issue related to the FDB implementation, we'll address
it as a separate patch series rather than merging it into this series. This avoids
expanding the scope of the current patch series.
Thanks and Regards,
Parvathi.
^ permalink raw reply
* Re: [PATCH net v2] nfc: llcp: bound the connect_sn TLV walk to the skb
From: Simon Horman @ 2026-07-16 10:07 UTC (permalink / raw)
To: Doruk Tan Ozturk
Cc: david, oe-linux-nfc, david.laight.linux, netdev, linux-kernel,
stable
In-Reply-To: <20260709131229.44477-1-doruk@0sec.ai>
On Thu, Jul 09, 2026 at 03:12:29PM +0200, Doruk Tan Ozturk wrote:
> Commit 27256cdb290e ("nfc: llcp: bound SNL TLV parsing to the skb and
> add length checks") fixed the unbounded TLV walk in nfc_llcp_recv_snl(),
> and commit d8bd2dedbde5 ("nfc: llcp: fix OOB read and u8 offset wrap in
> TLV parsers") subsequently bounded nfc_llcp_parse_gb_tlv() and
> nfc_llcp_parse_connection_tlv(). One sibling parser sharing the same
> pattern remains unbounded: nfc_llcp_connect_sn().
>
> nfc_llcp_connect_sn() walks a TLV list, reading a two-byte header
> (type, length) followed by length bytes of value, without checking that
> the two header bytes or the declared length stay within the buffer. It
> returns a pointer to a service name of up to 255 bytes that may point
> past the end of the skb; it is subsequently consumed by memcmp() in
> nfc_llcp_sock_from_sn(). In addition tlv_array_len was computed as
> "skb->len - LLCP_HEADER_SIZE" in size_t, so a CONNECT/CC frame shorter
> than the LLCP header underflows to a huge length and the walk runs far
> past the buffer.
>
> nfc_llcp_connect_sn() is reachable from nfc_llcp_recv_connect() and
> nfc_llcp_recv_cc(), i.e. from received CONNECT and CC PDUs. A nearby
> NFC device can reach this without authentication; LLCP link activation
> happens automatically after NFC-DEP, and the nfc_llcp_rx_skb()
> dispatcher applies no minimum-length guard.
>
> Walk the TLV list by pointer, bounded by skb_tail_pointer(skb), and
> validate each declared length before use, matching the approach already
> used for nfc_llcp_recv_snl(). Starting the walk at
> &skb->data[LLCP_HEADER_SIZE] against the tail pointer also removes the
> size_t underflow for short frames.
>
> Found by 0sec automated security-research tooling (https://0sec.ai).
>
> Fixes: d646960f7986 ("NFC: Initial LLCP support")
> Cc: stable@vger.kernel.org
> Assisted-by: 0sec:claude-opus-4-8
> Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
> ---
> v2: drop the nfc_llcp_parse_gb_tlv() and nfc_llcp_parse_connection_tlv()
> hunks - fixed independently by d8bd2dedbde5. This resend covers only
> the still-unbounded nfc_llcp_connect_sn().
> v1: https://lore.kernel.org/netdev/20260705113505 net/nfc/llcp_core.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
Reviewed-by: Simon Horman <horms@kernel.org>
^ permalink raw reply
* [PATCH bpf] veth: convert frag_list skbs before running XDP
From: Matt Fleming @ 2026-07-16 10:06 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi,
Toke Høiland-Jørgensen, bpf, netdev, stable,
kernel-team, Matt Fleming
From: Matt Fleming <mfleming@cloudflare.com>
A frag_list skb can reach veth with data_len set but nr_frags zero.
veth_convert_skb_to_xdp_buff() only converts skbs that are shared,
locked, have frags[], or do not have enough headroom. It later uses
skb_is_nonlinear() to decide whether to set XDP_FLAGS_HAS_FRAGS and
xdp_frags_size.
That exposes frag_list data to XDP as if it were stored in frags[], but
frags[] is empty. AF_XDP copy mode can then trust the bogus XDP fragment
metadata, walk an empty fragment entry, and crash in memcpy() from
__xsk_rcv().
Route frag_list skbs through skb_pp_cow_data() before exposing them to
XDP, and only advertise XDP frags when the resulting skb has frags[].
skb_copy_bits() already handles frag_list input, and skb_pp_cow_data()
builds frags[] output with skb_add_rx_frag(), which is the representation
XDP multi-buffer expects.
Fixes: 718a18a0c8a6 ("veth: Rework veth_xdp_rcv_skb in order to accept non-linear skb")
Cc: stable@vger.kernel.org
Signed-off-by: Matt Fleming <mfleming@cloudflare.com>
---
drivers/net/veth.c | 4 ++--
net/core/skbuff.c | 9 ++++-----
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 1c5142149175..efb24aae1f26 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -756,7 +756,7 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
u32 frame_sz;
if (skb_shared(skb) || skb_head_is_locked(skb) ||
- skb_shinfo(skb)->nr_frags ||
+ skb_shinfo(skb)->nr_frags || skb_has_frag_list(skb) ||
skb_headroom(skb) < XDP_PACKET_HEADROOM) {
if (skb_pp_cow_data(rq->page_pool, pskb, XDP_PACKET_HEADROOM))
goto drop;
@@ -771,7 +771,7 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
xdp_prepare_buff(xdp, skb->head, skb_headroom(skb),
skb_headlen(skb), true);
- if (skb_is_nonlinear(skb)) {
+ if (skb_shinfo(skb)->nr_frags) {
skb_shinfo(skb)->xdp_frags_size = skb->data_len;
xdp_buff_set_frags_flag(xdp);
} else {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 18dabb4e9cfa..1e837d01a908 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -936,12 +936,11 @@ int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
int err, i, head_off;
void *data;
- /* XDP does not support fraglist so we need to linearize
- * the skb.
+ /*
+ * skb_copy_bits() handles both frags[] and frag_list input. If the
+ * copied skb remains non-linear, it uses frags[], which is the
+ * representation used by XDP multi-buffer.
*/
- if (skb_has_frag_list(skb))
- return -EOPNOTSUPP;
-
max_head_size = SKB_WITH_OVERHEAD(PAGE_SIZE - headroom);
if (skb->len > max_head_size + MAX_SKB_FRAGS * PAGE_SIZE)
return -ENOMEM;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] vhost-vdpa: reject zero-size unmap
From: Eugenio Perez Martin @ 2026-07-16 10:04 UTC (permalink / raw)
To: Weimin Xiong; +Cc: virtualization, mst, jasowangio, netdev, kvm, xiongweimin
In-Reply-To: <20260716030238.124368-1-xiongwm2026@163.com>
On Thu, Jul 16, 2026 at 5:02 AM Weimin Xiong <xiongwm2026@163.com> wrote:
>
> From: xiongweimin <xiongweimin@kylinos.cn>
>
> Reject unmap requests with size == 0 to prevent iova + size - 1
> from underflowing to U64_MAX, which would incorrectly unmap the
> entire IOTLB range.
>
> This fix also covers the error rollback path in vhost_vdpa_va_map:
> when the first VMA lookup fails, map_iova equals iova, resulting
> in a zero-size unmap that would otherwise clear the whole IOTLB.
>
> Signed-off-by: xiongweimin <xiongweimin@kylinos.cn>
Acked-by: Eugenio Pérez <eperezma@redhat.com>
Thanks!
> ---
> drivers/vhost/vdpa.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
> index bb96b1aa5..f49bf1cfb 100644
> --- a/drivers/vhost/vdpa.c
> +++ b/drivers/vhost/vdpa.c
> @@ -1035,6 +1035,9 @@ static void vhost_vdpa_unmap(struct vhost_vdpa *v,
> const struct vdpa_config_ops *ops = vdpa->config;
> u32 asid = iotlb_to_asid(iotlb);
>
> + if (!size)
> + return;
> +
> vhost_vdpa_iotlb_unmap(v, iotlb, iova, iova + size - 1, asid);
>
> if (ops->set_map) {
> --
> 2.39.3
>
^ permalink raw reply
* [PATCH v2 1/2] net: sctp: socket: Fix uninitialized error on socket shutdown
From: luoqing @ 2026-07-16 10:04 UTC (permalink / raw)
To: marcelo.leitner, lucien.xin, davem, edumazet, kuba, pabeni
Cc: horms, linux-sctp, netdev, linux-kernel, luoqing
From: luoqing <luoqing@kylinos.cn>
When sctp_skb_recv_datagram() detects sk->sk_shutdown & RCV_SHUTDOWN,
it breaks out of the loop and returns NULL without setting *err.
This leaves the error pointer uninitialized or with a stale value,
which can confuse callers expecting a clean shutdown indication.
Compare with the generic __skb_wait_for_more_packets() in
net/core/datagram.c which properly handles shutdown by setting *err = 0.
Fix this by setting *err = 0 before breaking when the socket is shut down,
indicating an orderly shutdown rather than an error condition.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: luoqing <luoqing@kylinos.cn>
---
net/sctp/socket.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c7b9e325ec1c..ea7050b27715 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -9117,8 +9117,10 @@ struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int *err)
if (error)
goto no_packet;
- if (sk->sk_shutdown & RCV_SHUTDOWN)
+ if (sk->sk_shutdown & RCV_SHUTDOWN) {
+ *err = 0;
break;
+ }
/* User doesn't want to wait. */
--
2.25.1
^ permalink raw reply related
* [PATCH v2 2/2] net: sctp: auth: Fix safety issue when skb_clone fails in auth_chunk handling
From: luoqing @ 2026-07-16 10:04 UTC (permalink / raw)
To: marcelo.leitner, lucien.xin, davem, edumazet, kuba, pabeni
Cc: horms, linux-sctp, netdev, linux-kernel, luoqing
In-Reply-To: <20260716100407.1490724-1-l1138897701@163.com>
From: luoqing <luoqing@kylinos.cn>
When processing AUTH + COOKIE-ECHO packets, if skb_clone fails due to
memory pressure, chunk->auth_chunk is set to NULL but chunk->auth is
still set to 1. This causes sctp_auth_chunk_verify to skip the AUTH
validation (since auth_chunk is NULL), allowing unauthenticated
COOKIE-ECHO packets to be accepted.
Fix this by only setting chunk->auth = 1 when skb_clone succeeds.
Fixes: 59d8d4434f429b ("sctp: delay the authentication for the duplicated cookie-echo chunk")
Signed-off-by: luoqing <luoqing@kylinos.cn>
---
net/sctp/associola.c | 3 ++-
net/sctp/endpointola.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 62d3cc155809..e54068305396 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -999,7 +999,8 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
chunk->auth_chunk = skb_clone(chunk->skb,
GFP_ATOMIC);
- chunk->auth = 1;
+ if (chunk->auth_chunk)
+ chunk->auth = 1;
continue;
}
}
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index dfb1719275db..3419748c66bc 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -368,7 +368,8 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
chunk->auth_chunk = skb_clone(chunk->skb,
GFP_ATOMIC);
- chunk->auth = 1;
+ if (chunk->auth_chunk)
+ chunk->auth = 1;
continue;
}
}
--
2.25.1
^ permalink raw reply related
* Re: [PATCH] vhost-vdpa: propagate set_map error to caller
From: Eugenio Perez Martin @ 2026-07-16 10:01 UTC (permalink / raw)
To: Weimin Xiong; +Cc: virtualization, mst, jasowangio, netdev, kvm, xiongweimin
In-Reply-To: <20260716030242.124455-1-xiongwm2026@163.com>
On Thu, Jul 16, 2026 at 5:02 AM Weimin Xiong <xiongwm2026@163.com> wrote:
>
> From: xiongweimin <xiongweimin@kylinos.cn>
>
> The return value of ops->set_map() is currently ignored when handling
> VHOST_IOTLB_BATCH_END. If the backend fails to program the IOTLB,
> the VMM incorrectly believes the operation succeeded and may continue
> with stale or incorrect mappings.
>
> Save and propagate the error from ops->set_map() in BATCH_END.
>
> Signed-off-by: xiongweimin <xiongweimin@kylinos.cn>
> ---
> drivers/vhost/vdpa.c | 6 +++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
> index bb96b1aa5..ffbb10a92 100644
> --- a/drivers/vhost/vdpa.c
> +++ b/drivers/vhost/vdpa.c
> @@ -1297,8 +1297,10 @@ static int vhost_vdpa_process_iotlb_msg(struct vhost_dev *dev, u32 asid,
> v->in_batch = true;
> break;
> case VHOST_IOTLB_BATCH_END:
> - if (v->in_batch && ops->set_map)
> - ops->set_map(vdpa, asid, iotlb);
> + if (v->in_batch && ops->set_map) {
> + r = ops->set_map(vdpa, asid, iotlb);
> + break;
> + }
> v->in_batch = false;
Maybe this needs to be discussed, but v->in_batch should be set to
false even in failure case.
> break;
> default:
> --
> 2.39.3
>
^ permalink raw reply
* Re: [PATCH v4 3/3] drm/xe/xe_ras: Add error-event support for CRI
From: Tauro, Riana @ 2026-07-16 9:57 UTC (permalink / raw)
To: Raag Jadav
Cc: intel-xe, dri-devel, netdev, aravind.iddamsetty, anshuman.gupta,
rodrigo.vivi, joonas.lahtinen, kuba, simona.vetter, airlied,
pratik.bari, joshua.santosh.ranjan, ashwin.kumar.kulkarni,
shubham.kumar, ravi.kishore.koppuravuri, maarten.lankhorst,
mallesh.koujalagi, soham.purkait, Michal Wajdeczko
In-Reply-To: <ak9yEyDF_tlJe-Rx@black.igk.intel.com>
On 09-07-2026 15:34, Raag Jadav wrote:
> On Wed, Jul 01, 2026 at 03:14:13PM +0530, Riana Tauro wrote:
>> Add error-event support for Correctable errors in CRI. Report an error
>> event to userspace for every component that has crossed the threshold on
>> receiving an interrupt.
> ...
>
>> +static void ras_send_error_event(struct xe_device *xe, u8 severity, u8 component)
>> +{
>> + u8 drm_severity, drm_component;
>> + u32 value;
>> + int ret;
>> +
>> + drm_severity = xe_to_drm_ras_severity(severity);
>> + if (drm_severity == DRM_XE_RAS_ERR_SEV_MAX) {
>> + xe_warn(xe, "sysctrl: unexpected severity %u\n", severity);
> This is uapi and not coming from sysctrl, so the message is a bit
> misleading. But if at all it needs validation, it should be done in
> drm_ras layer.
You mean in the ras_event function? The parameters to this function are
coming from sysctrl.
So added sysctrl flag
>
>> + return;
>> + }
>> +
>> + drm_component = xe_to_drm_ras_component(component);
>> + if (drm_component == DRM_XE_RAS_ERR_COMP_MAX) {
>> + xe_warn(xe, "sysctrl: unexpected component %u\n", component);
> Ditto.
>
>> + return;
>> + }
>> +
>> + ret = xe_ras_get_counter(xe, drm_severity, drm_component, &value);
> No, instead of converting back and forth just do get_counter() using
> sysctrl values and send_event() afterwards.
The reason for using this is to avoid unnecessary churn of moving the
get counter above or use forward declaration.
Yeah i can use that too directly.
>> + if (ret)
>> + return;
>> +
>> + xe_drm_ras_event(xe, drm_component, drm_severity, value, GFP_KERNEL);
>> +}
>> +
>> void xe_ras_counter_threshold_crossed(struct xe_device *xe,
>> struct xe_sysctrl_event_response *response)
>> {
>> struct xe_ras_threshold_crossed *pending = (void *)&response->data;
>> struct xe_ras_error_class *errors = pending->counters;
>> u32 id, ncounters = pending->ncounters;
>> + u8 sent = 0;
>>
>> BUILD_BUG_ON(sizeof(response->data) < sizeof(*pending));
>> + BUILD_BUG_ON(XE_RAS_COMP_MAX > (BITS_PER_BYTE * sizeof(sent)));
> I prefer it the other way around. Also, have you tried using BITS_PER_TYPE()?
>
> BUILD_BUG_ON(BITS_PER_TYPE(sent) < XE_RAS_COMP_MAX));
Will try this
>
>> xe_device_assert_mem_access(xe);
>>
>> if (!ncounters || ncounters > XE_RAS_NUM_COUNTERS)
>> @@ -154,6 +211,24 @@ void xe_ras_counter_threshold_crossed(struct xe_device *xe,
>>
>> xe_warn(xe, "[RAS]: %s %s detected\n",
>> comp_to_str(component), sev_to_str(severity));
>> +
>> + if (severity != XE_RAS_SEV_CORRECTABLE) {
>> + xe_warn(xe, "sysctrl: unexpected severity %s (%u)\n", sev_to_str(severity),
>> + severity);
> This should be before "detected" log above.
okay
>
>> + continue;
>> + }
>> +
>> + if (component >= XE_RAS_COMP_MAX) {
>> + xe_warn(xe, "sysctrl: unexpected component %u\n", component);
> Ditto. Also, use xx_to_str() in both cases or don't but be consistent.
>
It will only display not supported. Will remove the string in both.
Thanks
Riana
>
> Raag
>
>> + continue;
>> + }
>> +
>> + /* Send event once per component */
>> + if (sent & BIT(component))
>> + continue;
>> + sent |= BIT(component);
>> +
>> + ras_send_error_event(xe, severity, component);
>> }
>> }
>>
>> --
>> 2.47.1
>>
^ permalink raw reply
* Re: [PATCH net] geneve: fix hint header definition wrt endianness
From: Simon Horman @ 2026-07-16 9:55 UTC (permalink / raw)
To: Antoine Tenart; +Cc: davem, kuba, pabeni, edumazet, netdev, Sashiko
In-Reply-To: <20260709124801.140632-1-atenart@kernel.org>
On Thu, Jul 09, 2026 at 02:48:00PM +0200, Antoine Tenart wrote:
> Bitfields are packed differently depending on the endianness, take it into
> account in the GRO hint header definition.
>
> Fixes: e0a12cbf262b ("geneve: add GRO hint output path")
> Cc: Paolo Abeni <pabeni@redhat.com>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://sashiko.dev/#/patchset/20260529144713.780938-1-atenart%40kernel.org
> Signed-off-by: Antoine Tenart <atenart@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
^ permalink raw reply
* Re: [PATCH net] geneve: ensure the skb is writable before fixing its headers
From: Simon Horman @ 2026-07-16 9:51 UTC (permalink / raw)
To: Antoine Tenart; +Cc: davem, kuba, pabeni, edumazet, netdev, Sashiko
In-Reply-To: <20260709125000.141092-1-atenart@kernel.org>
On Thu, Jul 09, 2026 at 02:50:00PM +0200, Antoine Tenart wrote:
> Make sure the IPv4/6 and UDP headers are writable before fixing them up in
> geneve_post_decap_hint. As skb_ensure_writable can reallocate the skb linear
> area, reload the GRO hint header pointer and only set the IPv4/6 header ones
> after the call.
>
> Fixes: fd0dd796576e ("geneve: use GRO hint option in the RX path")
> Cc: Paolo Abeni <pabeni@redhat.com>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://sashiko.dev/#/patchset/20260529144713.780938-1-atenart%40kernel.org
> Signed-off-by: Antoine Tenart <atenart@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
^ permalink raw reply
* Re: [PATCH net-next v1 00/11] net: flow_dissector: opt-in byte-identical fast paths for common shapes
From: Willem de Bruijn @ 2026-07-16 9:50 UTC (permalink / raw)
To: Dave Seddon, netdev
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Stanislav Fomichev, Tom Herbert, Willem de Bruijn, linux-kernel,
Dave Seddon
In-Reply-To: <20260716004357.3652679-1-dave.seddon.ca@gmail.com>
Dave Seddon wrote:
> G'day,
>
> __skb_flow_dissect() parses packet headers with a generic protocol-graph
> parser. The graph walk is what makes the dissector so flexible, but most
> machines spend that flexibility on the same traffic all day long: plain
> eth + IPv4/IPv6 + TCP/UDP, perhaps with a VLAN tag or a tunnel header in
> front. The intuition behind this series is that the common shapes can be
> dissected by straight-line code instead, without giving up the graph
> walk for everything else.
>
> Concretely: the series adds an opt-in, static-branch-gated fast path per
> packet shape, covering the common cases and the IP-in-IP/GRE
> encapsulations. Each shape has its own gate under
> /proc/sys/net/flow_dissector/, every gate is disabled by default, and
> when a gate is off its added cost is one not-taken branch per dissect.
> The gates are manual in this series; a follow-up RFC will propose an
> optional auto mode that flips them from the measured traffic mix (via
> the patch-8 counters), so nobody has to hand-tune seven knobs
> (eth_ip, vlan, qinq, pppoe, mpls, ipip, gre). Nothing
> here depends on it -- it is where this is heading, not a prerequisite.
> Relationship to the BPF flow dissector
> ======================================
> The fast path is invoked strictly after the netns BPF flow dissector
> hook in __skb_flow_dissect(): if a program is attached and returns any
> verdict other than BPF_FLOW_DISSECTOR_CONTINUE, the function returns
> before flow_dissect_fast() is reached. Attached BPF dissectors therefore
> always take precedence, and a system running one sees bit-for-bit
> unchanged behaviour from this series (patch 1 additionally makes its
> program lookup cheaper for everyone else). Dissects fully handled by a
> BPF program are deliberately not counted in
> /proc/net/flow_dissector_stats (patch 8).
>
> The gates are global (a static key patches code shared by every netns);
> per-netns dissector policy already has a mechanism -- the netns BPF
> flow dissector -- and it keeps full precedence here.
This series adds a lot of code: +2500 LoC.
If you want a linear fast path, the BPF dissector offers that.
I don't think the purported benefit justifies the significant new
code, I'm afraid.
The code is duplicative of existing paths, so there may be additional
maintenance cost keeping the two consistent.
And which paths justify a fast paths and which do not is highly
subjective. Why is GRE included, for instance?
^ permalink raw reply
* Re: net: rnpgbe: Pass an expression directly in rnpgbe_rm_adapter()
From: Markus Elfring @ 2026-07-16 9:48 UTC (permalink / raw)
To: Dan Carpenter, netdev, kernel-janitors
Cc: Uwe Kleine-König, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, MD Danish Anwar, Michael Grzeschik, Paolo Abeni,
Vadim Fedorenko, Yibo Dong, LKML, Jonathan Corbet
In-Reply-To: <alikx3W3NX7r9o99@stanley.mountain>
> In C writing if (!p) and if (p == NULL) are always equivalent but weirdly
> the NULL doesn't have to zero. It's part of the C FAQ.
> https://c-faq.com/null/machexamp.html It's just a bit of fun trivia that
> doesn't really matter unless you have a time machine. Even if you invented
> a time machine, the code here would still be fine because we have a NULL
> test before dereferencing the results of our pointer math.
Which expression evaluations would you interpret as pointer dereferences finally?
https://c-faq.com/sx1/
Regards,
Markus
^ permalink raw reply
* Re: [PATCH iproute2-next 2/2] seg6: man: document the lookup attribute for SRv6 encap routes
From: Nicolas Dichtel @ 2026-07-16 9:49 UTC (permalink / raw)
To: Andrea Mayer, David Ahern, netdev
Cc: Stephen Hemminger, Stefano Salsano, Ahmed Abdelsalam,
Paolo Lungaroni, Justin Iurman, Anthony Doeraene
In-Reply-To: <20260712021155.7621-3-andrea.mayer@uniroma2.it>
Le 12/07/2026 à 04:11, Andrea Mayer a écrit :
> Document the new optional "lookup" attribute for seg6 encap routes. It
> selects the FIB table for the post-encap SID route lookup and accepts a
> table number or a table name.
>
> Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
^ permalink raw reply
* [PATCH iwl-next v1 4/4] ice: dpll: Rework the SMA control logic to match the requirements
From: Sergey Temerkhanov @ 2026-07-16 9:49 UTC (permalink / raw)
To: intel-wired-lan; +Cc: netdev
In-Reply-To: <20260716094912.1210865-1-sergey.temerkhanov@intel.com>
Make the SMA control logic match the requirements:
Setting SMA1 as Rx automatically enables U.FL1 as Tx if U.FL1 is
disconnected.
Setting SMA1 as Tx automatically changes U.FL1 state to disconnected.
Setting SMA2 as Tx automatically enables U.FL2 as Rx if U.FL2 is
disconnected.
Setting SMA2 as Rx automatically changes U.FL2 state to disconnected.
Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
Reviewed-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
---
drivers/net/ethernet/intel/ice/ice_dpll.c | 88 ++++++++++++++++++++---
1 file changed, 78 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c
index cb14621b3aef..f11d90ed80f2 100644
--- a/drivers/net/ethernet/intel/ice/ice_dpll.c
+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
@@ -698,10 +698,10 @@ ice_dpll_sw_pins_update(struct ice_pf *pf)
p = &d->sma[ICE_DPLL_PIN_SW_2_IDX];
p->active = true;
p->direction = DPLL_PIN_DIRECTION_INPUT;
+ if (data & ICE_SMA2_DIR_EN)
+ p->direction = DPLL_PIN_DIRECTION_OUTPUT;
if ((data & ICE_SMA2_INACTIVE_MASK) == ICE_SMA2_INACTIVE_MASK)
p->active = false;
- else if (data & ICE_SMA2_DIR_EN)
- p->direction = DPLL_PIN_DIRECTION_OUTPUT;
p = &d->ufl[ICE_DPLL_PIN_SW_1_IDX];
if (!(data & (ICE_SMA1_DIR_EN | ICE_SMA1_TX_EN)))
@@ -1224,17 +1224,21 @@ static int ice_dpll_sma_direction_set(struct ice_dpll_pin *p,
switch (p->idx) {
case ICE_DPLL_PIN_SW_1_IDX:
- data &= ~ICE_SMA1_MASK;
- if (direction == DPLL_PIN_DIRECTION_OUTPUT)
+ if (direction == DPLL_PIN_DIRECTION_OUTPUT) {
+ data &= ~ICE_SMA1_TX_EN;
data |= ICE_SMA1_DIR_EN;
+ } else {
+ data &= ~ICE_SMA1_DIR_EN;
+ data &= ~ICE_SMA1_TX_EN;
+ }
break;
case ICE_DPLL_PIN_SW_2_IDX:
if (direction == DPLL_PIN_DIRECTION_INPUT) {
data &= ~ICE_SMA2_DIR_EN;
- data |= ICE_SMA2_UFL2_RX_DIS;
} else {
- data &= ~(ICE_SMA2_TX_EN | ICE_SMA2_UFL2_RX_DIS);
data |= ICE_SMA2_DIR_EN;
+ data &= ~ICE_SMA2_UFL2_RX_DIS;
+ data &= ~ICE_SMA2_TX_EN;
}
break;
default:
@@ -1505,6 +1509,7 @@ ice_dpll_sma_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
struct ice_dpll *d = dpll_priv;
struct ice_pf *pf = sma->pf;
enum ice_dpll_pin_type type;
+ u8 old_data = 0;
bool enable;
int ret;
@@ -1556,13 +1561,76 @@ ice_dpll_sma_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
goto unlock;
}
- if (enable)
+ if (enable) {
+ u8 data;
+
+ ret = ice_read_sma_ctrl(&pf->hw, &data);
+ if (ret)
+ goto unlock;
+ old_data = data;
+ if (sma->idx == ICE_DPLL_PIN_SW_1_IDX) {
+ data &= ~ICE_SMA1_TX_EN;
+ } else if (sma->idx == ICE_DPLL_PIN_SW_2_IDX) {
+ data &= ~ICE_SMA2_UFL2_RX_DIS;
+ data &= ~ICE_SMA2_TX_EN;
+ }
+ ret = ice_write_sma_ctrl(&pf->hw, data);
+ if (ret)
+ goto unlock;
+ ret = ice_dpll_sw_pins_update(pf);
+ if (ret)
+ goto restore_sma_ctrl;
+
ret = ice_dpll_pin_enable(&pf->hw, target, d->dpll_idx, type,
extack);
- else
- ret = ice_dpll_pin_disable(&pf->hw, target, type, extack);
- if (!ret)
+ if (ret)
+ goto restore_sma_ctrl;
+ /* refresh target state first so a peer-side error cannot leave it stale */
ret = ice_dpll_pin_state_update(pf, target, type, extack);
+ if (ret)
+ goto restore_sma_ctrl;
+
+ if (sma->muxed->active) {
+ struct ice_dpll_pin *peer = sma->muxed;
+ struct ice_dpll_pin *peer_target;
+ enum ice_dpll_pin_type peer_type;
+
+ if (peer->direction == DPLL_PIN_DIRECTION_OUTPUT) {
+ peer_target = peer->output;
+ peer_type = ICE_DPLL_PIN_TYPE_OUTPUT;
+ } else {
+ peer_target = peer->input;
+ peer_type = ICE_DPLL_PIN_TYPE_INPUT;
+ }
+ ret = ice_dpll_pin_enable(&pf->hw, peer_target,
+ d->dpll_idx,
+ peer_type, extack);
+ if (!ret)
+ ret = ice_dpll_pin_state_update(pf, peer_target,
+ peer_type, extack);
+ if (ret)
+ goto restore_sma_ctrl;
+ }
+ } else {
+ ret = ice_dpll_pin_disable(&pf->hw, target, type, extack);
+ if (!ret)
+ ret = ice_dpll_pin_state_update(pf, target, type,
+ extack);
+ }
+ goto unlock;
+
+restore_sma_ctrl:
+ {
+ int restore_ret;
+
+ restore_ret = ice_write_sma_ctrl(&pf->hw, old_data);
+ if (!restore_ret)
+ restore_ret = ice_dpll_sw_pins_update(pf);
+ if (restore_ret)
+ dev_warn(ice_pf_to_dev(pf),
+ "Failed to restore SMA control after pin state error %d, restore err %d\n",
+ ret, restore_ret);
+ }
unlock:
mutex_unlock(&pf->dplls.lock);
--
2.53.0
^ permalink raw reply related
* [PATCH iwl-next v1 3/4] ice: dpll: Rework U.FL muxed pin (SMA) control
From: Sergey Temerkhanov @ 2026-07-16 9:49 UTC (permalink / raw)
To: intel-wired-lan; +Cc: netdev
In-Reply-To: <20260716094912.1210865-1-sergey.temerkhanov@intel.com>
Rework multiplexed pin control to match the state change listed in
the design requirements.
Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
---
drivers/net/ethernet/intel/ice/ice_dpll.c | 35 ++++++++++++++++++++---
1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c
index 54958e17713b..cb14621b3aef 100644
--- a/drivers/net/ethernet/intel/ice/ice_dpll.c
+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
@@ -1381,12 +1381,39 @@ ice_dpll_ufl_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
if (ret)
goto unlock;
- if (enable)
+ if (enable) {
ret = ice_dpll_pin_enable(hw, target, d->dpll_idx, type, extack);
- else
+ if (!ret)
+ ret = ice_dpll_pin_state_update(pf, target, type, extack);
+ if (!ret && p->muxed->active) {
+ struct ice_dpll_pin *peer = p->muxed;
+ struct ice_dpll_pin *peer_target;
+ enum ice_dpll_pin_type peer_type;
+ int peer_ret;
+
+ if (peer->direction == DPLL_PIN_DIRECTION_OUTPUT) {
+ peer_target = peer->output;
+ peer_type = ICE_DPLL_PIN_TYPE_OUTPUT;
+ } else {
+ peer_target = peer->input;
+ peer_type = ICE_DPLL_PIN_TYPE_INPUT;
+ }
+ peer_ret = ice_dpll_pin_enable(&pf->hw, peer_target,
+ pf->dplls.eec.dpll_idx,
+ peer_type, NULL);
+ if (!peer_ret)
+ peer_ret = ice_dpll_pin_state_update(pf, peer_target,
+ peer_type, NULL);
+ if (peer_ret)
+ dev_warn(ice_pf_to_dev(pf),
+ "Failed to sync peer pin %u after enabling U.FL pin %u, err %d\n",
+ peer_target->idx, target->idx, peer_ret);
+ }
+ } else {
ret = ice_dpll_pin_disable(hw, target, type, extack);
- if (!ret)
- ret = ice_dpll_pin_state_update(pf, target, type, extack);
+ if (!ret)
+ ret = ice_dpll_pin_state_update(pf, target, type, extack);
+ }
unlock:
mutex_unlock(&pf->dplls.lock);
--
2.53.0
^ permalink raw reply related
* [PATCH iwl-next v1 2/4] ice: dpll: Use switch statements to handle pin states
From: Sergey Temerkhanov @ 2026-07-16 9:49 UTC (permalink / raw)
To: intel-wired-lan; +Cc: netdev
In-Reply-To: <20260716094912.1210865-1-sergey.temerkhanov@intel.com>
Use switch statements to handle pin states to make the code more
readable. This also makes this code more future-proof, should any
new states appear.
This also changes how direction-mismatched state requests are handled in
ice_dpll_sma_pin_state_set(). Previously, requesting CONNECTED on an
INPUT-direction SMA pin or SELECTABLE on an OUTPUT-direction pin would
fall through to ice_dpll_pin_disable() and return success. After this
change those requests return -EINVAL without issuing a firmware command.
Because the DPLL netlink core does not filter pin states by direction
before calling the driver, this is a user-visible netlink API change.
Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
---
drivers/net/ethernet/intel/ice/ice_dpll.c | 65 ++++++++++++++++++-----
1 file changed, 53 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c
index fed7c9fea953..54958e17713b 100644
--- a/drivers/net/ethernet/intel/ice/ice_dpll.c
+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
@@ -1320,10 +1320,12 @@ ice_dpll_ufl_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
ret = -EINVAL;
switch (p->idx) {
case ICE_DPLL_PIN_SW_1_IDX:
- if (state == DPLL_PIN_STATE_CONNECTED) {
+ switch (state) {
+ case DPLL_PIN_STATE_CONNECTED:
data &= ~ICE_SMA1_MASK;
enable = true;
- } else if (state == DPLL_PIN_STATE_DISCONNECTED) {
+ break;
+ case DPLL_PIN_STATE_DISCONNECTED:
/* Skip if U.FL1 is not active, setting TX_EN
* while DIR_EN is set would also deactivate
* the paired SMA1 output.
@@ -1334,18 +1336,21 @@ ice_dpll_ufl_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
}
data |= ICE_SMA1_TX_EN;
enable = false;
- } else {
+ break;
+ default:
goto unlock;
}
target = p->output;
type = ICE_DPLL_PIN_TYPE_OUTPUT;
break;
case ICE_DPLL_PIN_SW_2_IDX:
- if (state == DPLL_PIN_STATE_SELECTABLE) {
+ switch (state) {
+ case DPLL_PIN_STATE_SELECTABLE:
data |= ICE_SMA2_DIR_EN;
data &= ~ICE_SMA2_UFL2_RX_DIS;
enable = true;
- } else if (state == DPLL_PIN_STATE_DISCONNECTED) {
+ break;
+ case DPLL_PIN_STATE_DISCONNECTED:
/* Skip if U.FL2 is not active, setting
* UFL2_RX_DIS could also disable the paired
* SMA2 input.
@@ -1357,7 +1362,8 @@ ice_dpll_ufl_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
}
data |= ICE_SMA2_UFL2_RX_DIS;
enable = false;
- } else {
+ break;
+ default:
goto unlock;
}
target = p->input;
@@ -1484,14 +1490,43 @@ ice_dpll_sma_pin_state_set(const struct dpll_pin *pin, void *pin_priv,
if (ret)
goto unlock;
}
- if (sma->direction == DPLL_PIN_DIRECTION_INPUT) {
- enable = state == DPLL_PIN_STATE_SELECTABLE;
+ switch (state) {
+ case DPLL_PIN_STATE_SELECTABLE:
+ if (sma->direction == DPLL_PIN_DIRECTION_OUTPUT) {
+ enable = false;
+ ret = -EINVAL;
+ goto unlock;
+ }
+ enable = true;
+ break;
+ case DPLL_PIN_STATE_CONNECTED:
+ if (sma->direction == DPLL_PIN_DIRECTION_INPUT) {
+ enable = false;
+ ret = -EINVAL;
+ goto unlock;
+ }
+ enable = true;
+ break;
+ case DPLL_PIN_STATE_DISCONNECTED:
+ enable = false;
+ break;
+ default:
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ switch (sma->direction) {
+ case DPLL_PIN_DIRECTION_INPUT:
target = sma->input;
type = ICE_DPLL_PIN_TYPE_INPUT;
- } else {
- enable = state == DPLL_PIN_STATE_CONNECTED;
+ break;
+ case DPLL_PIN_DIRECTION_OUTPUT:
target = sma->output;
type = ICE_DPLL_PIN_TYPE_OUTPUT;
+ break;
+ default:
+ ret = -EINVAL;
+ goto unlock;
}
if (enable)
@@ -4631,7 +4666,8 @@ static int ice_dpll_init_info_sw_pins(struct ice_pf *pf)
pin->prop.capabilities = caps;
pin->pf = pf;
pin->prop.board_label = ice_dpll_sw_pin_ufl[i];
- if (i == ICE_DPLL_PIN_SW_1_IDX) {
+ switch (i) {
+ case ICE_DPLL_PIN_SW_1_IDX:
pin->direction = DPLL_PIN_DIRECTION_OUTPUT;
pin_abs_idx = ICE_DPLL_PIN_SW_OUTPUT_ABS(i);
pin->prop.freq_supported =
@@ -4641,7 +4677,8 @@ static int ice_dpll_init_info_sw_pins(struct ice_pf *pf)
pin->prop.freq_supported_num = freq_supp_num;
pin->input = NULL;
pin->output = &d->outputs[pin_abs_idx];
- } else if (i == ICE_DPLL_PIN_SW_2_IDX) {
+ break;
+ case ICE_DPLL_PIN_SW_2_IDX:
pin->direction = DPLL_PIN_DIRECTION_INPUT;
pin_abs_idx = ICE_DPLL_PIN_SW_INPUT_ABS(i) +
input_idx_offset;
@@ -4654,6 +4691,10 @@ static int ice_dpll_init_info_sw_pins(struct ice_pf *pf)
pin->prop.capabilities =
(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |
caps);
+ break;
+ default:
+ dev_err(ice_pf_to_dev(pf), "Invalid U.FL pin index: %d\n", i);
+ return -EINVAL;
}
pin->muxed = &d->sma[i];
ice_dpll_phase_range_set(&pin->prop.phase_range, phase_adj_max);
--
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