Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net] nfc: microread: validate CARD_FOUND event length before parsing targets
From: David Heidelberg @ 2026-07-19 14:15 UTC (permalink / raw)
  To: Doruk Tan Ozturk; +Cc: oe-linux-nfc, netdev, linux-kernel, stable, Pengpeng Hou
In-Reply-To: <20260713215936.23137-1-doruk@0sec.ai>

On 13/07/2026 23:59, Doruk Tan Ozturk wrote:
> microread_target_discovered() parses a device-supplied MREAD_CARD_FOUND
> event into a struct nfc_target, reading fixed offsets and -- for the
> ISO-A and ISO-A-3 gates -- a variable-length NFCID1 straight out of the
> event skb. The only length check is nfcid1_len vs sizeof(targets->nfcid1);
> skb->len itself is never validated, so a short event makes every gate
> case read out of bounds past the skb:
> 
>    - ISO-A / ISO-A-3: fixed ATQA/SAK/LEN reads plus a memcpy of an
>      attacker-controlled nfcid1_len bytes from the NFCID1 offset;
>    - ISO-B / NFC-T1 / NFC-T3: a fixed 4- or 8-byte NFCID1 memcpy from a
>      fixed offset.
> 
> The copied nfcid1 is exported to user space via nfc_targets_found(), so
> the over-read is an information leak (and a possible oops on an unmapped
> page).
> 
> Reject events too short for the fields each gate case reads.
> 
> Found by 0sec (https://0sec.ai).
> 
> Fixes: cfad1ba87150 ("NFC: Initial support for Inside Secure microread")
> Cc: stable@vger.kernel.org
> Assisted-by: 0sec
> Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
> ---
>   drivers/nfc/microread/microread.c | 31 +++++++++++++++++++++++++++++--
>   1 file changed, 29 insertions(+), 2 deletions(-)
> 
Hello Doruk,

thanks for the patch, 1. 7. I got the same one from Pengpeng, which needs to 
address Fixes and Cc tag [1].

Feel free to sync together for the future effort to not get duplicated (and 
tokens not wasted ;-) )

Adding Pengpeng to Cc.

David

[1] https://lore.kernel.org/all/20260701053709.45176-1-pengpeng@iscas.ac.cn/

^ permalink raw reply

* Re: [PATCH net-next v2 2/2] nfc: s3fwrn5: support the S3NRN4V variant
From: Jorijn van der Graaf @ 2026-07-19 14:22 UTC (permalink / raw)
  To: David Heidelberg, Krzysztof Kozlowski
  Cc: Jorijn van der Graaf, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Rob Herring, Conor Dooley,
	oe-linux-nfc, netdev, devicetree, linux-kernel, Luca Weiss
In-Reply-To: <18c3e13f-88e4-458e-9f57-7aceeb1ce1d1@ixit.cz>

Hello David,

Thank you for the review!

On 19/07/2026 15:15, David Heidelberg wrote:
> Please, send the "drop the of_match_ptr()/__maybe_unused annotations
> from it." type of change as part of the series, but as a separate
> commit before the new HW support introduction.

Will do in v3.

> Since you touch S3FWRN5_I2C_DRIVER_NAME, replace define
> S3FWRN5_I2C_DRIVER_NAME occurenced with the "s3fwrn5_i2c" directly
> before introducing the support (also separate commit)

Will do, also in v3.

> is S3NRN4V really a variant of S3FWRN5 or is it just S3NRN4V?

It is a separate, later part, but from the same Samsung S.LSI NFC
controller line this driver covers. Samsung's downstream stack drives
that whole line with one kernel driver and one HAL: the HAL's product
table lists the N5 (S3FWRN5) and N82 (S3FWRN82) generations next to
RN4V (S3NRN4V) and others, dispatching on a product code reported by
the chip's bootloader, and the parts share the I2C framing, the
power-control GPIO scheme and the proprietary-NCI style of
configuration. The generational differences (bootloader protocol,
RF-register transport command, FW_CFG payload form) are exactly what
this patch dispatches on -- the same way the driver already supports
the S3FWRN82 next to the S3FWRN5.

That said, "S3FWRN5-family" can indeed be read as "a variant of the
S3FWRN5 chip", which it is not, so I'll reword it in v3 to something
like "a later part of the same Samsung NFC controller line". The
phrase also sits in the commit message of the already-acked binding
patch; I'll tweak it there too (commit message only) and note it in
the changelog.

> While it's "register update" and function is named "configure_dual",
> it's loading firmware.
>
> If it's not a firmware, but only configuration, it can reside inside
> the driver, maybe LLM even be able to decode to understandable
> sequence of registers and values.

There are two separate things here: the chip's executable firmware
(~180 KiB) ships in its flash and is not touched by this patch at all
-- its download protocol is not implemented, which is why the
download step is skipped. What is loaded here are only the two RF
register tables (~3.5 KiB combined).

Those tables are configuration by nature, but I don't think they can
reside in the driver:

- They are board-specific analog/RF tuning, not chip constants: the
  values match a particular antenna/matching-network design, and the
  vendor revises them across software releases (my two Fairphone 6
  units shipped different builds of these files, with different
  version stamps embedded). A different S3NRN4V board design would be
  expected to ship its own tables. Per-device data loaded at runtime
  is what request_firmware() is there for, much like Wi-Fi
  board/calibration files. The tables ship in the device's vendor
  image, which is where I extracted them from.

- There is nothing to decode them against. The register map of these
  controllers is not publicly documented, and even Samsung's own
  (Apache-licensed) HAL treats the register content as opaque: the
  only part of the image it interprets is a 16-byte metadata trailer
  at its end (version stamps, used to decide whether an update is
  needed at all, plus a region code), while the register content
  itself is pushed to the chip untouched, in 252-byte sections.
  Nothing in the stream or in the vendor stack identifies
  address/value pairs one could transcribe, so "decoded" into the
  driver this could only become a 3.5 KiB hex array in C, and we
  would lose the ability to ship a newer table without rebuilding
  the kernel.

- It also mirrors what this driver already does for the parts it
  supports: s3fwrn5_nci_rf_configure() loads the same class of table
  (sec_s3fwrn5_rfreg.bin) with request_firmware() and pushes it via
  the older START/SET/STOP_RFREG commands. The new function is the
  same operation over the newer parts' transport command.

If the naming reads confusingly I'm happy to rename the function or
extend its comment to spell out the firmware-vs-register-table
distinction.

> For next revision of the patch, I'll likely still have some
> additional feedback.

Understood -- I'll send the v3 with all of the above shortly.

> With next revision send also as last patch the device-tree entry for
> the Fairphone 6, so we can also get additional testing from
> developers/users.

Will do -- v3 will carry the Fairphone 6 DT patch at the end of the
series, marked as included for testing and presumably to be picked up
via the Qualcomm DT tree once the driver side is settled; I'll Cc
linux-arm-msm and the qcom maintainers on that patch.

Thanks again,
Jorijn

^ permalink raw reply

* Re: [BUG] nfc: llcp: race between nfc_llcp_send_ui_frame() and llcp_sock_bind() dereferences NULL sock->dev
From: David Heidelberg @ 2026-07-19 14:24 UTC (permalink / raw)
  To: Junwoong Doh
  Cc: krzk, davem, edumazet, kuba, pabeni, horms, oe-linux-nfc, netdev,
	linux-kernel
In-Reply-To: <a89d0419-8bcf-40a2-b52d-3e5d911f11da@gmail.com>

On 14/07/2026 02:00, Junwoong Doh wrote:
> Hello,
> 
> Commit dded08927ca3 ("nfc: llcp: fix NULL error pointer dereference on
> sendmsg() after failed bind()") added a NULL check for llcp_sock->local
> in llcp_sock_sendmsg(), but it does not handle all the races.
> The thread interleaving is the same as Krzysztof mentioned:
> https://lore.kernel.org/oe-linux-nfc/20220119074816.6505-2-krzysztof.kozlowski@canonical.com/
> 
> In detail:
> nfc_llcp_send_ui_frame() checks sock->local == NULL, but it is called
> without socket's lock held, which opens a window for a race condition.
> Between the sock->local == NULL check and the sock->dev use in
> nfc_alloc_send_skb(), llcp_sock_bind() can run concurrently and set
> both sock->local and sock->dev to NULL.
> This leads to NULL pointer dereference in the nfc_alloc_send_skb() call.
> Moreover, the window can be enlarged by the
> memcpy_from_msg(msg_data, msg, len) call that sits between
> the sock->local check and the sock->dev use.

Hello Junwoong,

thank you for the report. Would you be willing to try preparing a patch against 
the NFC for-next or for-linus tree to fix the issue?

Thank you
David

[...]

^ permalink raw reply

* Re: [PATCH net-next v2 2/2] nfc: s3fwrn5: support the S3NRN4V variant
From: David Heidelberg @ 2026-07-19 14:56 UTC (permalink / raw)
  To: Jorijn van der Graaf, Luca Weiss, Krzysztof Kozlowski
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Conor Dooley, oe-linux-nfc, netdev,
	devicetree, linux-kernel
In-Reply-To: <20260719142241.12640-1-jorijnvdgraaf@catcrafts.net>

On 19/07/2026 16:22, Jorijn van der Graaf wrote:
> Hello David,
> 
> Thank you for the review!
> 
> On 19/07/2026 15:15, David Heidelberg wrote:
>> Please, send the "drop the of_match_ptr()/__maybe_unused annotations
>> from it." type of change as part of the series, but as a separate
>> commit before the new HW support introduction.
> 
> Will do in v3.
> 
>> Since you touch S3FWRN5_I2C_DRIVER_NAME, replace define
>> S3FWRN5_I2C_DRIVER_NAME occurenced with the "s3fwrn5_i2c" directly
>> before introducing the support (also separate commit)
> 
> Will do, also in v3.
> 
>> is S3NRN4V really a variant of S3FWRN5 or is it just S3NRN4V?
> 
> It is a separate, later part, but from the same Samsung S.LSI NFC
> controller line this driver covers. Samsung's downstream stack drives
> that whole line with one kernel driver and one HAL: the HAL's product
> table lists the N5 (S3FWRN5) and N82 (S3FWRN82) generations next to
> RN4V (S3NRN4V) and others, dispatching on a product code reported by
> the chip's bootloader, and the parts share the I2C framing, the
> power-control GPIO scheme and the proprietary-NCI style of
> configuration. The generational differences (bootloader protocol,
> RF-register transport command, FW_CFG payload form) are exactly what
> this patch dispatches on -- the same way the driver already supports
> the S3FWRN82 next to the S3FWRN5.
> 
> That said, "S3FWRN5-family" can indeed be read as "a variant of the
> S3FWRN5 chip", which it is not, so I'll reword it in v3 to something
> like "a later part of the same Samsung NFC controller line". The
> phrase also sits in the commit message of the already-acked binding
> patch; I'll tweak it there too (commit message only) and note it in
> the changelog.
> 
>> While it's "register update" and function is named "configure_dual",
>> it's loading firmware.
>>
>> If it's not a firmware, but only configuration, it can reside inside
>> the driver, maybe LLM even be able to decode to understandable
>> sequence of registers and values.
> 
> There are two separate things here: the chip's executable firmware
> (~180 KiB) ships in its flash and is not touched by this patch at all
> -- its download protocol is not implemented, which is why the
> download step is skipped. What is loaded here are only the two RF
> register tables (~3.5 KiB combined).
> 
> Those tables are configuration by nature, but I don't think they can
> reside in the driver:
> 
> - They are board-specific analog/RF tuning, not chip constants: the
>    values match a particular antenna/matching-network design, and the
>    vendor revises them across software releases (my two Fairphone 6
>    units shipped different builds of these files, with different
>    version stamps embedded). A different S3NRN4V board design would be
>    expected to ship its own tables. Per-device data loaded at runtime
>    is what request_firmware() is there for, much like Wi-Fi
>    board/calibration files. The tables ship in the device's vendor
>    image, which is where I extracted them from.
> 
> - There is nothing to decode them against. The register map of these
>    controllers is not publicly documented, and even Samsung's own
>    (Apache-licensed) HAL treats the register content as opaque: the
>    only part of the image it interprets is a 16-byte metadata trailer
>    at its end (version stamps, used to decide whether an update is
>    needed at all, plus a region code), while the register content
>    itself is pushed to the chip untouched, in 252-byte sections.
>    Nothing in the stream or in the vendor stack identifies
>    address/value pairs one could transcribe, so "decoded" into the
>    driver this could only become a 3.5 KiB hex array in C, and we
>    would lose the ability to ship a newer table without rebuilding
>    the kernel.
> 
> - It also mirrors what this driver already does for the parts it
>    supports: s3fwrn5_nci_rf_configure() loads the same class of table
>    (sec_s3fwrn5_rfreg.bin) with request_firmware() and pushes it via
>    the older START/SET/STOP_RFREG commands. The new function is the
>    same operation over the newer parts' transport command.
> 
> If the naming reads confusingly I'm happy to rename the function or
> extend its comment to spell out the firmware-vs-register-table
> distinction.

Thanks,

now it makes more sense to me, feel free to name it as calibration data.

I would suggest to introduce something as a calibration-variant (see ath10k code).

If I understand right, firmware location path could look like

default path + driver vendor and model + device vendor and model + revision

/lib/firmware/ + Samsung/s3nrn4v/ + Fairphone/FP5/hwrevision.bin

/cc Luca here, as he may know more about the different configuration data shipped.

We should assume the configuration will be shipped with linux-firmware at some 
point.

David

> 
>> For next revision of the patch, I'll likely still have some
>> additional feedback.
> 
> Understood -- I'll send the v3 with all of the above shortly.
> 
>> With next revision send also as last patch the device-tree entry for
>> the Fairphone 6, so we can also get additional testing from
>> developers/users.
> 
> Will do -- v3 will carry the Fairphone 6 DT patch at the end of the
> series, marked as included for testing and presumably to be picked up
> via the Qualcomm DT tree once the driver side is settled; I'll Cc
> linux-arm-msm and the qcom maintainers on that patch.
> 
> Thanks again,
> Jorijn

-- 
David Heidelberg


^ permalink raw reply

* Re: [PATCH 6.12] vsock/virtio: fix zerocopy completion for multi-skb sends
From: Sasha Levin @ 2026-07-19 15:00 UTC (permalink / raw)
  To: stable, Greg Kroah-Hartman
  Cc: Sasha Levin, Alexander Martyniuk, lvc-project, Michael S. Tsirkin,
	Jason Wang, Xuan Zhuo, Eugenio Pérez, Stefan Hajnoczi,
	Stefano Garzarella, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Arseniy Krasnov, virtualization, kvm,
	netdev, linux-kernel, Maher Azzouzi
In-Reply-To: <20260716163600.115458-1-alexevgmart@gmail.com>

> When a large message is fragmented into multiple skbs, the zerocopy
> uarg is only allocated and attached to the last skb in the loop.
> Non-final skbs carry pinned user pages with no completion tracking,
> so the kernel has no way to notify userspace when those pages are safe
> to reuse.

Queued for 6.12, thanks.

-- 
Thanks,
Sasha

^ permalink raw reply

* [PATCH] net: pktgen: fix proc entry use-after-free
From: Chengfeng Ye @ 2026-07-19 14:57 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Thorsten Blum, Andrew Morton, Andy Shevchenko,
	Randy Dunlap, Chengfeng Ye, Robert Olsson, Stephen Hemminger
  Cc: netdev, linux-kernel, stable

pktgen_change_name() replaces pkt_dev->entry while holding t->if_lock.
pktgen_remove_device() removes the same entry before
_rem_dev_from_if_list() takes that lock.

This allows the following interleaving:

  CPU 0 (NETDEV_CHANGENAME)       CPU 1 (kpktgend)
  if_lock(t)
  proc_remove(pkt_dev->entry)
                                  proc_remove(pkt_dev->entry)
  pkt_dev->entry = proc_create_data(...)
  if_unlock(t)

The kthread can pass the stale proc_dir_entry to proc_remove() after the
rename path has freed it. A reproducer with a widened race window reports:

  BUG: KASAN: slab-use-after-free in proc_remove+0x78/0x80
  Read of size 8 at addr ffff8881478fea70 by task kpktgend_0/67
  Call Trace:
   proc_remove+0x78/0x80
   pktgen_remove_device.isra.0+0x11c/0x4c0
   pktgen_thread_worker+0x1214/0x6bc0
   kthread+0x2c6/0x3b0
  Allocated by task 95:
   __proc_create+0x204/0x790
   proc_create_data+0x72/0xe0
   pktgen_thread_write+0xd61/0x1510
  Freed by task 28:
   kmem_cache_free+0xcb/0x3d0
   proc_free_inode+0x5b/0x80
   rcu_core+0x50a/0x1850
  The buggy address belongs to the object at ffff8881478fea00
   which belongs to the cache proc_dir_entry of size 192

Move proc_remove() into the if_lock-protected list removal helper. Keep it
before list_del_rcu() to preserve the ordering required by add_device().
The rename path must then finish replacing the entry before removal, or
it observes that the device is no longer on the list.

Fixes: 39df232f1a9b ("[PKTGEN]: fix device name handling")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
---
 net/core/pktgen.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 8e185b318288..ee64f3012321 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3972,6 +3972,7 @@ static void _rem_dev_from_if_list(struct pktgen_thread *t,
 	struct pktgen_dev *p;
 
 	if_lock(t);
+	proc_remove(pkt_dev->entry);
 	list_for_each_safe(q, n, &t->if_list) {
 		p = list_entry(q, struct pktgen_dev, list);
 		if (p == pkt_dev)
@@ -4001,9 +4002,6 @@ static int pktgen_remove_device(struct pktgen_thread *t,
 	 * list to determine if interface already exist, avoid race
 	 * with proc_create_data()
 	 */
-	proc_remove(pkt_dev->entry);
-
-	/* And update the thread if_list */
 	_rem_dev_from_if_list(t, pkt_dev);
 
 #ifdef CONFIG_XFRM
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH net v5 0/3] nfc: fix remaining OOB bugs in NCI/LLCP parsing
From: David Heidelberg @ 2026-07-19 15:04 UTC (permalink / raw)
  To: Lekë Hapçiu, David Heidelberg
  Cc: davem, edumazet, kuba, pabeni, krzk, horms, linux-kernel, netdev,
	oe-linux-nfc
In-Reply-To: <20260716203507.7328-1-snowwlake@icloud.com>

On 16/07/2026 22:35, Lekë Hapçiu wrote:
> Rebased against David's linux-nfc for-linus tree [1], as requested.
> 
> This was originally a 5-patch series. Two of the five (the
> parse_gb_tlv()/parse_connection_tlv() offset-wrap fix and the
> nfc_llcp_recv_snl() TLV bounds fix) have since been fixed independently
> by other contributors already merged into for-linus:
> 
>    d8bd2dedbde5 ("nfc: llcp: fix OOB read and u8 offset wrap in TLV parsers")
>    27256cdb290e ("nfc: llcp: bound SNL TLV parsing to the skb and add length checks")
> 
> Those two are dropped from this series to avoid duplicating work. The
> remaining three patches are unchanged in substance from v4, just
> rebased and renumbered:
> 
>    1/3 (was 1/5) - nci_store_general_bytes_nfc_dep() u8 underflow
>    2/3 (was 4/5) - nfc_llcp_recv_dm() OOB read of the reason byte
>    3/3 (was 5/5) - nfc_llcp_connect_sn() TLV parsing OOB
> 
> All three still reproduce against current for-linus (verified against
> 1671b8fb7300 before rebase). checkpatch --strict is clean on all three.
> 
> [1] https://codeberg.org/linux-nfc/linux.git for-linus
> 
> Lekë Hapçiu (3):
>    nfc: nci: fix u8 underflow in nci_store_general_bytes_nfc_dep
>    nfc: llcp: fix OOB read of DM reason byte in nfc_llcp_recv_dm
>    nfc: llcp: fix TLV parsing OOB in nfc_llcp_connect_sn
> 
>   net/nfc/llcp_core.c | 19 +++++++++++++++++--
>   net/nfc/nci/ntf.c   |  6 ++++++
>   2 files changed, 23 insertions(+), 2 deletions(-)
> 

Hello Lekë,

I'm afraid I won't make you happy here, but after merging the outstanding 
backlog today, I ran into conflicts again with your patch series. I'm very sorry 
about that, but I've been receiving a high number of fixes.

Now that I'm back from the conference, if you send the next revision based on 
the current for-linus / for-next, I believe I'll be able to apply it quickly 
enough to avoid conflicts.

Thank you for your understanding.

David

^ permalink raw reply

* [PATCH] bpf, sockmap: Fix sk_redir use-after-free in send verdict
From: Chengfeng Ye @ 2026-07-19 15:22 UTC (permalink / raw)
  To: Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima, John Fastabend,
	Jakub Sitnicki, Jiayuan Chen, David S. Miller, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Daniel Borkmann, Alexei Starovoitov,
	open list:BPF [L7 FRAMEWORK] (sockmap)
  Cc: netdev, linux-kernel, Chengfeng Ye, stable

sk_psock_msg_verdict() takes a socket reference for psock->sk_redir.
tcp_bpf_send_verdict() copies that pointer while holding the source socket
lock, but does not take a reference for the local copy before dropping the
lock around tcp_bpf_sendmsg_redir().

When apply_bytes keeps the cached verdict active, another sendmsg() on the
same source socket can consume the remaining bytes and release the cached
reference while the first thread still holds only the raw local pointer:

  CPU 0                                  CPU 1
  sk_redir = psock->sk_redir
  apply_bytes remains nonzero
  release_sock(sk)
                                         lock_sock(sk)
                                         apply_bytes reaches zero
                                         psock->sk_redir = NULL
                                         release_sock(sk)
                                         tcp_bpf_sendmsg_redir(sk_redir)
                                         sock_put(sk_redir)
  tcp_bpf_sendmsg_redir(sk_redir)

The final sock_put() can free sk_redir before CPU 0 dereferences it.

KASAN reported:

  BUG: KASAN: slab-use-after-free in tcp_bpf_sendmsg_redir+0xf39/0x1020
  Read of size 8 at addr ffff888108537090 by task poc/87
  Call Trace:
   tcp_bpf_sendmsg_redir+0xf39/0x1020
   tcp_bpf_sendmsg+0x977/0x1a50
   __sys_sendto+0x32c/0x3a0
   __x64_sys_sendto+0xdb/0x1b0
  Allocated by task 85:
   sk_prot_alloc+0x56/0x210
   sk_clone+0x6f/0x14b0
   inet_csk_clone_lock+0x24/0x740
   tcp_create_openreq_child+0x25/0x2710
   tcp_v4_syn_recv_sock+0x10a/0xe00
  Freed by task 0:
   __kasan_slab_free+0x43/0x70
   slab_free_after_rcu_debug+0xa6/0x1e0
   rcu_core+0x50a/0x1850
  Last potentially related work creation:
   __sk_destruct+0x3da/0x540
   sk_psock_destroy+0x81e/0xab0
   process_one_work+0x63a/0x1070

Take a temporary socket reference while the source socket lock still
protects psock->sk_redir, and drop it after tcp_bpf_sendmsg_redir()
returns.  This keeps each unlocked use independent of cached-verdict
ownership.

Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
---
 net/ipv4/tcp_bpf.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index 8e905b50dead..69cc8bc33bcd 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -469,6 +469,7 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock,
 	case __SK_REDIRECT:
 		redir_ingress = psock->redir_ingress;
 		sk_redir = psock->sk_redir;
+		sock_hold(sk_redir);
 		sk_msg_apply_bytes(psock, tosend);
 		if (!psock->apply_bytes) {
 			/* Clean up before releasing the sock lock. */
@@ -489,6 +490,7 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock,
 
 		if (eval == __SK_REDIRECT)
 			sock_put(sk_redir);
+		sock_put(sk_redir);
 
 		lock_sock(sk);
 		sk_mem_uncharge(sk, sent);
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH net v2] nfc: nci: fix use of uninitialized memory in NFC-DEP general bytes
From: David Heidelberg @ 2026-07-19 15:27 UTC (permalink / raw)
  To: Muhammad Bilal
  Cc: netdev, davem, edumazet, kuba, pabeni, horms, oe-linux-nfc,
	linux-kernel, stable
In-Reply-To: <20260628214929.135152-1-meatuni001@gmail.com>

On 28/06/2026 23:49, Muhammad Bilal wrote:
> nci_store_general_bytes_nfc_dep() derives the length of the NFC-DEP
> general bytes by subtracting the fixed general-bytes offset from the ATR
> length:
> 
>    atr_res_len - NFC_ATR_RES_GT_OFFSET   (poll, offset 15)
>    atr_req_len - NFC_ATR_REQ_GT_OFFSET   (listen, offset 14)
> 
> It never checks that the ATR is at least that long.  When a
> RF_INTF_ACTIVATED_NTF reports an ATR shorter than the offset the
> subtraction is negative; because min_t() casts its arguments to __u8 the
> negative value becomes large and is then capped at
> NFC_ATR_RES_GB_MAXSIZE / NFC_ATR_REQ_GB_MAXSIZE.  remote_gb_len is thus
> set to up to 47/48 even though only atr_res_len/atr_req_len bytes of the
> on-stack atr_res/atr_req buffer were copied from the packet, and the
> following memcpy() reads the uninitialized remainder into
> ndev->remote_gb.
> 
> Zero remote_gb_len and skip storing the general bytes when the ATR is
> shorter than the general-bytes offset, so that a stale remote_gb_len
> from a previous activation does not survive into the new session.
> 
> Fixes: a99903ec4566 ("NFC: NCI: Handle Target mode activation")
> Cc: stable@vger.kernel.org
> Signed-off-by: Muhammad Bilal <meatuni001@gmail.com>
> ---
>   net/nfc/nci/ntf.c | 8 ++++++--
>   1 file changed, 6 insertions(+), 2 deletions(-)
> 
Hello Muhammad,

could you please rebase the patch on the currect version for-linus or for-next?

Thank you
David

^ permalink raw reply

* Re: [PATCH v3 net 4/6] xsk: reclaim invalid multi-buffer Tx descs in ZC path
From: Jason Xing @ 2026-07-19 15:30 UTC (permalink / raw)
  To: Maciej Fijalkowski
  Cc: netdev, bpf, magnus.karlsson, stfomichev, kuba, pabeni, horms,
	bjorn
In-Reply-To: <alzPbtHWgy97oeBv@boxer>

On Sun, Jul 19, 2026 at 9:22 PM Maciej Fijalkowski
<maciej.fijalkowski@intel.com> wrote:
>
> On Thu, Jul 16, 2026 at 11:58:24PM +0200, Jason Xing wrote:
> > On Tue, Jul 14, 2026 at 4:08 PM Maciej Fijalkowski
> > <maciej.fijalkowski@intel.com> wrote:
> > >
> > > The zero-copy Tx batch parser stops when it encounters an invalid
> > > descriptor. If this happens after one or more continuation descriptors,
> > > the Tx consumer can be advanced past fragments that are neither submitted
> > > to the driver nor returned to userspace through the completion ring.
> > >
> > > A similar problem occurs when a packet exceeds xdp_zc_max_segs. The
> > > descriptors consumed up to the limit are released without completion, and
> > > the remaining continuation descriptors can subsequently be interpreted
> > > as the beginning of another packet.
> > >
> > > Parse Tx batches in packet units and distinguish descriptors belonging to
> > > complete valid packets from descriptors consumed while draining an
> > > invalid or oversized packet. Return the former to the driver and append
> > > the latter to the CQ address area so userspace can reclaim their UMEM
> > > frames.
> > >
> > > Once draining starts, continue until the packet's end-of-packet
> > > descriptor is consumed. Preserve the drain state on the socket when EOP
> > > has not yet been supplied, so draining can continue during a later call.
> > > Leave incomplete but otherwise valid packets on the Tx ring. Keep the
> > > existing handling of standalone invalid descriptors unchanged.
> > >
> > > Shared-UMEM pools using multi-buffer Tx also need packet-framed parsing.
> > > Walk their Tx sockets one packet at a time, preserving the existing
> > > per-socket fairness scheme, instead of using the legacy one-descriptor
> > > fallback. Keep that fallback for shared pools that do not use
> > > multi-buffer Tx. Since the drain state is maintained per socket and both
> > > the singular and shared paths can resume an interrupted drain, changing
> > > the socket list from singular to shared requires no special bind-time
> > > transition.
> > >
> > > CQ entries are positional, and drivers may complete only part of the Tx
> > > work returned by xsk_tx_peek_release_desc_batch(). Therefore, reclaim-only
> > > entries cannot be published immediately when earlier driver-visible
> > > descriptors are still outstanding.
> > >
> > > Track the number of driver-visible CQ entries preceding the reclaim
> > > entries. Let xsk_tx_completed() publish partial real Tx completions, and
> > > publish the reclaim entries only after every earlier Tx descriptor has
> > > completed. Complete a reclaim-only batch immediately when there is no
> > > driver-visible work in front of it, and prevent another Tx batch from
> > > being appended while reclaim entries remain pending.
> > >
> > > Also cap batch processing by the size of the pool's temporary descriptor
> > > array, as Tx rings belonging to sockets sharing a UMEM may have different
> > > sizes.
> > >
> > > This ensures that every descriptor consumed as part of an invalid
> > > multi-buffer packet is eventually returned to userspace without exposing
> > > the dropped packet to the driver or violating CQ completion ordering.
> > >
> > > Fixes: cf24f5a5feea ("xsk: add support for AF_XDP multi-buffer on Tx path")
> > > Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
> >
> > Thanks for working on this big patch! It's not easy to fix it in a
> > simpler way, I think. And I didn't observe any obvious performance
> > impact by xdpsock.
> >
> > Overall, it looks good to me except for a few minor points:
> > Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
> >
> > > ---
> > >  include/net/xsk_buff_pool.h |   3 +
> > >  net/xdp/xsk.c               | 192 ++++++++++++++++++++++++++++++++----
> > >  net/xdp/xsk_buff_pool.c     |   1 +
> > >  net/xdp/xsk_queue.h         |  76 ++++++++++----
> > >  4 files changed, 232 insertions(+), 40 deletions(-)
> > >
> > > diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h
> > > index f5e737a83055..2bb1d122b1bc 100644
> > > --- a/include/net/xsk_buff_pool.h
> > > +++ b/include/net/xsk_buff_pool.h
> > > @@ -78,6 +78,9 @@ struct xsk_buff_pool {
> > >         u32 chunk_size;
> > >         u32 chunk_shift;
> > >         u32 frame_len;
> > > +       u32 tx_descs_nentries;
> > > +       u32 reclaim_descs;
> > > +       u32 tx_zc_pending_descs;
> > >         u32 xdp_zc_max_segs;
> > >         u8 tx_metadata_len; /* inherited from umem */
> > >         u8 cached_need_wakeup;
> > > diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
> > > index 385a3f4a1b32..2909a0ec6837 100644
> > > --- a/net/xdp/xsk.c
> > > +++ b/net/xdp/xsk.c
> > > @@ -499,6 +499,23 @@ void __xsk_map_flush(struct list_head *flush_list)
> > >
> > >  void xsk_tx_completed(struct xsk_buff_pool *pool, u32 nb_entries)
> > >  {
> > > +       u32 reclaim_descs = READ_ONCE(pool->reclaim_descs);
> > > +
> > > +       if (unlikely(reclaim_descs)) {
> >
> > Just a side note: it might impact the performance because new descs
> > need to wait for the existing descs to be completed if there are
> > reclaim descs.
>
> That is a tradeoff for dealing with this corner case i'd say.
>
> >
> > > +               u32 pending_descs = READ_ONCE(pool->tx_zc_pending_descs);
> > > +
> > > +               if (nb_entries < pending_descs) {
> > > +                       WRITE_ONCE(pool->tx_zc_pending_descs,
> > > +                                  pending_descs - nb_entries);
> > > +                       xskq_prod_submit_n(pool->cq, nb_entries);
> > > +                       return;
> > > +               }
> > > +
> > > +               WRITE_ONCE(pool->tx_zc_pending_descs, 0);
> > > +               nb_entries += reclaim_descs;
> > > +               WRITE_ONCE(pool->reclaim_descs, 0);
> > > +       }
> > > +
> > >         xskq_prod_submit_n(pool->cq, nb_entries);
> > >  }
> > >  EXPORT_SYMBOL(xsk_tx_completed);
> > > @@ -574,24 +591,162 @@ static u32 xsk_tx_peek_release_fallback(struct xsk_buff_pool *pool, u32 max_entr
> > >         return nb_pkts;
> > >  }
> > >
> > > +static void xsk_tx_commit_batch(struct xsk_buff_pool *pool,
> > > +                               struct xsk_tx_batch *batch)
> > > +{
> > > +       u32 nb_descs = xsk_tx_batch_cq_descs(batch);
> > > +       u32 cq_cached_prod;
> > > +
> > > +       if (!nb_descs)
> > > +               return;
> > > +
> > > +       cq_cached_prod = pool->cq->cached_prod;
> > > +       xskq_prod_write_addr_batch(pool->cq, pool->tx_descs, nb_descs);
> > > +
> > > +       if (unlikely(batch->reclaim_descs)) {
> > > +               u32 cq_pending_descs;
> > > +
> > > +               /* CQ is positional. Descriptors already written but not
> > > +                * submitted must complete before any reclaim-only descriptors
> > > +                * appended below.
> > > +                */
> > > +               cq_pending_descs = cq_cached_prod - xskq_get_prod(pool->cq);
> > > +
> > > +               WRITE_ONCE(pool->tx_zc_pending_descs,
> > > +                          batch->tx_descs + cq_pending_descs);
> > > +               WRITE_ONCE(pool->reclaim_descs, batch->reclaim_descs);
> > > +               if (unlikely(!pool->tx_zc_pending_descs))
> > > +                       xsk_tx_completed(pool, 0);
> > > +       }
> > > +}
> > > +
> > > +static struct xsk_tx_batch
> > > +__xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, struct xdp_sock *xs,
> > > +                                struct xdp_desc *descs, u32 max_descs)
> > > +{
> > > +       struct xsk_tx_batch batch = {};
> > > +       u32 entries;
> > > +
> > > +       entries = xskq_cons_nb_entries(xs->tx, max_descs);
> > > +       if (!entries)
> > > +               return batch;
> > > +
> > > +       batch = xskq_cons_read_desc_batch(xs, pool, descs, max_descs);
> > > +       if (!xsk_tx_batch_cq_descs(&batch)) {
> > > +               xs->tx->queue_empty_descs++;
> > > +               if (batch.consumed_descs) {
> > > +                       __xskq_cons_release(xs->tx);
> > > +                       xs->sk.sk_write_space(&xs->sk);
> > > +               }
> > > +               return batch;
> > > +       }
> > > +
> > > +       __xskq_cons_release(xs->tx);
> > > +       xs->sk.sk_write_space(&xs->sk);
> > > +       return batch;
> > > +}
> > > +
> > > +static struct xsk_tx_batch
> > > +xsk_tx_peek_release_shared_desc_batch(struct xsk_buff_pool *pool, u32 max_descs)
> > > +{
> > > +       u32 cq_descs_before, cq_descs_after;
> > > +       struct xsk_tx_batch sum_batch = {};
> > > +       bool budget_exhausted;
> > > +       u32 per_socket_budget;
> > > +       struct xdp_sock *xs;
> > > +
> > > +       /* The fairness quota must allow one maximum-sized valid packet. */
> > > +       per_socket_budget = max_t(u32, MAX_PER_SOCKET_BUDGET,
> > > +                                 pool->xdp_zc_max_segs);
> > > +
> > > +again:
> > > +       budget_exhausted = false;
> > > +       cq_descs_before = xsk_tx_batch_cq_descs(&sum_batch);
> > > +       list_for_each_entry_rcu(xs, &pool->xsk_tx_list, tx_list) {
> > > +               u32 budget, budget_left, offset, remaining;
> > > +               struct xsk_tx_batch curr_batch;
> > > +
> > > +               /* Once reclaim-only descriptors have been appended to the CQ
> > > +                * address area, do not append driver-visible Tx descriptors
> > > +                * from another socket after them. xsk_tx_completed() relies on
> > > +                * all driver-visible descriptors preceding all reclaim-only
> > > +                * descriptors in CQ order.
> > > +                */
> > > +               if (sum_batch.reclaim_descs)
> > > +                       break;
> > > +
> > > +               /* be gentle when playing with pool->tx_descs */
> >
> > Minor nit: seems unneeded comment?
>
> this has been my helper/reminder that we need to respect already consumed
> space at tx_descs array; i can remove it
>
> >
> > > +               offset = xsk_tx_batch_cq_descs(&sum_batch);
> > > +               if (offset >= max_descs)
> > > +                       break;
> > > +
> > > +               if (xs->tx_budget_spent >= per_socket_budget) {
> > > +                       if (xskq_cons_nb_entries(xs->tx, 1))
> > > +                               budget_exhausted = true;
> > > +                       continue;
> > > +               }
> > > +
> > > +               budget_left = per_socket_budget - xs->tx_budget_spent;
> > > +               remaining = max_descs - offset;
> > > +               budget = min(remaining, budget_left);
> > > +
> > > +               curr_batch = __xsk_tx_peek_release_desc_batch(pool, xs,
> > > +                                                             pool->tx_descs + offset,
> > > +                                                             budget);
> > > +               if (!xsk_tx_batch_cq_descs(&curr_batch)) {
> > > +                       if (curr_batch.budget_limited && budget_left < remaining)
> > > +                               budget_exhausted = true;
> > > +                       xs->tx_budget_spent += curr_batch.consumed_descs;
> > > +                       continue;
> > > +               }
> > > +
> > > +               xs->tx_budget_spent += curr_batch.consumed_descs;
> > > +               sum_batch.tx_descs += curr_batch.tx_descs;
> >
> > No need to use '+' here because of the previous reclaim_descs check.
>
> hmm correct!
>
> >
> > > +               sum_batch.reclaim_descs += curr_batch.reclaim_descs;
> > > +       }
> > > +
> > > +       cq_descs_after = xsk_tx_batch_cq_descs(&sum_batch);
> > > +
> > > +       if (sum_batch.reclaim_descs || cq_descs_after >= max_descs)
> > > +               return sum_batch;
> > > +
> > > +       /* Continue filling the batch while this pass made progress */
> > > +       if (cq_descs_before != cq_descs_after)
> > > +               goto again;
> > > +
> > > +       if (!budget_exhausted)
> > > +               return sum_batch;
> > > +
> > > +       list_for_each_entry_rcu(xs, &pool->xsk_tx_list, tx_list)
> > > +               xs->tx_budget_spent = 0;
> > > +       goto again;
> > > +}
> > > +
> > >  u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 nb_pkts)
> > >  {
> > > +       struct xsk_tx_batch batch = {};
> > >         struct xdp_sock *xs;
> > > +       bool umem_shared;
> > >
> > >         rcu_read_lock();
> > > -       if (!list_is_singular(&pool->xsk_tx_list)) {
> > > -               /* Fallback to the non-batched version */
> > > -               rcu_read_unlock();
> > > -               return xsk_tx_peek_release_fallback(pool, nb_pkts);
> > > -       }
> > > +       if (unlikely(READ_ONCE(pool->reclaim_descs)))
> > > +               goto out;
> > >
> > > -       xs = list_first_or_null_rcu(&pool->xsk_tx_list, struct xdp_sock, tx_list);
> > > -       if (!xs) {
> > > -               nb_pkts = 0;
> > > +       xs = list_first_or_null_rcu(&pool->xsk_tx_list, struct xdp_sock,
> > > +                                   tx_list);
> > > +       if (!xs)
> > >                 goto out;
> > > -       }
> > >
> > > -       nb_pkts = xskq_cons_nb_entries(xs->tx, nb_pkts);
> > > +       nb_pkts = min(nb_pkts, pool->tx_descs_nentries);
> > > +       if (!nb_pkts)
> > > +               goto out;
> > > +
> > > +       umem_shared = !list_is_singular(&pool->xsk_tx_list);
> > > +
> > > +       if (umem_shared && !(pool->umem->flags & XDP_UMEM_SG_FLAG)) {
> > > +               rcu_read_unlock();
> > > +               return xsk_tx_peek_release_fallback(pool, nb_pkts);
> > > +       }
> > >
> > >         /* This is the backpressure mechanism for the Tx path. Try to
> > >          * reserve space in the completion queue for all packets, but
> > > @@ -603,19 +758,16 @@ u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 nb_pkts)
> > >         if (!nb_pkts)
> > >                 goto out;
> > >
> > > -       nb_pkts = xskq_cons_read_desc_batch(xs->tx, pool, nb_pkts);
> > > -       if (!nb_pkts) {
> > > -               xs->tx->queue_empty_descs++;
> > > -               goto out;
> > > -       }
> > > -
> > > -       __xskq_cons_release(xs->tx);
> > > -       xskq_prod_write_addr_batch(pool->cq, pool->tx_descs, nb_pkts);
> > > -       xs->sk.sk_write_space(&xs->sk);
> > > +       batch = umem_shared ?
> > > +               xsk_tx_peek_release_shared_desc_batch(pool, nb_pkts) :
> > > +               __xsk_tx_peek_release_desc_batch(pool, xs,
> > > +                                                pool->tx_descs,
> > > +                                                nb_pkts);
> > > +       xsk_tx_commit_batch(pool, &batch);
> > >
> > >  out:
> > >         rcu_read_unlock();
> > > -       return nb_pkts;
> > > +       return batch.tx_descs;
> > >  }
> > >  EXPORT_SYMBOL(xsk_tx_peek_release_desc_batch);
> > >
> > > diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
> > > index 12c9fb29af05..a4089480b22b 100644
> > > --- a/net/xdp/xsk_buff_pool.c
> > > +++ b/net/xdp/xsk_buff_pool.c
> > > @@ -51,6 +51,7 @@ int xp_alloc_tx_descs(struct xsk_buff_pool *pool, struct xdp_sock *xs,
> > >         if (!pool->tx_descs)
> > >                 return -ENOMEM;
> > >
> > > +       pool->tx_descs_nentries = nentries;
> > >         return 0;
> > >  }
> > >
> > > diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h
> > > index 3e3fbb73d23e..a15ff1929db6 100644
> > > --- a/net/xdp/xsk_queue.h
> > > +++ b/net/xdp/xsk_queue.h
> > > @@ -58,6 +58,18 @@ struct parsed_desc {
> > >         u32 valid;
> > >  };
> > >
> > > +struct xsk_tx_batch {
> > > +       u32 tx_descs;
> > > +       u32 reclaim_descs;
> > > +       u32 consumed_descs;
> > > +       bool budget_limited;
> > > +};
> > > +
> > > +static inline u32 xsk_tx_batch_cq_descs(const struct xsk_tx_batch *batch)
> > > +{
> > > +       return batch->tx_descs + batch->reclaim_descs;
> > > +}
> > > +
> > >  /* The structure of the shared state of the rings are a simple
> > >   * circular buffer, as outlined in
> > >   * Documentation/core-api/circular-buffers.rst. For the Rx and
> > > @@ -263,17 +275,18 @@ static inline void parse_desc(struct xsk_queue *q, struct xsk_buff_pool *pool,
> > >         parsed->mb = xp_mb_desc(desc);
> > >  }
> > >
> > > -static inline
> > > -u32 xskq_cons_read_desc_batch(struct xsk_queue *q, struct xsk_buff_pool *pool,
> > > -                             u32 max)
> > > +static inline struct xsk_tx_batch
> > > +xskq_cons_read_desc_batch(struct xdp_sock *xs, struct xsk_buff_pool *pool,
> > > +                         struct xdp_desc *descs, u32 max)
> > >  {
> > > -       u32 cached_cons = q->cached_cons, nb_entries = 0;
> > > -       struct xdp_desc *descs = pool->tx_descs;
> > > -       u32 total_descs = 0, nr_frags = 0;
> > > +       bool drain = READ_ONCE(xs->drain_cont);
> > > +       u32 cached_cons, nb_entries = 0, released;
> > > +       struct xsk_tx_batch batch = {};
> > > +       struct xsk_queue *q = xs->tx;
> > > +       u32 nr_frags = 0;
> > > +
> > > +       cached_cons = q->cached_cons;
> > >
> > > -       /* track first entry, if stumble upon *any* invalid descriptor, rewind
> > > -        * current packet that consists of frags and stop the processing
> > > -        */
> > >         while (cached_cons != q->cached_prod && nb_entries < max) {
> > >                 struct xdp_rxtx_ring *ring = (struct xdp_rxtx_ring *)q->ring;
> > >                 u32 idx = cached_cons & q->ring_mask;
> > > @@ -282,26 +295,49 @@ u32 xskq_cons_read_desc_batch(struct xsk_queue *q, struct xsk_buff_pool *pool,
> > >                 descs[nb_entries] = ring->desc[idx];
> > >                 cached_cons++;
> > >                 parse_desc(q, pool, &descs[nb_entries], &parsed);
> > > -               if (unlikely(!parsed.valid))
> > > -                       break;
> > > +               if (unlikely(!parsed.valid)) {
> > > +                       if (!drain && !nr_frags && !parsed.mb)
> >
> > I understand you're fixing the mb problem here. But I'm wondering if
> > it still has a problem in the non mb case because the single invalid
> > packet (mb ==0, nr_frags == 0, drain == 0) that isn't published in CQ
> > cannot be tracked by application?
> >
> > My thinking is to just remove the above line in this patch. Or I can
> > cook a follow-up patch to fix this specific problem?
>
> Good catch - seems I got too focused at mb case and now we have a bit of
> misbehave as invalid mb descs are cq produced and standalone not.
>
> I'm gonna address this and align standalone descs (in generic xmit as
> well) that are invalid so they are also cq published, not silently wiped
> out from tx ring only.
>
> Thanks! sending v4.

Great! Thanks!

^ permalink raw reply

* Re: [PATCH net-next] net: phy: motorcomm: enable the reference clock for YT8531
From: Andrew Lunn @ 2026-07-19 15:34 UTC (permalink / raw)
  To: Jiaxing Hu
  Cc: Frank.Sae, hkallweit1, linux, davem, edumazet, kuba, pabeni,
	netdev, linux-kernel, maxime.chevallier, heiko, linux-rockchip
In-Reply-To: <20260719034555.3623003-1-gahing@gahingwoo.com>

On Sun, Jul 19, 2026 at 03:45:55PM +1200, Jiaxing Hu wrote:
> The YT8531 needs a 25 MHz reference. On boards without a local crystal
> it is fed from the SoC, described as a clock on the PHY node. Get and
> enable it in probe so the PHY is clocked before its registers are
> accessed. The clock is optional, so crystal-clocked boards are
> unaffected.
> 
> Signed-off-by: Jiaxing Hu <gahing@gahingwoo.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply

* Re: unix_stream_connect and socket address resolution
From: John Ericson @ 2026-07-19 15:37 UTC (permalink / raw)
  To: David Laight
  Cc: Kuniyuki Iwashima, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Cong Wang, Simon Horman, Christian Brauner,
	David Rheinsberg, Andy Lutomirski, Sergei Zimmerman, network dev,
	Mickaël Salaün, Günther Noack, Paul Moore,
	linux-security-module, LKML
In-Reply-To: <20260718215855.07284fb1@pumpkin>

Hi David,

On Sat, Jul 18, 2026, at 4:58 PM, David Laight wrote:
> My $0.02

Thanks for weighing in here.

> If you assume that the client isn't responsible for restarting the server,
> then there is no strong timing relation between creating a new server
> (by any means) and the connect request from the client.
> In other words both the above are very similar to the client being
> preempted at the start of the connect() system call.
> 
> What you need to do is hard link foo to foo1, create the new
> socket at foo2/bar then mv foo2 to foo so that it is atomic.
> But I suspect hard links to directories aren't allowed any more :-(
> (Creating 'random' hard links to directories used to be 'fun',
> you could get 'find' in a right mess.)
> 
> David

I think I am a little confused by your answer. I am not trying to do
anything in particular in userland relating to dying and restarting
servers. Rather, I am wondering why it was decided (long ago, pre the
current repo's git history) for connect to re-resolve the path every
loop iteration.

I am working on a series of related af_unix refactors, and it would
simplify things a lot if I could make `unix_stream_connect` just resolve
the path once before the loop, but I do not know if that is an
acceptable change in behavior.

I was justifying the change in terms of the resolve-once behavior being
less surprising in my original email, since that reason stands on its
own, with or without my other planned work, but the truth is both that
and the ease of refactoring with that change are my motivations.

Hope that clarifies things,

John

^ permalink raw reply

* Re: [PATCH net] rds: tcp: unregister sysctl before tearing down listen socket
From: Cen Zhang (Microsoft) @ 2026-07-19 15:48 UTC (permalink / raw)
  To: achender
  Cc: AutonomousCodeSecurity, blbllhy, davem, edumazet, horms, kuba,
	kys, linux-kernel, linux-rdma, netdev, pabeni, rds-devel,
	tgopinath
In-Reply-To: <259284aa1280d387c413cc34fa5e4b11ad28379d.camel@kernel.org>

Thanks. The KASAN stack was observed on x86_64 QEMU/KASAN.

The full KASAN report and C reproducer are a few hundred lines. Would you
prefer that I include them after the --- line in v2, or reply to this
thread with them separately and keep v2 concise?

I'll prepare v2 after confirming the preferred format.

^ permalink raw reply

* Re: [PATCH net-next] net: sfp: add quirk for HORACO copper SFP+ module
From: Andrew Lunn @ 2026-07-19 15:49 UTC (permalink / raw)
  To: Aleksander Jan Bajkowski
  Cc: linux, hkallweit1, davem, edumazet, kuba, pabeni, netdev,
	linux-kernel
In-Reply-To: <20260719100158.874882-1-olek2@wp.pl>

On Sun, Jul 19, 2026 at 12:01:55PM +0200, Aleksander Jan Bajkowski wrote:
> Add quirk for a copper SFP+ module that identifies itself as "OEM"
> "HC-10GE-113C". It uses RollBall protocol to talk to the PHY.
> 
> Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply

* Re: [PATCH ethtool-next v3 1/3] sfpid: print all implemented options
From: Andrew Lunn @ 2026-07-19 15:54 UTC (permalink / raw)
  To: Aleksander Jan Bajkowski
  Cc: danieller, mkubecek, davem, edumazet, kuba, pabeni, jbe, netdev
In-Reply-To: <20260719090458.659332-1-olek2@wp.pl>

On Sun, Jul 19, 2026 at 11:00:35AM +0200, Aleksander Jan Bajkowski wrote:
> SFP modules implement multiple options. Before the “json” option was
> introduced, all options were listed.

Hi Aleksander

This is a common theme here, the json option. Are the three patches
for things you noticed for devices you have, or have you analysed
those json patches and think you have found all the places it broke?

Thanks
	Andrew

^ permalink raw reply

* Re: [PATCH net-next] net: stmmac: Simplify ioctl handling
From: Andrew Lunn @ 2026-07-19 16:13 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
	Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
	thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
	linux-arm-kernel, linux-stm32
In-Reply-To: <20260718143848.677531-1-maxime.chevallier@bootlin.com>

> Looking at this, I'm wondering if we can't just get rid of SIOCSHWTSTAMP
> handling in phy_mii_ioctl(). Looks like we can ?

I'm not sure about that. We need Richards input.

The code in phy_mii_ioctl() allows the MAC to be bypassed, it goes
straight to a PHY based stamper. It could be the MAC has no idea the
PHY has this capability, so it has not implemented the .ndo?

It might be we need to hoist the code from phy_mii_ioctl() into
dev_{sg}et_hwtstamp()?

	Andrew

^ permalink raw reply

* [PATCH] bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg()
From: Chengfeng Ye @ 2026-07-19 16:16 UTC (permalink / raw)
  To: Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima, John Fastabend,
	Jakub Sitnicki, Jiayuan Chen, David S. Miller, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	open list:BPF [L7 FRAMEWORK] (sockmap)
  Cc: netdev, linux-kernel, Chengfeng Ye, stable

tcp_bpf_sendmsg() keeps msg_tx across sk_stream_wait_memory(), which
drops and reacquires the socket lock.  Its error path tries to decide
whether msg_tx names the local temporary message by comparing it with
the current value of psock->cork.

This comparison is unsafe when two threads send on the same socket:

  Thread A                         Thread B
  msg_tx = psock->cork
  sk_msg_alloc() fails
  sk_stream_wait_memory()
    releases the socket lock      acquires the socket lock
                                  completes the cork
                                  psock->cork = NULL
                                  frees the cork
    reacquires the socket lock
  msg_tx != psock->cork
  sk_msg_free(msg_tx)

The stale cork is therefore mistaken for the local temporary message
and freed again.  KASAN reported:

  BUG: KASAN: slab-use-after-free in sk_msg_free+0x49/0x50
  Read of size 4 at addr ffff88810c908800 by task poc/90
  Call Trace:
   sk_msg_free+0x49/0x50
   tcp_bpf_sendmsg+0x14f5/0x1cc0
   __sys_sendto+0x32c/0x3a0
   __x64_sys_sendto+0xdb/0x1b0
  Allocated by task 89:
   __kasan_kmalloc+0x8f/0xa0
   tcp_bpf_sendmsg+0x16b3/0x1cc0
  Freed by task 91:
   __kasan_slab_free+0x43/0x70
   kfree+0x131/0x3c0
   tcp_bpf_sendmsg+0xec3/0x1cc0

msg_tx can only name the stack-local tmp or the shared cork.  Test for
tmp directly so a changed psock->cork cannot turn a shared message into
an apparent local one.

Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
---
 net/ipv4/tcp_bpf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index 8e905b50dead..a30475afb6f8 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -604,7 +604,7 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 wait_for_memory:
 		err = sk_stream_wait_memory(sk, &timeo);
 		if (err) {
-			if (msg_tx && msg_tx != psock->cork)
+			if (msg_tx == &tmp)
 				sk_msg_free(sk, msg_tx);
 			goto out_err;
 		}
-- 
2.43.0


^ permalink raw reply related

* Re: [RFC PATCH net-next v0.1 0/1] add GeoNetworking protocol
From: Andrew Lunn @ 2026-07-19 16:21 UTC (permalink / raw)
  To: Simon Dietz
  Cc: netdev, andrew+netdev, davem, edumazet, johannes, kuniyu,
	linux-wireless, dietz23838
In-Reply-To: <20260718210046.2357882-1-simon.dietz@plantwatch.de>

On Sat, Jul 18, 2026 at 11:00:32PM +0200, Simon Dietz wrote:
> Implement the GeoNetworking / ETSI ITS-G5 ('net/gn') protocol which
> is based on 802.11p wifi and used for vehicle2x applications. It is
> standardized by the ETSI and used by some car manufacturers
> (especially in europe). It enables ad-hoc, multi-hop geographical
> communication and routing among vehicles (and road- or railside
> infrastructure).
> 
> Most work of this implementation has been done by the bachelor
> project 2018/2019 of the operating systems and middleware group of
> the Hasso Plattner Institute, University of Potsdam, which the author
> was part of.

Hi Simon

Is there are architecture documentation somewhere?

One of my comments was about routing tables. Should there be a user
space component determining the routes, and the kernel just has a
static routing table? That would be typical for IP.

There also seems to be a need for location information. How does that
get into the kernel? Is there a daemon for that? Patches to gpsd?

    Andrew

^ permalink raw reply

* [PATCH net-next v4] selftests/net/openvswitch: add SCTP flow key test
From: Minxi Hou @ 2026-07-19 16:26 UTC (permalink / raw)
  To: netdev; +Cc: davem, edumazet, kuba, pabeni, aconole, Minxi Hou

Add test_sctp_connect_v4() to verify OVS can match on SCTP flow keys
(sctp src/dst port).

The test sets up client and server namespaces connected through an
OVS bridge, installs port-keyed flows, and verifies:
  - sctp(dst=4443) matches client-to-server INIT
  - sctp(src=4443) matches server-to-client INIT-ACK
  - removing flows drops the connection
  - reinstalling flows restores connectivity

Signed-off-by: Minxi Hou <houminxi@gmail.com>
---
 .../selftests/net/openvswitch/openvswitch.sh  | 105 ++++++++++++++++++
 .../selftests/net/openvswitch/ovs-dpctl.py    |   5 +
 2 files changed, 110 insertions(+)

v3 -> v4: rebase onto latest net-next (2026-07-19), resolve test list
  conflict from merged trunc test

diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh
index f75ee723415a..af9cf0888316 100755
--- a/tools/testing/selftests/net/openvswitch/openvswitch.sh
+++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh
@@ -33,6 +33,7 @@ tests="
 	flow_set				flow-set: Flow modify
 	action_set				set: SET action rewrites fields
 	trunc					trunc: output truncation
+	sctp_connect_v4				sctp: SCTP flow key matching
 	psample					psample: Sampling packets with psample"
 
 info() {
@@ -530,6 +531,110 @@ test_trunc() {
 	return 0
 }
 
+# sctp_connect_v4 test
+# - sctp(dst=4443) matches client-to-server INIT
+# - sctp(src=4443) matches server-to-client INIT-ACK
+# - remove flows and verify connection fails, reinstall and recover
+test_sctp_connect_v4() {
+	local t="test_sctp_connect_v4"
+
+	which nc >/dev/null 2>&1 || return $ksft_skip
+	nc --sctp -z 127.0.0.1 1 </dev/null 2>/dev/null || return $ksft_skip
+	modprobe -q sctp 2>/dev/null || return $ksft_skip
+
+	sbx_add "$t" || return $?
+	ovs_add_dp "$t" sctp4 || return 1
+
+	info "create namespaces"
+	for ns in client server; do
+		ovs_add_netns_and_veths "$t" "sctp4" "$ns" \
+		    "${ns:0:1}0" "${ns:0:1}1" || return 1
+	done
+
+	ip netns exec client ip addr add 172.31.110.10/24 dev c1
+	ip netns exec client ip link set c1 up
+	ip netns exec server ip addr add 172.31.110.20/24 dev s1
+	ip netns exec server ip link set s1 up
+
+	# ARP forwarding
+	ovs_add_flow "$t" sctp4 \
+	    'in_port(1),eth(),eth_type(0x0806),arp()' \
+	    '2' || return 1
+	ovs_add_flow "$t" sctp4 \
+	    'in_port(2),eth(),eth_type(0x0806),arp()' \
+	    '1' || return 1
+
+	# SCTP port matching: dst for request, src for reply
+	ovs_add_flow "$t" sctp4 \
+	    'in_port(1),eth(),eth_type(0x0800),ipv4(proto=132),sctp(dst=4443)' \
+	    '2' || return 1
+	ovs_add_flow "$t" sctp4 \
+	    'in_port(2),eth(),eth_type(0x0800),ipv4(proto=132),sctp(src=4443)' \
+	    '1' || return 1
+
+	echo "server" | \
+		ovs_netns_spawn_daemon "$t" "server" \
+				nc --sctp -l 172.31.110.20 -vn 4443
+	local server_pid=$pid
+	ovs_wait ip netns exec server \
+	    ss -lnH sport = :4443 \| grep -q . \
+	    || return 1
+
+	info "verify SCTP association with port-keyed flows"
+	ovs_sbx "$t" ip netns exec client \
+	    nc --sctp -i 1 -zv 172.31.110.20 4443 \
+	    || return 1
+
+	ovs_del_flows "$t" sctp4
+
+	info "verify connection fails without flows"
+	ovs_add_flow "$t" sctp4 \
+	    'in_port(1),eth(),eth_type(0x0806),arp()' \
+	    '2' || return 1
+	ovs_add_flow "$t" sctp4 \
+	    'in_port(2),eth(),eth_type(0x0806),arp()' \
+	    '1' || return 1
+
+	kill -TERM $server_pid 2>/dev/null
+	wait $server_pid 2>/dev/null
+	echo "server2" | \
+		ovs_netns_spawn_daemon "$t" "server" \
+				nc --sctp -l 172.31.110.20 -vn 4443
+	server_pid=$pid
+	ovs_wait ip netns exec server \
+	    ss -lnH sport = :4443 \| grep -q . \
+	    || return 1
+
+	ovs_sbx "$t" ip netns exec client \
+	    nc --sctp -w 2 -zv 172.31.110.20 4443 \
+	    >/dev/null 2>&1 \
+	    && { info "FAIL: connection should fail without flows"
+	         return 1; }
+
+	info "reinstall flows and verify recovery"
+	ovs_add_flow "$t" sctp4 \
+	    'in_port(1),eth(),eth_type(0x0800),ipv4(proto=132),sctp(dst=4443)' \
+	    '2' || return 1
+	ovs_add_flow "$t" sctp4 \
+	    'in_port(2),eth(),eth_type(0x0800),ipv4(proto=132),sctp(src=4443)' \
+	    '1' || return 1
+
+	kill -TERM $server_pid 2>/dev/null
+	wait $server_pid 2>/dev/null
+	echo "server3" | \
+		ovs_netns_spawn_daemon "$t" "server" \
+				nc --sctp -l 172.31.110.20 -vn 4443
+	ovs_wait ip netns exec server \
+	    ss -lnH sport = :4443 \| grep -q . \
+	    || return 1
+
+	ovs_sbx "$t" ip netns exec client \
+	    nc --sctp -i 1 -zv 172.31.110.20 4443 \
+	    || return 1
+
+	return 0
+}
+
 # psample test
 # - use psample to observe packets
 test_psample() {
diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
index e1ecfad2c03e..7cfc29ec7e59 100644
--- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
+++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
@@ -1982,6 +1982,11 @@ class ovskey(nla):
                 "icmp",
                 ovskey.ovs_key_icmp,
             ),
+            (
+                "OVS_KEY_ATTR_SCTP",
+                "sctp",
+                ovskey.ovs_key_sctp,
+            ),
             (
                 "OVS_KEY_ATTR_TCP_FLAGS",
                 "tcp_flags",
-- 
2.55.0


^ permalink raw reply related

* Re: [PATCH net-next,v3] xfrm: allow to enable udp encapsulation without userspace socket
From: Eyal Birger @ 2026-07-19 16:49 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: devel, netdev, tobias, antony, steffen.klassert
In-Reply-To: <20260717110118.251866-1-pablo@netfilter.org>

Hi,

On Fri, Jul 17, 2026 at 4:01 AM Pablo Neira Ayuso <pablo@netfilter.org> wrote:
>
> It is currently not possible to enable UDP encapsulation in xfrm without
> a userspace process that listens on the specified UDP listener port in
> the SA.
>
> People have work around this by creating dummy userspace daemons such as
> the one in the smallish perl program (see the script at the bottom of
> this link):
>
> http://techblog.newsnow.co.uk/2011/11/simple-udp-esp-encapsulation-nat-t-for.html
>
> This patch adds XFRM_SA_XFLAG_UDP_ENCAP_SOCK to create the UDP socket
> from the kernel.
>
> Use a hole in net->xfrm to place the new encap_socket list.
>
> The following example shows how to enable the standalone UDP
> encapsulation:
>
>     ip xfrm state add src 192.168.10.10 dst 192.168.10.11 proto esp spi 1 \
>             encap espinudp 9999 9999 0.0.0.0 \
>             if_id 0x1 reqid 1 replay-window 0 mode tunnel aead 'rfc4106(gcm(aes))' \
>             0x1111111111111111111111111111111111111111 96 \
>             sel src 10.141.10.0/24 dst 10.141.11.0/24 dir out
>
> and the receiving side uses 'extra-flag udp-encap-sock':
>
>     ip xfrm state add src 192.168.10.11 dst 192.168.10.10 proto esp spi 2 \
>             encap espinudp 9999 0 0.0.0.0 extra-flag udp-encap-sock \
>             if_id 0x1 reqid 2 replay-window 10 mode tunnel aead 'rfc4106(gcm(aes))' \
>             0x2222222222222222222222222222222222222222 96 dir in
>
> This allows for multiple SAs using the same listener udp port.
>
> This is useful for testing scenarios where UDP encapsulation is
> required.
>
> Note this patch exports xfrm6_udp_encap_rcv() just like
> xfrm4_udp_encap_rcv() otherwise linker complains due to unreachable
> symbol.
>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

LGTM. Thanks!

Reviewed-by: Eyal Birger <eyal.birger@gmail.com>



> ---
> v3: - Use x->id.daddr.a{4,6} instead of encap_oa, as suggested by Eyal and Tobias.
>     - Fix several SA using same udp encapsulation configuration.
>
> This is a follow up to:
> https://lists.linux-ipsec.org/archives/list/devel@lists.linux-ipsec.org/thread/F4IOY2DKFDX3E45UUFQHUZKTHV7AD6G4/
>
> NOTE for netdev maintainers:
> Targetting net-next so sashiko kicks in for review, ipsec-devel still has no such service yet.
>
>  include/net/netns/xfrm.h  |   1 +
>  include/net/xfrm.h        |  11 ++++
>  include/uapi/linux/xfrm.h |   1 +
>  net/ipv6/xfrm6_input.c    |   1 +
>  net/xfrm/Kconfig          |   2 +
>  net/xfrm/xfrm_state.c     |  16 +++++
>  net/xfrm/xfrm_user.c      | 122 +++++++++++++++++++++++++++++++++++++-
>  7 files changed, 152 insertions(+), 2 deletions(-)
>
> diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
> index b73983a17e08..5091c07b1e46 100644
> --- a/include/net/netns/xfrm.h
> +++ b/include/net/netns/xfrm.h
> @@ -56,6 +56,7 @@ struct netns_xfrm {
>         unsigned int            policy_count[XFRM_POLICY_MAX * 2];
>         struct work_struct      policy_hash_work;
>         struct xfrm_policy_hthresh policy_hthresh;
> +       struct hlist_head       encap_socket;
>         struct list_head        inexact_bins;
>
>
> diff --git a/include/net/xfrm.h b/include/net/xfrm.h
> index a6d69aaa6cd2..99730a2fc8b9 100644
> --- a/include/net/xfrm.h
> +++ b/include/net/xfrm.h
> @@ -25,6 +25,7 @@
>  #include <net/ipv6.h>
>  #include <net/ip6_fib.h>
>  #include <net/flow.h>
> +#include <net/udp_tunnel.h>
>  #include <net/gro_cells.h>
>
>  #include <linux/interrupt.h>
> @@ -169,6 +170,13 @@ struct xfrm_dev_offload {
>         u8                      flags : 2;
>  };
>
> +struct xfrm_encap_sock {
> +       struct hlist_node       list;
> +       struct udp_port_cfg     cfg;
> +       struct sock             *sk;
> +       refcount_t              refcnt;
> +};
> +
>  struct xfrm_mode {
>         u8 encap;
>         u8 family;
> @@ -249,6 +257,7 @@ struct xfrm_state {
>
>         /* Data for encapsulator */
>         struct xfrm_encap_tmpl  *encap;
> +       struct xfrm_encap_sock  *encap_sock;
>
>         /* NAT keepalive */
>         u32                     nat_keepalive_interval; /* seconds */
> @@ -2343,6 +2352,8 @@ static inline bool xfrm6_local_dontfrag(const struct sock *sk)
>  }
>  #endif
>
> +int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
> +
>  #if (IS_BUILTIN(CONFIG_XFRM_INTERFACE) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF)) || \
>      (IS_MODULE(CONFIG_XFRM_INTERFACE) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES))
>
> diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
> index 051f8066efd1..28aa5c8ca317 100644
> --- a/include/uapi/linux/xfrm.h
> +++ b/include/uapi/linux/xfrm.h
> @@ -413,6 +413,7 @@ struct xfrm_usersa_info {
>
>  #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP  1
>  #define XFRM_SA_XFLAG_OSEQ_MAY_WRAP    2
> +#define XFRM_SA_XFLAG_UDP_ENCAP_SOCK   4
>
>  struct xfrm_usersa_id {
>         xfrm_address_t                  daddr;
> diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
> index 89d0443b5307..2e3f7b9e5a4f 100644
> --- a/net/ipv6/xfrm6_input.c
> +++ b/net/ipv6/xfrm6_input.c
> @@ -173,6 +173,7 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
>
>         return ret;
>  }
> +EXPORT_SYMBOL(xfrm6_udp_encap_rcv);
>
>  struct sk_buff *xfrm6_gro_udp_encap_rcv(struct sock *sk, struct list_head *head,
>                                         struct sk_buff *skb)
> diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig
> index 4a62817a88f8..fe42cfca9423 100644
> --- a/net/xfrm/Kconfig
> +++ b/net/xfrm/Kconfig
> @@ -7,6 +7,7 @@ config XFRM
>         depends on INET
>         select GRO_CELLS
>         select SKB_EXTENSIONS
> +       select NET_UDP_TUNNEL
>
>  config XFRM_OFFLOAD
>         bool
> @@ -23,6 +24,7 @@ if INET
>  config XFRM_USER
>         tristate "Transformation user configuration interface"
>         select XFRM_ALGO
> +       select NET_UDP_TUNNEL
>         help
>           Support for Transformation(XFRM) user configuration interface
>           like IPsec used by native Linux tools.
> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
> index 36a4f6793ede..c849e7ac750a 100644
> --- a/net/xfrm/xfrm_state.c
> +++ b/net/xfrm/xfrm_state.c
> @@ -27,6 +27,7 @@
>  #include <linux/slab.h>
>  #include <linux/interrupt.h>
>  #include <linux/kernel.h>
> +#include <net/udp_tunnel.h>
>
>  #include <crypto/aead.h>
>
> @@ -586,6 +587,16 @@ static const struct xfrm_mode_cbs *xfrm_get_mode_cbs(u8 mode)
>         return cbs;
>  }
>
> +static bool xfrm_socket_put(struct xfrm_encap_sock *encap_sock)
> +{
> +       if (refcount_dec_and_test(&encap_sock->refcnt)) {
> +               udp_tunnel_sock_release(encap_sock->sk);
> +               return true;
> +       }
> +
> +       return false;
> +}
> +
>  void xfrm_state_free(struct xfrm_state *x)
>  {
>         kmem_cache_free(xfrm_state_cache, x);
> @@ -597,6 +608,10 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
>  {
>         if (x->mode_cbs && x->mode_cbs->destroy_state)
>                 x->mode_cbs->destroy_state(x);
> +
> +       if (x->encap_sock && xfrm_socket_put(x->encap_sock))
> +               kfree(x->encap_sock);
> +
>         hrtimer_cancel(&x->mtimer);
>         timer_delete_sync(&x->rtimer);
>         kfree_sensitive(x->aead);
> @@ -3332,6 +3347,7 @@ int __net_init xfrm_state_init(struct net *net)
>                                               SLAB_HWCACHE_ALIGN | SLAB_PANIC);
>
>         INIT_LIST_HEAD(&net->xfrm.state_all);
> +       INIT_HLIST_HEAD(&net->xfrm.encap_socket);
>
>         sz = sizeof(struct hlist_head) * 8;
>
> diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
> index d6db63304ba6..bc88581e51e8 100644
> --- a/net/xfrm/xfrm_user.c
> +++ b/net/xfrm/xfrm_user.c
> @@ -29,6 +29,7 @@
>  #include <net/xfrm.h>
>  #include <net/netlink.h>
>  #include <net/ah.h>
> +#include <net/udp_tunnel.h>
>  #include <linux/uaccess.h>
>  #if IS_ENABLED(CONFIG_IPV6)
>  #include <linux/in6.h>
> @@ -484,6 +485,17 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
>                         goto out;
>         }
>
> +       if (attrs[XFRMA_SA_EXTRA_FLAGS]) {
> +               u32 xflags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]);
> +
> +               if (xflags & XFRM_SA_XFLAG_UDP_ENCAP_SOCK &&
> +                   (!sa_dir || sa_dir == XFRM_SA_DIR_OUT)) {
> +                       NL_SET_ERR_MSG(extack, "Flag UDP_ENCAP_SOCK can only be set on input SA");
> +                       err = -EINVAL;
> +                       goto out;
> +               }
> +       }
> +
>         if (sa_dir == XFRM_SA_DIR_OUT) {
>                 if (p->flags & XFRM_STATE_DECAP_DSCP) {
>                         NL_SET_ERR_MSG(extack, "Flag DECAP_DSCP should not be set for output SA");
> @@ -556,7 +568,6 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
>                                 err = -EINVAL;
>                                 goto out;
>                         }
> -
>                 }
>
>                 if (attrs[XFRMA_IPTFS_DONT_FRAG]) {
> @@ -932,9 +943,17 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
>                         goto error;
>         }
>
> -       if (attrs[XFRMA_SA_EXTRA_FLAGS])
> +       if (attrs[XFRMA_SA_EXTRA_FLAGS]) {
>                 x->props.extra_flags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]);
>
> +               if (x->props.extra_flags & XFRM_SA_XFLAG_UDP_ENCAP_SOCK &&
> +                   x->encap && x->encap->encap_type != UDP_ENCAP_ESPINUDP) {
> +                       NL_SET_ERR_MSG(extack, "XFRM_SA_XFLAG_UDP_ENCAP_SOCK can only be set on UDP_ENCAP_ESPINUDP type");
> +                       err = -EOPNOTSUPP;
> +                       goto error;
> +               }
> +       }
> +
>         if ((err = attach_aead(x, attrs[XFRMA_ALG_AEAD], extack)))
>                 goto error;
>         if ((err = attach_auth_trunc(&x->aalg, &x->props.aalgo,
> @@ -1036,6 +1055,97 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
>         return NULL;
>  }
>
> +static struct xfrm_encap_sock *
> +xfrm_socket_find_get(struct net *net, const struct udp_port_cfg *udp_conf)
> +{
> +       struct xfrm_encap_sock *listener;
> +
> +       hlist_for_each_entry(listener, &net->xfrm.encap_socket, list) {
> +               if (!memcmp(&listener->cfg, udp_conf, sizeof(*udp_conf))) {
> +                       refcount_inc(&listener->refcnt);
> +                       return listener;
> +               }
> +       }
> +
> +       return NULL;
> +}
> +
> +static int xfrm_socket_encap_create(struct net *net, struct xfrm_state *x,
> +                                   struct udp_port_cfg *udp_conf,
> +                                   struct udp_tunnel_sock_cfg *tuncfg)
> +{
> +       struct xfrm_encap_sock *listener;
> +       struct socket *sock;
> +       int err;
> +
> +       listener = kzalloc_obj(*listener);
> +       if (!listener)
> +               return -ENOMEM;
> +
> +       err = udp_sock_create(net, udp_conf, &sock);
> +       if (err) {
> +               kfree(listener);
> +               return err;
> +       }
> +       setup_udp_tunnel_sock(net, sock->sk, tuncfg);
> +
> +       listener->sk = sock->sk;
> +       listener->cfg = *udp_conf;
> +       refcount_set(&listener->refcnt, 1);
> +       hlist_add_head(&listener->list, &net->xfrm.encap_socket);
> +
> +       x->encap_sock = listener;
> +
> +       return 0;
> +}
> +
> +static int xfrm_socket_setup(struct net *net, struct xfrm_state *x,
> +                            struct netlink_ext_ack *extack)
> +{
> +       struct udp_tunnel_sock_cfg tuncfg = {};
> +       struct xfrm_encap_sock *listener;
> +       struct udp_port_cfg udp_conf;
> +       int err;
> +
> +       if (!x->encap)
> +               return -EOPNOTSUPP;
> +
> +       memset(&udp_conf, 0, sizeof(udp_conf));
> +       udp_conf.family = x->props.family;
> +
> +       switch (x->props.family) {
> +       case AF_INET:
> +               udp_conf.local_ip.s_addr = x->id.daddr.a4;
> +               tuncfg.encap_rcv = xfrm4_udp_encap_rcv;
> +               break;
> +#if IS_ENABLED(CONFIG_IPV6)
> +       case AF_INET6:
> +               udp_conf.local_ip6 = x->id.daddr.in6;
> +               tuncfg.encap_rcv = xfrm6_udp_encap_rcv;
> +               break;
> +#endif
> +       default:
> +               return -EOPNOTSUPP;
> +       }
> +       udp_conf.local_udp_port = x->encap->encap_sport;
> +
> +       listener = xfrm_socket_find_get(net, &udp_conf);
> +       if (listener) {
> +               x->encap_sock = listener;
> +               return 0;
> +       }
> +
> +       tuncfg.encap_type = UDP_ENCAP_ESPINUDP;
> +
> +       err = xfrm_socket_encap_create(net, x, &udp_conf, &tuncfg);
> +       if (err < 0) {
> +               NL_SET_ERR_MSG(extack, "Cannot initialize kernel UDP socket");
> +               return err;
> +       }
> +
> +       return 0;
> +}
> +
>  static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
>                        struct nlattr **attrs, struct netlink_ext_ack *extack)
>  {
> @@ -1053,6 +1163,14 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
>         if (!x)
>                 return err;
>
> +       if (x->props.extra_flags & XFRM_SA_XFLAG_UDP_ENCAP_SOCK) {
> +               err = xfrm_socket_setup(net, x, extack);
> +               if (err < 0) {
> +                       x->km.state = XFRM_STATE_DEAD;
> +                       goto out;
> +               }
> +       }
> +
>         xfrm_state_hold(x);
>         if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
>                 err = xfrm_state_add(x);
> --
> 2.47.3
>

^ permalink raw reply

* Re: [RFC PATCH net-next v0.1 1/1] net: add GeoNetworking protocol
From: Andrew Lunn @ 2026-07-19 17:16 UTC (permalink / raw)
  To: Simon Dietz
  Cc: netdev, andrew+netdev, davem, edumazet, johannes, kuniyu,
	linux-wireless, dietz23838
In-Reply-To: <20260718210046.2357882-2-simon.dietz@plantwatch.de>

Can this:

> +#define GN_MAX_HEADER_SZ 88

Be defined in terms of:

> +#define GN_GUC_HLEN sizeof(struct gn_guc_header)
> +#define GN_GXC_HLEN sizeof(struct gn_gxc_header)
> +#define GN_SHB_HLEN sizeof(struct gn_shb_header)
> +#define GN_TSB_HLEN sizeof(struct gn_tsb_header)
> +#define GN_BEACON_HLEN sizeof(struct gn_beacon_header)
> +#define GN_LS_REQUEST_HLEN sizeof(struct gn_ls_request_header)
> +#define GN_LS_REPLY_HLEN sizeof(struct gn_ls_reply_header)
> +#define BTP_HLEN sizeof(struct btp_header)

#define GN_MAX_HEADER_SZ (GN_GUC_HLEN + GN_GXC_HLEN + GN_SHB_HLEN + GN_TSB_HLEN + ...)

Doing it like this makes it also documentation, the assumption is, the
biggest header contains these sub headers.

> +/**
> + *	struct gn_iface - GeoNetworking interface
> + *	@dev - Network device associated with this interface
> + *	@address - Our address
> + *	@local_sn - Current sequence number
> + */
> +struct gn_iface {
> +	struct net_device	*dev;
> +	gn_address_t	address;
> +	struct gn_position pos;
> +	atomic_t local_sn;
> +	struct hlist_node hnode;
> +	struct rcu_head rcu;
> +};

It does not look like all members have the same indentation here. I
would suggest they are all indented to the same level, or none are
indented. This is a general comment for the code as a whole.

> +enum ITS_TYPE {
> +	UNKNOWN,

It is typical to use

	UNKNOWN = 0,

> +	PEDESTRIAN,
> +	CYCLIST,

and then the rest without explicit values. I don't know what the C
standard says, but maybe without the = 0, a language lawyer might
argue it is allowed to start at 42 and count upwards from there?

> +	MOPED,
> +	MOTORCYCLE,

Are these from the standard?  Maybe reference the clause in the
standard? The point being, we reviewers want to know if random
developer can add HOT_AIR_BALLOON, and HORSE_AND_TRAP at the end, or
if additions must first be accepted at the standards level and
assigned numbers.

	Andrew

^ permalink raw reply

* Re: [RFC PATCH net-next v0.1 1/1] net: add GeoNetworking protocol
From: Andrew Lunn @ 2026-07-19 17:28 UTC (permalink / raw)
  To: Simon Dietz
  Cc: netdev, andrew+netdev, davem, edumazet, johannes, kuniyu,
	linux-wireless, dietz23838
In-Reply-To: <20260718210046.2357882-2-simon.dietz@plantwatch.de>

> +#define GN_EPOCH_UNIX_MS 1072915232000LLU
> +
> +/* time until location table entry becomes invalid */
> +#define GN_LOC_TE_LIFETIME 20000
> +/* time between two beacons */
> +#define GN_BEACON_RETRANSMIT_TIME 3000
> +/* time between retransmits of an unanswered location service request */
> +#define GN_LS_RETRANSMIT_TIME 1000

It would be nice to have some units in these #defines. Classical bugs
are forgetting to convert from milliseconds to jiffies, or
milliseconds to microseconds. Having the unit in the name helpers
avoid that.

> +/* sizes in KiB */
> +#define GN_UC_BUF_SIZE 256
> +#define GN_BC_BUF_SIZE 1024
> +#define GN_CBF_BUF_SIZE 256

Again, units would be useful, the default would be to these are bytes,
not KB.

There is also linux/sizes.h.

	Andrew

^ permalink raw reply

* [PATCH net-next v4 0/8] net: dsa: mt7530: modernise register access and add two DSA ops
From: Daniel Golle @ 2026-07-19 17:33 UTC (permalink / raw)
  To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger, AngeloGioacchino Del Regno, Russell King,
	netdev, linux-kernel, linux-arm-kernel, linux-mediatek

The mt7530 driver carries its own register accessors that predate the
regmap conversion and now largely duplicate what regmap already
provides, including locking. Most of this series removes that layer.

It first moves the MDIO bus locking into the switch regmap via
.lock/.unlock callbacks, matching the PCS regmaps, so any path reaching
the regmap is serialised automatically. With the wrappers no longer
adding locking, the thin mt7530_mii_* indirection is folded away and the
remaining accessors are replaced mechanically with the plain regmap API,
using the coccinelle semantic patches included in the commit messages.
Open-coded register fields are then converted to FIELD_GET/FIELD_PREP.
None of this is intended to change behaviour.

The last two patches implement .port_fast_age, which flushes dynamically
learned MAC entries on topology changes, and .port_change_conduit, which
moves a user port's CPU-port affinity at runtime.

v3 of this series arrived too close to the end of the last development
cycle and was deferred, hence this respin on top of current net-next.
---
v4:
 * rebase onto current net-next
 * 5/8: zero the read-back buffer in mt7530_regmap_read() instead of
   initialising the result variables at every call site, as suggested
   by Jakub
 * 6/8: keep MT753X_CTRL_PHY_ADDR() as plain address arithmetic rather
   than converting it to FIELD_PREP() as suggested in review: the macro
   computes the MDIO bus address of the switch PHYs, used as the addr
   argument of bus->read/write and as an iterator base in
   mt7530_setup_mdio(), not a hardware register field
v3:
 * 5/8: initialise register read-back variables to 0 so a failed
   regmap_read keeps the previous read-as-zero behaviour, and use u32
   for the value in mt7530_setup_port5
 * 6/8: name the age timer field AGE_TIMER_MASK and document the
   corrected ATC_HASH/VTCR_VID field macros
 * 7/8: serialise the port_fast_age ATC flush under reg_mutex and log
   on timeout, align a define, and correct the commit message which
   wrongly claimed per-port parity with b53/realtek
 * 8/8: populate the netlink extack on rejection and refuse a conduit
   that lives on a different switch
v2:
 * fix stray 'static void' left-over in 4/8 which had a fix accidentally
   folded into 5/8 (byte-identical state at 8/8, but bisectability is
   restored)
 * extend port_change_conduit op commit message

Daniel Golle (8):
  net: dsa: mt7530: move MDIO bus locking into regmap
  net: dsa: mt7530: fold mt7530_mii_write/read into mt7530_write/read
  net: dsa: mt7530: replace mt7530_write with regmap_write
  net: dsa: mt7530: replace mt7530_rmw/set/clear with regmap API
  net: dsa: mt7530: replace mt7530_read with regmap_read
  net: dsa: mt7530: convert to use field accessor macros
  net: dsa: mt7530: implement port_fast_age
  net: dsa: mt7530: implement port_change_conduit op

 drivers/net/dsa/mt7530-mdio.c |  12 +-
 drivers/net/dsa/mt7530.c      | 809 +++++++++++++++++-----------------
 drivers/net/dsa/mt7530.h      | 209 +++++----
 3 files changed, 537 insertions(+), 493 deletions(-)


base-commit: ce6b4d3216b63f902bb8e9695ee6c10c83415f65
-- 
2.55.0

^ permalink raw reply

* [PATCH net] netdevsim: tc: serialize access to nsim_block_cb_list
From: Weiming Shi @ 2026-07-19 17:50 UTC (permalink / raw)
  To: Jakub Kicinski, Andrew Lunn, David S . Miller, Eric Dumazet,
	Paolo Abeni
  Cc: Pablo Neira Ayuso, netdev, linux-kernel, Xiang Mei, Weiming Shi,
	stable

nsim_setup_tc() passes a single global nsim_block_cb_list, shared by every
netdevsim device, to flow_block_cb_setup_simple(). That helper does
list_add_tail()/list_del() on the list on block bind/unbind and walks it
in flow_block_cb_is_busy(); it takes no lock of its own and relies on the
caller for serialization.

The tc control path calls ndo_setup_tc(TC_SETUP_BLOCK) under rtnl, but the
nf_tables hardware offload path reaches it under the per-netns nftables
commit_mutex only. Two nft transactions committing offload chains from
different netns thus run flow_block_cb_setup_simple() on the same list
concurrently, corrupting it and freeing a flow_block_cb that the other CPU
still walks:

 list_del corruption. prev->next should be ffff88801f18ff00, but was ffff88801de82b00.
 kernel BUG at lib/list_debug.c:62!
 RIP: 0010:__list_del_entry_valid_or_report (lib/list_debug.c:62)
  flow_block_cb_setup_simple (net/core/flow_offload.c:369)
  nsim_setup_tc (drivers/net/netdevsim/tc.c)
  nft_block_offload_cmd (net/netfilter/nf_tables_offload.c:394)
  nft_flow_rule_offload_commit (net/netfilter/nf_tables_offload.c:585)
  nf_tables_commit (net/netfilter/nf_tables_api.c:10490)
  nfnetlink_rcv_batch (net/netfilter/nfnetlink.c:577)
  nfnetlink_rcv (net/netfilter/nfnetlink.c:649)
  netlink_unicast (net/netlink/af_netlink.c:1314)
  netlink_sendmsg (net/netlink/af_netlink.c:1889)
  __sys_sendto (net/socket.c:729)

With KASAN the same race is reported as a slab-use-after-free read of the
freed flow_block_cb (kmalloc-192) in flow_block_cb_setup_simple(). The
trace above is from a 6.12.y reproduction.

Serialize the list with a mutex. ndo_setup_tc(TC_SETUP_BLOCK) always runs
in process context, so sleeping on the mutex is fine.

Fixes: 955bcb6ea0df ("drivers: net: use flow block API")
Reported-by: Xiang Mei <xmei5@asu.edu>
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
 drivers/net/netdevsim/tc.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/netdevsim/tc.c b/drivers/net/netdevsim/tc.c
index a415e02a6df1..30dd7f924b71 100644
--- a/drivers/net/netdevsim/tc.c
+++ b/drivers/net/netdevsim/tc.c
@@ -72,11 +72,13 @@ static int nsim_setup_tc_ets(struct net_device *dev,
 }
 
 static LIST_HEAD(nsim_block_cb_list);
+static DEFINE_MUTEX(nsim_block_cb_lock);
 
 int
 nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
 {
 	struct netdevsim *ns = netdev_priv(dev);
+	int err;
 
 	switch (type) {
 	case TC_SETUP_QDISC_TAPRIO:
@@ -84,10 +86,13 @@ nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
 	case TC_SETUP_QDISC_ETS:
 		return nsim_setup_tc_ets(dev, type_data);
 	case TC_SETUP_BLOCK:
-		return flow_block_cb_setup_simple(type_data,
-						  &nsim_block_cb_list,
-						  nsim_setup_tc_block_cb,
-						  ns, ns, true);
+		mutex_lock(&nsim_block_cb_lock);
+		err = flow_block_cb_setup_simple(type_data,
+						 &nsim_block_cb_list,
+						 nsim_setup_tc_block_cb,
+						 ns, ns, true);
+		mutex_unlock(&nsim_block_cb_lock);
+		return err;
 	case TC_SETUP_FT:
 		return 0;
 	default:
-- 
2.43.0


^ permalink raw reply related

* [PATCH net-next v4 1/8] net: dsa: mt7530: move MDIO bus locking into regmap
From: Daniel Golle @ 2026-07-19 17:53 UTC (permalink / raw)
  To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger, AngeloGioacchino Del Regno, Russell King,
	netdev, linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1784481922.git.daniel@makrotopia.org>

The switch register regmap was created with .disable_locking = true,
relying on callers to manually lock the MDIO bus. Move the locking
into the regmap using .lock/.unlock callbacks, matching the PCS
regmaps that already do this. This allows any code path reaching the
regmap to be automatically protected.

With regmap handling bus locking, the manual mt7530_mutex_lock/unlock
wrappers in mt7530_write(), _mt7530_read(), mt7530_rmw() and
mt7530_port_change_mtu() become redundant and are removed.

The MT7531 indirect PHY access functions need serialization of their
multi-step register sequences, but no longer need to hold bus->mdio_lock
across the whole operation. Switch them to reg_mutex.

core_write()/core_rmw() are the only remaining callers of
mt7530_mutex_lock(). They access TRGMII core PHY registers via the
clause 22 MMD indirect protocol -- a separate register space that
bypasses regmap and needs manual bus->mdio_lock protection.

Generated using the following semantic patch:

// Remove mt7530_mutex_lock/unlock around single regmap-based calls.
@@
expression priv, reg, val;
@@
 {
-	mt7530_mutex_lock(priv);
-
 	mt7530_mii_write(priv, reg, val);
-
-	mt7530_mutex_unlock(priv);
 }

@@
expression priv, reg, mask, set;
@@
 {
-	mt7530_mutex_lock(priv);
-
 	regmap_update_bits(priv->regmap, reg, mask, set);
-
-	mt7530_mutex_unlock(priv);
 }

@@
expression p;
identifier val;
@@
 {
-	u32 val;
-	mt7530_mutex_lock(p->priv);
-	val = mt7530_mii_read(p->priv, p->reg);
-	mt7530_mutex_unlock(p->priv);
-	return val;
+	return mt7530_mii_read(p->priv, p->reg);
 }

@@
expression priv;
@@
-	mt7530_mutex_lock(priv);
 	val = mt7530_mii_read(priv, MT7530_GMACCR);
 	...
 	mt7530_mii_write(priv, MT7530_GMACCR, val);
-	mt7530_mutex_unlock(priv);

@@
expression priv, port;
@@
 	INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
-	mt7530_mutex_lock(priv);
+	mutex_lock(&priv->reg_mutex);

@@
expression priv;
@@
 out:
-	mt7530_mutex_unlock(priv);
+	mutex_unlock(&priv->reg_mutex);

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/dsa/mt7530-mdio.c |  9 ++++++---
 drivers/net/dsa/mt7530.c      | 38 +++++++++--------------------------
 2 files changed, 15 insertions(+), 32 deletions(-)

diff --git a/drivers/net/dsa/mt7530-mdio.c b/drivers/net/dsa/mt7530-mdio.c
index 11ea924a9f35..f7c8eeb27211 100644
--- a/drivers/net/dsa/mt7530-mdio.c
+++ b/drivers/net/dsa/mt7530-mdio.c
@@ -141,12 +141,14 @@ static const struct regmap_config regmap_config = {
 	.val_bits = 32,
 	.reg_stride = 4,
 	.max_register = MT7530_CREV,
-	.disable_locking = true,
+	.lock = mt7530_mdio_regmap_lock,
+	.unlock = mt7530_mdio_regmap_unlock,
 };
 
 static int
 mt7530_probe(struct mdio_device *mdiodev)
 {
+	struct regmap_config rc = regmap_config;
 	struct mt7530_priv *priv;
 	struct device_node *dn;
 	int ret;
@@ -200,8 +202,9 @@ mt7530_probe(struct mdio_device *mdiodev)
 			return PTR_ERR(priv->io_pwr);
 	}
 
-	priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv,
-					&regmap_config);
+	rc.lock_arg = &priv->bus->mdio_lock;
+	priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus,
+					priv, &rc);
 	if (IS_ERR(priv->regmap))
 		return PTR_ERR(priv->regmap);
 
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 3c2a3029b10c..5f56a423b147 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -184,11 +184,7 @@ mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
 static void
 mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
 {
-	mt7530_mutex_lock(priv);
-
 	mt7530_mii_write(priv, reg, val);
-
-	mt7530_mutex_unlock(priv);
 }
 
 static u32
@@ -200,15 +196,7 @@ _mt7530_unlocked_read(struct mt7530_dummy_poll *p)
 static u32
 _mt7530_read(struct mt7530_dummy_poll *p)
 {
-	u32 val;
-
-	mt7530_mutex_lock(p->priv);
-
-	val = mt7530_mii_read(p->priv, p->reg);
-
-	mt7530_mutex_unlock(p->priv);
-
-	return val;
+	return mt7530_mii_read(p->priv, p->reg);
 }
 
 static u32
@@ -224,11 +212,7 @@ static void
 mt7530_rmw(struct mt7530_priv *priv, u32 reg,
 	   u32 mask, u32 set)
 {
-	mt7530_mutex_lock(priv);
-
 	regmap_update_bits(priv->regmap, reg, mask, set);
-
-	mt7530_mutex_unlock(priv);
 }
 
 static void
@@ -555,7 +539,7 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
 
 	INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
 
-	mt7530_mutex_lock(priv);
+	mutex_lock(&priv->reg_mutex);
 
 	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
 				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -588,7 +572,7 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
 
 	ret = val & MT7531_MDIO_RW_DATA_MASK;
 out:
-	mt7530_mutex_unlock(priv);
+	mutex_unlock(&priv->reg_mutex);
 
 	return ret;
 }
@@ -603,7 +587,7 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
 
 	INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
 
-	mt7530_mutex_lock(priv);
+	mutex_lock(&priv->reg_mutex);
 
 	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
 				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -635,7 +619,7 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
 	}
 
 out:
-	mt7530_mutex_unlock(priv);
+	mutex_unlock(&priv->reg_mutex);
 
 	return ret;
 }
@@ -649,7 +633,7 @@ mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
 
 	INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
 
-	mt7530_mutex_lock(priv);
+	mutex_lock(&priv->reg_mutex);
 
 	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
 				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -672,7 +656,7 @@ mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
 
 	ret = val & MT7531_MDIO_RW_DATA_MASK;
 out:
-	mt7530_mutex_unlock(priv);
+	mutex_unlock(&priv->reg_mutex);
 
 	return ret;
 }
@@ -687,7 +671,7 @@ mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
 
 	INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
 
-	mt7530_mutex_lock(priv);
+	mutex_lock(&priv->reg_mutex);
 
 	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
 				 !(reg & MT7531_PHY_ACS_ST), 20, 100000);
@@ -709,7 +693,7 @@ mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
 	}
 
 out:
-	mt7530_mutex_unlock(priv);
+	mutex_unlock(&priv->reg_mutex);
 
 	return ret;
 }
@@ -1444,8 +1428,6 @@ mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
 	if (!dsa_is_cpu_port(ds, port))
 		return 0;
 
-	mt7530_mutex_lock(priv);
-
 	val = mt7530_mii_read(priv, MT7530_GMACCR);
 	val &= ~MAX_RX_PKT_LEN_MASK;
 
@@ -1465,8 +1447,6 @@ mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
 
 	mt7530_mii_write(priv, MT7530_GMACCR, val);
 
-	mt7530_mutex_unlock(priv);
-
 	return 0;
 }
 
-- 
2.55.0

^ permalink raw reply related


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