* [RFC PATCH net-next] pppoe: drop getsockname() syscall
From: Qingfang Deng @ 2026-04-15 9:16 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Qingfang Deng, Kees Cook, Guillaume Nault,
Eric Woudstra, netdev, linux-kernel
Cc: Paul Mackerras, linux-ppp, Jaco Kroon, James Carlson,
Dianne Skoll, Denys Fedoryshchenko
The getsockname syscall is not used by pppd. It also has two flaws:
1. It does not hold the socket lock, so if the struct is being changed
in pppoe_connect() simultaneously, it may see partial updates.
2. If the lower network device is renamed, this operation still returns
the original name.
Given it is unused and buggy, remove the syscall.
Signed-off-by: Qingfang Deng <qingfang.deng@linux.dev>
---
Note: sent as RFC, since net-next is closed.
drivers/net/ppp/pppoe.c | 18 +-----------------
1 file changed, 1 insertion(+), 17 deletions(-)
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index d546a7af0d54..0d64a16715e2 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -688,22 +688,6 @@ static int pppoe_connect(struct socket *sock, struct sockaddr_unsized *uservaddr
goto end;
}
-static int pppoe_getname(struct socket *sock, struct sockaddr *uaddr,
- int peer)
-{
- int len = sizeof(struct sockaddr_pppox);
- struct sockaddr_pppox sp;
-
- sp.sa_family = AF_PPPOX;
- sp.sa_protocol = PX_PROTO_OE;
- memcpy(&sp.sa_addr.pppoe, &pppox_sk(sock->sk)->pppoe_pa,
- sizeof(struct pppoe_addr));
-
- memcpy(uaddr, &sp, len);
-
- return len;
-}
-
static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg)
{
@@ -1049,7 +1033,7 @@ static const struct proto_ops pppoe_ops = {
.connect = pppoe_connect,
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
- .getname = pppoe_getname,
+ .getname = sock_no_getname,
.poll = datagram_poll,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] netfilter: xt_realm: fix null-ptr-deref in realm_mt()
From: Pablo Neira Ayuso @ 2026-04-15 9:27 UTC (permalink / raw)
To: Florian Westphal
Cc: Kito Xu (veritas501), phil, davem, edumazet, kuba, pabeni, horms,
jengelh, kaber, netfilter-devel, coreteam, netdev, linux-kernel
In-Reply-To: <ad9UF5Cr12YGJnbi@strlen.de>
On Wed, Apr 15, 2026 at 11:02:15AM +0200, Florian Westphal wrote:
> Kito Xu (veritas501) <hxzene@gmail.com> wrote:
> > realm_mt() unconditionally dereferences skb_dst(skb) without a NULL
> > check. The xt_realm match registers with .family = NFPROTO_UNSPEC,
> > making it available to all netfilter protocol families. Through the
> > nftables compat layer (nft_compat), an unprivileged user inside a
> > user/net namespace can load this match into a bridge-family chain.
>
> I do not think this bug is related to nft_compat.
> You can also use ebtables setsockopt api to request xt_realm, no?
>
> > Fixes: ab4f21e6fb1c ("netfilter: xtables: use NFPROTO_UNSPEC in more extensions")
>
> Looks correct. Alternatively we could revert the xt_realm.c change.
> But I don't have a strong opinion here, patch looks correct.
Maybe partial revert makes sense, since in ab4f21e6fb1c:
- xt_MARK: OK
- xt_NOTRACK: OK
- xt_comment: OK
- xt_mac: There is a better way to do this in bridge.
- xt_owner, no sockets in bridge.
- xt_physdev, which makes no sense in bridge, this is for br_netfilter
only.
- xt_realm (as already mentioned).
That is, a partial revert of this patch for:
- xt_mac
- xt_owner
- xt_physdev
- xt_realm
^ permalink raw reply
* [PATCH net 1/1] mptcp: hold subflow request owners when cloning reqsk
From: Ren Wei @ 2026-04-15 9:31 UTC (permalink / raw)
To: netdev, mptcp
Cc: davem, edumazet, kuba, pabeni, horms, ncardwell, kuniyu, dsahern,
matttbe, martineau, geliang, daniel, kafai, yuantan098, yifanwucs,
tomapufckgml, bird, caoruide123, enjou1224z, n05ec
In-Reply-To: <cover.1776149210.git.caoruide123@gmail.com>
From: Ruide Cao <caoruide123@gmail.com>
TCP request migration clones pending request sockets with
inet_reqsk_clone(). For MPTCP MP_JOIN requests this raw-copies
subflow_req->msk, but the cloned request does not take a new reference.
Both the original and the cloned request can later drop the same msk in
subflow_req_destructor(), and a migrated request may keep a dangling msk
pointer after the original owner has already been released.
Add a request_sock clone callback and let MPTCP grab a reference for cloned
subflow requests that carry an msk. This keeps ownership balanced across
both successful migrations and failed clone/insert paths without changing
other protocols.
Fixes: c905dee62232 ("tcp: Migrate TCP_NEW_SYN_RECV requests at retransmitting SYN+ACKs.")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Ruide Cao <caoruide123@gmail.com>
Tested-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
include/net/request_sock.h | 2 ++
net/ipv4/inet_connection_sock.c | 3 +++
net/mptcp/subflow.c | 13 +++++++++++++
3 files changed, 18 insertions(+)
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 5a9c826a7092..560e464c400f 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -36,6 +36,8 @@ struct request_sock_ops {
struct sk_buff *skb,
enum sk_rst_reason reason);
void (*destructor)(struct request_sock *req);
+ void (*init_clone)(const struct request_sock *req,
+ struct request_sock *new_req);
};
struct saved_syn {
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index e961936b6be7..140a9e96ad58 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -954,6 +954,9 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,
if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(nreq)->tfo_listener)
rcu_assign_pointer(tcp_sk(nreq->sk)->fastopen_rsk, nreq);
+ if (req->rsk_ops->init_clone)
+ req->rsk_ops->init_clone(req, nreq);
+
return nreq;
}
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 4ff5863aa9fd..5f4069647822 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -47,6 +47,17 @@ static void subflow_req_destructor(struct request_sock *req)
mptcp_token_destroy_request(req);
}
+static void subflow_req_clone(const struct request_sock *req,
+ struct request_sock *new_req)
+{
+ struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(new_req);
+
+ (void)req;
+
+ if (subflow_req->msk)
+ sock_hold((struct sock *)subflow_req->msk);
+}
+
static void subflow_generate_hmac(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
void *hmac)
{
@@ -2143,6 +2154,7 @@ void __init mptcp_subflow_init(void)
mptcp_subflow_v4_request_sock_ops = tcp_request_sock_ops;
mptcp_subflow_v4_request_sock_ops.slab_name = "request_sock_subflow_v4";
mptcp_subflow_v4_request_sock_ops.destructor = subflow_v4_req_destructor;
+ mptcp_subflow_v4_request_sock_ops.init_clone = subflow_req_clone;
if (subflow_ops_init(&mptcp_subflow_v4_request_sock_ops) != 0)
panic("MPTCP: failed to init subflow v4 request sock ops\n");
@@ -2184,6 +2196,7 @@ void __init mptcp_subflow_v6_init(void)
mptcp_subflow_v6_request_sock_ops = tcp6_request_sock_ops;
mptcp_subflow_v6_request_sock_ops.slab_name = "request_sock_subflow_v6";
mptcp_subflow_v6_request_sock_ops.destructor = subflow_v6_req_destructor;
+ mptcp_subflow_v6_request_sock_ops.init_clone = subflow_req_clone;
if (subflow_ops_init(&mptcp_subflow_v6_request_sock_ops) != 0)
panic("MPTCP: failed to init subflow v6 request sock ops\n");
--
2.34.1
^ permalink raw reply related
* [PATCH v3 0/4] Rust netlink support + use in Rust Binder
From: Alice Ryhl @ 2026-04-15 9:37 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Greg Kroah-Hartman,
Arve Hjønnevåg, Todd Kjos, Christian Brauner,
Carlos Llamas
Cc: linux-kernel, rust-for-linux, netdev, Alice Ryhl
The C Binder driver exposes messages over netlink when transactions
fail, so that a userpace daemon can respond to processes with many
failing transactions.
This patch series adds netlink support from Rust, then implements an
equivalent API in Rust Binder.
As Binder only uses broadcast messages, I did not add support for other
kinds of messages.
Based on char-misc-next.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
Changes in v3:
- Fix spurious 'return' statements in Rust helpers (Patch 1).
- Sashiko review:
- Fix ynl_gen to handle empty multicast groups and correct multicast indexing (Patch 2).
- Fix transaction failed reply logic to report via Netlink inside reply_inner() (Patch 4).
- Link to v2: https://lore.kernel.org/r/20260408-binder-netlink-v2-0-c0d327d15435@google.com
Changes in v2:
- Make inclusion of to_pid conditional too.
- Add note about file name in second patch.
- Make it clear that the sk_buff wrapper is netlink-specific.
- Better handle bitfield in patch 1.
- Link to v1: https://lore.kernel.org/r/20260306-binder-netlink-v1-0-daceb5bc83f2@google.com
---
Alice Ryhl (3):
rust: netlink: add raw netlink abstraction
ynl_gen: generate Rust files from yaml files
rust_binder: add generated netlink.rs file
Carlos Llamas (1):
rust_binder: report netlink transactions
drivers/android/Kconfig | 2 +-
drivers/android/binder/netlink.rs | 113 ++++++++++
drivers/android/binder/rust_binder_main.rs | 8 +-
drivers/android/binder/thread.rs | 10 +
drivers/android/binder/transaction.rs | 40 ++++
rust/bindings/bindings_helper.h | 3 +
rust/helpers/genetlink.c | 46 ++++
rust/helpers/helpers.c | 1 +
rust/kernel/lib.rs | 1 +
rust/kernel/netlink.rs | 329 +++++++++++++++++++++++++++++
rust/uapi/uapi_helper.h | 1 +
tools/net/ynl/pyynl/ynl_gen_c.py | 139 +++++++++++-
tools/net/ynl/ynl-regen.sh | 2 +-
13 files changed, 690 insertions(+), 5 deletions(-)
---
base-commit: 0990a71f678aa0f045f2c126b39b6b581844d3b0
change-id: 20260306-binder-netlink-c82110b2fb74
Best regards,
--
Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply
* [PATCH v3 1/4] rust: netlink: add raw netlink abstraction
From: Alice Ryhl @ 2026-04-15 9:37 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Greg Kroah-Hartman,
Arve Hjønnevåg, Todd Kjos, Christian Brauner,
Carlos Llamas
Cc: linux-kernel, rust-for-linux, netdev, Alice Ryhl
In-Reply-To: <20260415-binder-netlink-v3-0-84be9ba63ee2@google.com>
This implements a safe and relatively simple API over the netlink API,
that allows you to add different attributes to a netlink message and
broadcast it. As the first user of this API only makes use of broadcast,
only broadcast messages are supported here.
This API is intended to be safe and to be easy to use in *generated*
code. This is because netlink is generally used with yaml files that
describe the underlying API, and the python generator outputs C code
(or, soon, Rust code) that lets you use the API more easily. So for
example, if there is a string field, the code generator will output a
method that internall calls `put_string()` with the right attr type.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
rust/bindings/bindings_helper.h | 3 +
rust/helpers/genetlink.c | 46 ++++++
rust/helpers/helpers.c | 1 +
rust/kernel/lib.rs | 1 +
rust/kernel/netlink.rs | 329 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 380 insertions(+)
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 083cc44aa952..8abb626fce6c 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -88,6 +88,8 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/xarray.h>
+#include <net/genetlink.h>
+#include <net/netlink.h>
#include <trace/events/rust_sample.h>
/*
@@ -105,6 +107,7 @@
const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
const size_t RUST_CONST_HELPER_ARCH_KMALLOC_MINALIGN = ARCH_KMALLOC_MINALIGN;
const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE;
+const size_t RUST_CONST_HELPER_GENLMSG_DEFAULT_SIZE = GENLMSG_DEFAULT_SIZE;
const gfp_t RUST_CONST_HELPER_GFP_ATOMIC = GFP_ATOMIC;
const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL;
const gfp_t RUST_CONST_HELPER_GFP_KERNEL_ACCOUNT = GFP_KERNEL_ACCOUNT;
diff --git a/rust/helpers/genetlink.c b/rust/helpers/genetlink.c
new file mode 100644
index 000000000000..3530b69f6cf7
--- /dev/null
+++ b/rust/helpers/genetlink.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2026 Google LLC.
+ */
+
+#include <net/genetlink.h>
+
+#ifdef CONFIG_NET
+
+__rust_helper struct sk_buff *rust_helper_genlmsg_new(size_t payload, gfp_t flags)
+{
+ return genlmsg_new(payload, flags);
+}
+
+__rust_helper
+int rust_helper_genlmsg_multicast(const struct genl_family *family,
+ struct sk_buff *skb, u32 portid,
+ unsigned int group, gfp_t flags)
+{
+ return genlmsg_multicast(family, skb, portid, group, flags);
+}
+
+__rust_helper void rust_helper_genlmsg_cancel(struct sk_buff *skb, void *hdr)
+{
+ genlmsg_cancel(skb, hdr);
+}
+
+__rust_helper void rust_helper_genlmsg_end(struct sk_buff *skb, void *hdr)
+{
+ genlmsg_end(skb, hdr);
+}
+
+__rust_helper void rust_helper_nlmsg_free(struct sk_buff *skb)
+{
+ nlmsg_free(skb);
+}
+
+__rust_helper
+int rust_helper_genl_has_listeners(const struct genl_family *family,
+ struct net *net, unsigned int group)
+{
+ return genl_has_listeners(family, net, group);
+}
+
+#endif
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index a3c42e51f00a..0813185d8760 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -32,6 +32,7 @@
#include "err.c"
#include "irq.c"
#include "fs.c"
+#include "genetlink.c"
#include "io.c"
#include "jump_label.c"
#include "kunit.c"
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index d93292d47420..f5ea0ae0b6b7 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -122,6 +122,7 @@
pub mod module_param;
#[cfg(CONFIG_NET)]
pub mod net;
+pub mod netlink;
pub mod num;
pub mod of;
#[cfg(CONFIG_PM_OPP)]
diff --git a/rust/kernel/netlink.rs b/rust/kernel/netlink.rs
new file mode 100644
index 000000000000..21f959c95fdc
--- /dev/null
+++ b/rust/kernel/netlink.rs
@@ -0,0 +1,329 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2026 Google LLC.
+
+//! Rust support for generic netlink.
+//!
+//! Currently only supports exposing multicast groups.
+//!
+//! C header: [`include/net/genetlink.h`](srctree/include/net/genetlink.h)
+#![cfg(CONFIG_NET)]
+
+use kernel::{
+ alloc::{self, AllocError},
+ error::to_result,
+ prelude::*,
+ transmute::AsBytes,
+ types::Opaque,
+ ThisModule,
+};
+
+use core::{
+ mem::ManuallyDrop,
+ ptr::NonNull, //
+};
+
+/// The default netlink message size.
+pub const GENLMSG_DEFAULT_SIZE: usize = bindings::GENLMSG_DEFAULT_SIZE;
+
+/// A wrapper around `struct sk_buff` for generic netlink messages.
+///
+/// This type is intended to be specific for buffers used with netlink only, and other usecases for
+/// `struct sk_buff` are out-of-scope for this abstraction.
+///
+/// # Invariants
+///
+/// The pointer has ownership over a valid `sk_buff`.
+pub struct NetlinkSkBuff {
+ skb: NonNull<kernel::bindings::sk_buff>,
+}
+
+impl NetlinkSkBuff {
+ /// Creates a new `NetlinkSkBuff` with the given size.
+ pub fn new(size: usize, flags: alloc::Flags) -> Result<NetlinkSkBuff, AllocError> {
+ // SAFETY: `genlmsg_new` only requires its arguments to be valid integers.
+ let skb = unsafe { bindings::genlmsg_new(size, flags.as_raw()) };
+ let skb = NonNull::new(skb).ok_or(AllocError)?;
+ Ok(NetlinkSkBuff { skb })
+ }
+
+ /// Puts a generic netlink header into the `NetlinkSkBuff`.
+ pub fn genlmsg_put(
+ self,
+ portid: u32,
+ seq: u32,
+ family: &'static Family,
+ cmd: u8,
+ ) -> Result<GenlMsg, AllocError> {
+ let skb = self.skb.as_ptr();
+ // SAFETY: The skb and family pointers are valid.
+ let hdr = unsafe { bindings::genlmsg_put(skb, portid, seq, family.as_raw(), 0, cmd) };
+ let hdr = NonNull::new(hdr).ok_or(AllocError)?;
+ Ok(GenlMsg { skb: self, hdr })
+ }
+}
+
+impl Drop for NetlinkSkBuff {
+ fn drop(&mut self) {
+ // SAFETY: We have ownership over the `sk_buff`, so we may free it.
+ unsafe { bindings::nlmsg_free(self.skb.as_ptr()) }
+ }
+}
+
+/// A generic netlink message being constructed.
+///
+/// # Invariants
+///
+/// `hdr` references the header in this netlink message.
+pub struct GenlMsg {
+ skb: NetlinkSkBuff,
+ hdr: NonNull<c_void>,
+}
+
+impl GenlMsg {
+ /// Puts an attribute into the message.
+ #[inline]
+ fn put<T>(&mut self, attrtype: c_int, value: &T) -> Result
+ where
+ T: ?Sized + AsBytes,
+ {
+ let skb = self.skb.skb.as_ptr();
+ let len = size_of_val(value);
+ let ptr = core::ptr::from_ref(value).cast::<c_void>();
+ // SAFETY: `skb` is valid by `NetlinkSkBuff` type invariants, and the provided value is
+ // readable and initialized for its `size_of` bytes.
+ to_result(unsafe { bindings::nla_put(skb, attrtype, len as c_int, ptr) })
+ }
+
+ /// Puts a `u32` attribute into the message.
+ #[inline]
+ pub fn put_u32(&mut self, attrtype: c_int, value: u32) -> Result {
+ self.put(attrtype, &value)
+ }
+
+ /// Puts a string attribute into the message.
+ #[inline]
+ pub fn put_string(&mut self, attrtype: c_int, value: &CStr) -> Result {
+ self.put(attrtype, value.to_bytes_with_nul())
+ }
+
+ /// Puts a flag attribute into the message.
+ #[inline]
+ pub fn put_flag(&mut self, attrtype: c_int) -> Result {
+ let skb = self.skb.skb.as_ptr();
+ // SAFETY: `skb` is valid by `NetlinkSkBuff` type invariants, and a null pointer is valid
+ // when the length is zero.
+ to_result(unsafe { bindings::nla_put(skb, attrtype, 0, core::ptr::null()) })
+ }
+
+ /// Sends the generic netlink message as a multicast message.
+ #[inline]
+ pub fn multicast(
+ self,
+ family: &'static Family,
+ portid: u32,
+ group: u32,
+ flags: alloc::Flags,
+ ) -> Result {
+ let me = ManuallyDrop::new(self);
+ // SAFETY: The `skb` and `family` pointers are valid. We pass ownership of the `skb` to
+ // `genlmsg_multicast` by not dropping `self`.
+ unsafe {
+ bindings::genlmsg_end(me.skb.skb.as_ptr(), me.hdr.as_ptr());
+ to_result(bindings::genlmsg_multicast(
+ family.as_raw(),
+ me.skb.skb.as_ptr(),
+ portid,
+ group,
+ flags.as_raw(),
+ ))
+ }
+ }
+}
+impl Drop for GenlMsg {
+ fn drop(&mut self) {
+ // SAFETY: The `hdr` pointer references the header of this generic netlink message.
+ unsafe { bindings::genlmsg_cancel(self.skb.skb.as_ptr(), self.hdr.as_ptr()) };
+ }
+}
+
+/// Flags for a generic netlink family.
+struct FamilyFlags {
+ /// Whether the family supports network namespaces.
+ netnsok: bool,
+ /// Whether the family supports parallel operations.
+ parallel_ops: bool,
+}
+
+impl FamilyFlags {
+ /// Converts the flags to the bitfield representation used by `genl_family`.
+ const fn into_bitfield(self) -> bindings::__BindgenBitfieldUnit<[u8; 1]> {
+ // The below shifts are verified correct by test_family_flags_bitfield() below.
+ //
+ // Although bindgen generates helpers to change bitfields based on the C headers, these
+ // helpers unfortunately can't be used in const context. Since `Family` needs to be filled
+ // out at build-time, we use this helper instead.
+ let mut bits = 0;
+ if self.netnsok {
+ bits |= 1 << 0;
+ }
+ if self.parallel_ops {
+ bits |= 1 << 1;
+ }
+ // SAFETY: This bitfield is represented as an u8.
+ unsafe { core::mem::transmute::<u8, bindings::__BindgenBitfieldUnit<[u8; 1]>>(bits) }
+ }
+}
+
+/// A generic netlink family.
+#[repr(transparent)]
+pub struct Family {
+ inner: Opaque<bindings::genl_family>,
+}
+
+// SAFETY: The `Family` type is thread safe.
+unsafe impl Sync for Family {}
+
+impl Family {
+ /// Creates a new `Family` instance.
+ pub const fn const_new(
+ module: &ThisModule,
+ name: &[u8],
+ version: u32,
+ mcgrps: &'static [MulticastGroup],
+ ) -> Family {
+ let n_mcgrps = mcgrps.len() as u8;
+ if n_mcgrps as usize != mcgrps.len() {
+ panic!("too many mcgrps");
+ }
+ let mut genl_family = bindings::genl_family {
+ version,
+ _bitfield_1: FamilyFlags {
+ netnsok: true,
+ parallel_ops: true,
+ }
+ .into_bitfield(),
+ module: module.as_ptr(),
+ mcgrps: mcgrps.as_ptr().cast(),
+ n_mcgrps,
+ ..pin_init::zeroed()
+ };
+ if CStr::from_bytes_with_nul(name).is_err() {
+ panic!("genl_family name not nul-terminated");
+ }
+ if genl_family.name.len() < name.len() {
+ panic!("genl_family name too long");
+ }
+ let mut i = 0;
+ while i < name.len() {
+ genl_family.name[i] = name[i];
+ i += 1;
+ }
+ Family {
+ inner: Opaque::new(genl_family),
+ }
+ }
+
+ /// Checks if there are any listeners for the given multicast group.
+ pub fn has_listeners(&self, group: u32) -> bool {
+ // SAFETY: The family and init_net pointers are valid.
+ unsafe {
+ bindings::genl_has_listeners(self.as_raw(), &raw mut bindings::init_net, group) != 0
+ }
+ }
+
+ /// Returns a raw pointer to the underlying `genl_family` structure.
+ pub fn as_raw(&self) -> *mut bindings::genl_family {
+ self.inner.get()
+ }
+}
+
+/// A generic netlink multicast group.
+#[repr(transparent)]
+pub struct MulticastGroup {
+ // No Opaque because fully immutable
+ group: bindings::genl_multicast_group,
+}
+
+// SAFETY: Pure data so thread safe.
+unsafe impl Sync for MulticastGroup {}
+
+impl MulticastGroup {
+ /// Creates a new `MulticastGroup` instance.
+ pub const fn const_new(name: &CStr) -> MulticastGroup {
+ let mut group: bindings::genl_multicast_group = pin_init::zeroed();
+
+ let name = name.to_bytes_with_nul();
+ if group.name.len() < name.len() {
+ panic!("genl_multicast_group name too long");
+ }
+ let mut i = 0;
+ while i < name.len() {
+ group.name[i] = name[i];
+ i += 1;
+ }
+
+ MulticastGroup { group }
+ }
+}
+
+/// A registration of a generic netlink family.
+///
+/// This type represents the registration of a [`Family`]. When an instance of this type is
+/// dropped, its respective generic netlink family will be unregistered from the system.
+///
+/// # Invariants
+///
+/// `self.family` always holds a valid reference to an initialized and registered [`Family`].
+pub struct Registration {
+ family: &'static Family,
+}
+
+impl Family {
+ /// Registers the generic netlink family with the kernel.
+ pub fn register(&'static self) -> Result<Registration> {
+ // SAFETY: `self.as_raw()` is a valid pointer to a `genl_family` struct.
+ // The `genl_family` struct is static, so it will outlive the registration.
+ to_result(unsafe { bindings::genl_register_family(self.as_raw()) })?;
+ Ok(Registration { family: self })
+ }
+}
+
+impl Drop for Registration {
+ fn drop(&mut self) {
+ // SAFETY: `self.family.as_raw()` is a valid pointer to a registered `genl_family` struct.
+ // The `Registration` struct ensures that `genl_unregister_family` is called exactly once
+ // for this family when it goes out of scope.
+ unsafe { bindings::genl_unregister_family(self.family.as_raw()) };
+ }
+}
+
+#[macros::kunit_tests(rust_netlink)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_family_flags_bitfield() {
+ for netnsok in [false, true] {
+ for parallel_ops in [false, true] {
+ let mut b_fam = bindings::genl_family {
+ ..Default::default()
+ };
+ b_fam.set_netnsok(if netnsok { 1 } else { 0 });
+ b_fam.set_parallel_ops(if parallel_ops { 1 } else { 0 });
+
+ let c_bitfield = FamilyFlags {
+ netnsok,
+ parallel_ops,
+ }
+ .into_bitfield();
+
+ // SAFETY: The bit field is stored as u8.
+ let b_val: u8 = unsafe { core::mem::transmute(b_fam._bitfield_1) };
+ // SAFETY: The bit field is stored as u8.
+ let c_val: u8 = unsafe { core::mem::transmute(c_bitfield) };
+ assert_eq!(b_val, c_val);
+ }
+ }
+ }
+}
--
2.54.0.rc0.605.g598a273b03-goog
^ permalink raw reply related
* [PATCH v3 2/4] ynl_gen: generate Rust files from yaml files
From: Alice Ryhl @ 2026-04-15 9:37 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Greg Kroah-Hartman,
Arve Hjønnevåg, Todd Kjos, Christian Brauner,
Carlos Llamas
Cc: linux-kernel, rust-for-linux, netdev, Alice Ryhl
In-Reply-To: <20260415-binder-netlink-v3-0-84be9ba63ee2@google.com>
To generate netlink frames from Rust code easily, generate Rust
libraries with methods for generating different netlink messages as
appropriate.
The new 'rust' type corresponds to a Rust version of the C target
'kernel'. There is no Rust version of the 'uapi' target since Rust code
exports its uapi via C headers - choice of language is opaque to
userspace.
This logic is kept in the existing ynl_gen_c.py file to reuse CodeWriter
and other shared pieces of logic in the existing python file. This has
the disadvantage that the gen_c part of the name is now wrong, as it
also generates Rust. One possible solution to this could be to rename
the file.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
tools/net/ynl/pyynl/ynl_gen_c.py | 139 ++++++++++++++++++++++++++++++++++++++-
tools/net/ynl/ynl-regen.sh | 2 +-
2 files changed, 139 insertions(+), 2 deletions(-)
diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py
index 0e1e486c1185..76b8b2f1ac16 100755
--- a/tools/net/ynl/pyynl/ynl_gen_c.py
+++ b/tools/net/ynl/pyynl/ynl_gen_c.py
@@ -19,6 +19,7 @@ import pathlib
import os
import re
import shutil
+import subprocess
import sys
import tempfile
import yaml as pyyaml
@@ -1744,6 +1745,19 @@ class CodeWriter:
else:
self.p('}' + line)
+ def array_start(self, line=''):
+ if line:
+ line = line + ' '
+ self.p(line + '[')
+ self._ind += 1
+
+ def array_end(self, line=''):
+ if line and line[0] not in {';', ','}:
+ line = ' ' + line
+ self._ind -= 1
+ self._nl = False
+ self.p(']' + line)
+
def write_doc_line(self, doc, indent=True):
words = doc.split()
line = ' *'
@@ -3415,10 +3429,126 @@ def find_kernel_root(full_path):
return full_path, sub_path[:-1]
+def render_rust(family, cw):
+ cw.p('#![allow(unreachable_pub, clippy::wrong_self_convention)]')
+ cw.p('use kernel::netlink::{Family, MulticastGroup};')
+ cw.p('use kernel::prelude::*;')
+ cw.nl()
+
+ family_upper = c_upper(family.ident_name)
+ family_name = f'{family_upper}_NL_FAMILY'
+ mcgrps_name = f'{family_name}_MCGRPS'
+
+ cw.p(f'pub static {family_name}: Family = Family::const_new(')
+ cw._ind += 1
+ cw.p('&crate::THIS_MODULE,')
+ cw.p(f'kernel::uapi::{family.fam_key},')
+ cw.p(f'kernel::uapi::{family.ver_key},')
+ if family.mcgrps['list']:
+ cw.p(f'&{mcgrps_name},')
+ else:
+ cw.p('&[],')
+ cw._ind -= 1
+ cw.p(');')
+ cw.nl()
+
+ if family.mcgrps['list']:
+ cw.array_start(f'static {mcgrps_name}: [MulticastGroup; {len(family.mcgrps["list"])}] = ')
+ for grp in family.mcgrps['list']:
+ cw.p(f'MulticastGroup::const_new(c"{grp["name"]}"),')
+ cw.array_end(';')
+ cw.nl()
+
+ for idx, (op_name, op) in enumerate(item for item in family.msgs.items() if 'event' in item[1]):
+ struct_name = op_name.capitalize()
+
+ if 'doc' in op:
+ doc_lines = op['doc'].strip().split('\n')
+ for line in doc_lines:
+ cw.p(f'/// {line.strip()}')
+
+ cw.block_start(f'pub struct {struct_name}')
+ cw.p('skb: kernel::netlink::GenlMsg,')
+ cw.block_end()
+ cw.nl()
+
+ cw.block_start(f'impl {struct_name}')
+ cw.p('/// Create a new multicast message.')
+ cw.p('pub fn new(')
+ cw._ind += 1
+ cw.p('size: usize,')
+ cw.p('portid: u32,')
+ cw.p('seq: u32,')
+ cw.p('flags: kernel::alloc::Flags,')
+ cw._ind -= 1
+ cw.block_start(') -> Result<Self, kernel::alloc::AllocError>')
+ cw.p(f'const {op.enum_name}: u8 = kernel::uapi::{op.enum_name} as u8;')
+ cw.p('let skb = kernel::netlink::NetlinkSkBuff::new(size, flags)?;')
+ cw.p(f'let skb = skb.genlmsg_put(portid, seq, &{family_name}, {op.enum_name})?;')
+ cw.p('Ok(Self { skb })')
+ cw.block_end()
+ cw.nl()
+
+ grp_idx = 0
+ if 'mcgrp' in op:
+ grp_idx = next(i for i, grp in enumerate(family.mcgrps['list']) if grp['name'] == op['mcgrp'])
+
+ cw.p('/// Broadcast this message.')
+ cw.block_start('pub fn multicast(self, portid: u32, flags: kernel::alloc::Flags) -> Result')
+ cw.p(f'self.skb.multicast(&{family_name}, portid, {grp_idx}, flags)')
+ cw.block_end()
+ cw.nl()
+
+ cw.p('/// Check if this message type has listeners.')
+ cw.block_start('pub fn has_listeners() -> bool')
+ cw.p(f'{family_name}.has_listeners({grp_idx})')
+ cw.block_end()
+
+ attr_set_name = op['attribute-set']
+ attr_set = family.attr_sets[attr_set_name]
+ event_attrs = op['event']['attributes']
+
+ for attr_name in event_attrs:
+ attr = attr_set[attr_name]
+ method_name = attr_name.replace('-', '_')
+
+ if attr.type == 'u32':
+ put_fn = 'put_u32'
+ arg_str = ', val'
+ method_args = '(&mut self, val: u32)'
+ elif attr.type == 'string':
+ put_fn = 'put_string'
+ arg_str = ', val'
+ method_args = '(&mut self, val: &CStr)'
+ elif attr.type == 'flag':
+ put_fn = 'put_flag'
+ arg_str = ''
+ method_args = '(&mut self)'
+ else:
+ put_fn = f'put_{attr.type}'
+ arg_str = ', val'
+ method_args = f'(&mut self, val: {attr.type})'
+
+ cw.nl()
+ if 'doc' in attr.yaml:
+ doc_lines = attr.yaml['doc'].strip().split('\n')
+ for line in doc_lines:
+ cw.p(f'/// {line.strip()}')
+
+ cw.block_start(f'pub fn {method_name}{method_args} -> Result')
+ cw.p(f'const {attr.enum_name}: c_int = kernel::uapi::{attr.enum_name} as c_int;')
+ cw.p(f'self.skb.{put_fn}({attr.enum_name}{arg_str})')
+ cw.block_end()
+
+ cw.block_end()
+ cw.nl()
+ cw.p(' ')
+
+
def main():
parser = argparse.ArgumentParser(description='Netlink simple parsing generator')
parser.add_argument('--mode', dest='mode', type=str, required=True,
- choices=('user', 'kernel', 'uapi'))
+ choices=('user', 'kernel', 'uapi', 'rust'))
parser.add_argument('--spec', dest='spec', type=str, required=True)
parser.add_argument('--header', dest='header', action='store_true', default=None)
parser.add_argument('--source', dest='header', action='store_false')
@@ -3471,6 +3601,13 @@ def main():
render_uapi(parsed, cw)
return
+ if args.mode == 'rust':
+ render_rust(parsed, cw)
+ cw.close_out_file()
+ if args.out_file:
+ subprocess.run(['rustfmt', '--edition', '2021', args.out_file])
+ return
+
hdr_prot = f"_LINUX_{parsed.c_name.upper()}_GEN_H"
if args.header:
cw.p('#ifndef ' + hdr_prot)
diff --git a/tools/net/ynl/ynl-regen.sh b/tools/net/ynl/ynl-regen.sh
index d9809276db98..4f5ceb4fe147 100755
--- a/tools/net/ynl/ynl-regen.sh
+++ b/tools/net/ynl/ynl-regen.sh
@@ -17,7 +17,7 @@ done
KDIR=$(dirname $(dirname $(dirname $(dirname $(realpath $0)))))
pushd ${search:-$KDIR} >>/dev/null
-files=$(git grep --files-with-matches '^/\* YNL-GEN \(kernel\|uapi\|user\)')
+files=$(git grep --files-with-matches '^/\* YNL-GEN \(kernel\|uapi\|user\|rust\)')
for f in $files; do
# params: 0 1 2 3
# $YAML YNL-GEN kernel $mode
--
2.54.0.rc0.605.g598a273b03-goog
^ permalink raw reply related
* [PATCH v3 3/4] rust_binder: add generated netlink.rs file
From: Alice Ryhl @ 2026-04-15 9:37 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Greg Kroah-Hartman,
Arve Hjønnevåg, Todd Kjos, Christian Brauner,
Carlos Llamas
Cc: linux-kernel, rust-for-linux, netdev, Alice Ryhl
In-Reply-To: <20260415-binder-netlink-v3-0-84be9ba63ee2@google.com>
To use netlink from Rust Binder, add a new generated netlink file using
the new script and Documentation/netlink/specs/binder.yaml.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
drivers/android/Kconfig | 2 +-
drivers/android/binder/netlink.rs | 113 +++++++++++++++++++++++++++++
drivers/android/binder/rust_binder_main.rs | 9 ++-
rust/uapi/uapi_helper.h | 1 +
4 files changed, 122 insertions(+), 3 deletions(-)
diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index e2e402c9d175..606a9d07f774 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -16,7 +16,7 @@ config ANDROID_BINDER_IPC
config ANDROID_BINDER_IPC_RUST
bool "Rust version of Android Binder IPC Driver"
- depends on RUST && MMU && !ANDROID_BINDER_IPC
+ depends on RUST && MMU && NET && !ANDROID_BINDER_IPC
help
This enables the Rust implementation of the Binder driver.
diff --git a/drivers/android/binder/netlink.rs b/drivers/android/binder/netlink.rs
new file mode 100644
index 000000000000..2a842c7b1b33
--- /dev/null
+++ b/drivers/android/binder/netlink.rs
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/binder.yaml */
+/* YNL-GEN rust source */
+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
+
+#![allow(unreachable_pub, clippy::wrong_self_convention)]
+use kernel::netlink::{Family, MulticastGroup};
+use kernel::prelude::*;
+
+pub static BINDER_NL_FAMILY: Family = Family::const_new(
+ &crate::THIS_MODULE,
+ kernel::uapi::BINDER_FAMILY_NAME,
+ kernel::uapi::BINDER_FAMILY_VERSION,
+ &BINDER_NL_FAMILY_MCGRPS,
+);
+
+static BINDER_NL_FAMILY_MCGRPS: [MulticastGroup; 1] = [MulticastGroup::const_new(c"report")];
+
+/// A multicast event sent to userspace subscribers to notify them about
+/// binder transaction failures. The generated report provides the full
+/// details of the specific transaction that failed. The intention is for
+/// programs to monitor these events and react to the failures as needed.
+pub struct Report {
+ skb: kernel::netlink::GenlMsg,
+}
+
+impl Report {
+ /// Create a new multicast message.
+ pub fn new(
+ size: usize,
+ portid: u32,
+ seq: u32,
+ flags: kernel::alloc::Flags,
+ ) -> Result<Self, kernel::alloc::AllocError> {
+ const BINDER_CMD_REPORT: u8 = kernel::uapi::BINDER_CMD_REPORT as u8;
+ let skb = kernel::netlink::NetlinkSkBuff::new(size, flags)?;
+ let skb = skb.genlmsg_put(portid, seq, &BINDER_NL_FAMILY, BINDER_CMD_REPORT)?;
+ Ok(Self { skb })
+ }
+
+ /// Broadcast this message.
+ pub fn multicast(self, portid: u32, flags: kernel::alloc::Flags) -> Result {
+ self.skb.multicast(&BINDER_NL_FAMILY, portid, 0, flags)
+ }
+
+ /// Check if this message type has listeners.
+ pub fn has_listeners() -> bool {
+ BINDER_NL_FAMILY.has_listeners(0)
+ }
+
+ /// The enum binder_driver_return_protocol returned to the sender.
+ pub fn error(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_ERROR: c_int = kernel::uapi::BINDER_A_REPORT_ERROR as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_ERROR, val)
+ }
+
+ /// The binder context where the transaction occurred.
+ pub fn context(&mut self, val: &CStr) -> Result {
+ const BINDER_A_REPORT_CONTEXT: c_int = kernel::uapi::BINDER_A_REPORT_CONTEXT as c_int;
+ self.skb.put_string(BINDER_A_REPORT_CONTEXT, val)
+ }
+
+ /// The PID of the sender process.
+ pub fn from_pid(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_FROM_PID: c_int = kernel::uapi::BINDER_A_REPORT_FROM_PID as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_FROM_PID, val)
+ }
+
+ /// The TID of the sender thread.
+ pub fn from_tid(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_FROM_TID: c_int = kernel::uapi::BINDER_A_REPORT_FROM_TID as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_FROM_TID, val)
+ }
+
+ /// The PID of the recipient process. This attribute may not be present
+ /// if the target could not be determined.
+ pub fn to_pid(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_TO_PID: c_int = kernel::uapi::BINDER_A_REPORT_TO_PID as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_TO_PID, val)
+ }
+
+ /// The TID of the recipient thread. This attribute may not be present
+ /// if the target could not be determined.
+ pub fn to_tid(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_TO_TID: c_int = kernel::uapi::BINDER_A_REPORT_TO_TID as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_TO_TID, val)
+ }
+
+ /// When present, indicates the failed transaction is a reply.
+ pub fn is_reply(&mut self) -> Result {
+ const BINDER_A_REPORT_IS_REPLY: c_int = kernel::uapi::BINDER_A_REPORT_IS_REPLY as c_int;
+ self.skb.put_flag(BINDER_A_REPORT_IS_REPLY)
+ }
+
+ /// The bitmask of enum transaction_flags from the transaction.
+ pub fn flags(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_FLAGS: c_int = kernel::uapi::BINDER_A_REPORT_FLAGS as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_FLAGS, val)
+ }
+
+ /// The application-defined code from the transaction.
+ pub fn code(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_CODE: c_int = kernel::uapi::BINDER_A_REPORT_CODE as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_CODE, val)
+ }
+
+ /// The transaction payload size in bytes.
+ pub fn data_size(&mut self, val: u32) -> Result {
+ const BINDER_A_REPORT_DATA_SIZE: c_int = kernel::uapi::BINDER_A_REPORT_DATA_SIZE as c_int;
+ self.skb.put_u32(BINDER_A_REPORT_DATA_SIZE, val)
+ }
+}
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 678e987902aa..9057e5dba7ed 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -36,6 +36,8 @@
mod deferred_close;
mod defs;
mod error;
+#[allow(dead_code)]
+mod netlink;
mod node;
mod page_range;
mod process;
@@ -286,19 +288,22 @@ fn ptr_align(value: usize) -> Option<usize> {
// SAFETY: We call register in `init`.
static BINDER_SHRINKER: Shrinker = unsafe { Shrinker::new() };
-struct BinderModule {}
+struct BinderModule {
+ _netlink: kernel::netlink::Registration,
+}
impl kernel::Module for BinderModule {
fn init(_module: &'static kernel::ThisModule) -> Result<Self> {
// SAFETY: The module initializer never runs twice, so we only call this once.
unsafe { crate::context::CONTEXTS.init() };
+ let netlink = crate::netlink::BINDER_NL_FAMILY.register()?;
BINDER_SHRINKER.register(c"android-binder")?;
// SAFETY: The module is being loaded, so we can initialize binderfs.
unsafe { kernel::error::to_result(binderfs::init_rust_binderfs())? };
- Ok(Self {})
+ Ok(Self { _netlink: netlink })
}
}
diff --git a/rust/uapi/uapi_helper.h b/rust/uapi/uapi_helper.h
index 06d7d1a2e8da..86c7b6b284b0 100644
--- a/rust/uapi/uapi_helper.h
+++ b/rust/uapi/uapi_helper.h
@@ -11,6 +11,7 @@
#include <uapi/drm/nova_drm.h>
#include <uapi/drm/panthor_drm.h>
#include <uapi/linux/android/binder.h>
+#include <uapi/linux/android/binder_netlink.h>
#include <uapi/linux/mdio.h>
#include <uapi/linux/mii.h>
#include <uapi/linux/ethtool.h>
--
2.54.0.rc0.605.g598a273b03-goog
^ permalink raw reply related
* [PATCH v3 4/4] rust_binder: report netlink transactions
From: Alice Ryhl @ 2026-04-15 9:37 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Greg Kroah-Hartman,
Arve Hjønnevåg, Todd Kjos, Christian Brauner,
Carlos Llamas
Cc: linux-kernel, rust-for-linux, netdev, Alice Ryhl
In-Reply-To: <20260415-binder-netlink-v3-0-84be9ba63ee2@google.com>
From: Carlos Llamas <cmllamas@google.com>
The Android Binder driver supports a netlink API that reports
transaction *failures* to a userapce daemon. This allows devices to
monitor processes with many failed transactions so that it can e.g. kill
misbehaving apps.
One very important thing that this monitors is when many oneway messages
are sent to a frozen process, so there is special handling to ensure
this scenario is surfaced over netlink.
Signed-off-by: Carlos Llamas <cmllamas@google.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
drivers/android/binder/rust_binder_main.rs | 1 -
drivers/android/binder/thread.rs | 10 ++++++++
drivers/android/binder/transaction.rs | 40 ++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 9057e5dba7ed..407cda7bd766 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -36,7 +36,6 @@
mod deferred_close;
mod defs;
mod error;
-#[allow(dead_code)]
mod netlink;
mod node;
mod page_range;
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 97d5f31e8fe3..aa4e93a877ac 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -1263,6 +1263,15 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
}
}
+ if info.oneway_spam_suspect {
+ // If this is both a oneway spam suspect and a failure, we report it twice. This is
+ // useful in case the transaction failed with BR_TRANSACTION_PENDING_FROZEN.
+ info.report_netlink(BR_ONEWAY_SPAM_SUSPECT, &self.process.ctx);
+ }
+ if info.reply != 0 {
+ info.report_netlink(info.reply, &self.process.ctx);
+ }
+
Ok(())
}
@@ -1332,6 +1341,7 @@ fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
);
let reply = Err(BR_FAILED_REPLY);
orig.from.deliver_reply(reply, &orig);
+ info.reply = BR_FAILED_REPLY;
err.reply = BR_TRANSACTION_COMPLETE;
err
});
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index 47d5e4d88b07..3fa7091ed8a6 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -3,6 +3,7 @@
// Copyright (C) 2025 Google LLC.
use kernel::{
+ netlink::GENLMSG_DEFAULT_SIZE,
prelude::*,
seq_file::SeqFile,
seq_print,
@@ -17,6 +18,7 @@
allocation::{Allocation, TranslatedFds},
defs::*,
error::{BinderError, BinderResult},
+ netlink::Report,
node::{Node, NodeRef},
process::{Process, ProcessInner},
ptr_align,
@@ -49,6 +51,44 @@ impl TransactionInfo {
pub(crate) fn is_oneway(&self) -> bool {
self.flags & TF_ONE_WAY != 0
}
+
+ pub(crate) fn report_netlink(&self, reply: u32, ctx: &crate::Context) {
+ if let Err(err) = self.report_netlink_inner(reply, ctx) {
+ pr_warn!(
+ "{}:{} netlink report failed: {err:?}\n",
+ self.from_pid,
+ self.from_tid
+ );
+ }
+ }
+
+ fn report_netlink_inner(&self, reply: u32, ctx: &crate::Context) -> kernel::error::Result {
+ if !Report::has_listeners() {
+ return Ok(());
+ }
+ let mut report = Report::new(GENLMSG_DEFAULT_SIZE, 0, 0, GFP_KERNEL)?;
+
+ report.error(reply)?;
+ report.context(&ctx.name)?;
+ report.from_pid(self.from_pid as u32)?;
+ report.from_tid(self.from_tid as u32)?;
+ if self.to_pid != 0 {
+ report.to_pid(self.to_pid as u32)?;
+ }
+ if self.to_tid != 0 {
+ report.to_tid(self.to_tid as u32)?;
+ }
+
+ if self.is_reply {
+ report.is_reply()?;
+ }
+ report.flags(self.flags)?;
+ report.code(self.code)?;
+ report.data_size(self.data_size as u32)?;
+
+ report.multicast(0, GFP_KERNEL)?;
+ Ok(())
+ }
}
use core::mem::offset_of;
--
2.54.0.rc0.605.g598a273b03-goog
^ permalink raw reply related
* [net-next v1 0/3] Add motorcomm 8531s set ds func and 8522 driver
From: Minda Chen @ 2026-04-15 9:26 UTC (permalink / raw)
To: Frank, Andrew Lunn, Heiner Kallweit, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
Cc: linux-kernel, Minda Chen
This patch is for Starfive JHB100 EVB board. JHB100 contain
1 RGMII/RMII and 1 RMII synopsys GMAC cores. In the EVB board, RGMII
interface connect with YT8531s Ethernet PHY. RMII interface connect
with YT8522 ethernet PHY. So patch 1-2 is for RGMII interface
patch 3 is RMII is for RMII interface.
JHB100 is a Starfive new RISC-V SoC for datacenter BMC (BaseBoard
Managent Controller). Similar with Aspeed 27x0.
The JHB100 minimal system upstream is in progress:
https://patchwork.kernel.org/project/linux-riscv/cover/20260403054945.467700-1-changhuang.liang@starfivetech.com/
The patch base in V7.0-rc5
Minda Chen (3):
net: phy: motorcomm: Add yt8531_set_ds() mdio_locked bool parameter
net: motorcomm: phy: set drive strength in 8531s RGMII case
net: phy: motorcomm: Add YT8522 100M RMII PHY support
drivers/net/phy/motorcomm.c | 105 ++++++++++++++++++++++++++++++------
1 file changed, 88 insertions(+), 17 deletions(-)
base-commit: c369299895a591d96745d6492d4888259b004a9e
--
2.17.1
^ permalink raw reply
* [net-next v1 3/3] net: phy: motorcomm: Add YT8522 100M RMII PHY support
From: Minda Chen @ 2026-04-15 9:26 UTC (permalink / raw)
To: Frank, Andrew Lunn, Heiner Kallweit, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
Cc: linux-kernel, Minda Chen
In-Reply-To: <20260415092654.64907-1-minda.chen@starfivetech.com>
Add YT8522 100M RMII ethernet PHY base driver support, including
PHY ID and base config init function.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
drivers/net/phy/motorcomm.c | 49 ++++++++++++++++++++++++++++++++++++-
1 file changed, 48 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index f3129419f7c9..86396424b042 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Motorcomm 8511/8521/8531/8531S/8821 PHY driver.
+ * Motorcomm 8511/8521/8522/8531/8531S/8821 PHY driver.
*
* Author: Peter Geis <pgwipeout@gmail.com>
* Author: Frank <Frank.Sae@motor-comm.com>
@@ -14,6 +14,7 @@
#define PHY_ID_YT8511 0x0000010a
#define PHY_ID_YT8521 0x0000011a
+#define PHY_ID_YT8522 0x4f51e928
#define PHY_ID_YT8531 0x4f51e91b
#define PHY_ID_YT8531S 0x4f51e91a
#define PHY_ID_YT8821 0x4f51ea19
@@ -227,6 +228,13 @@
#define YT8521_LED_100_ON_EN BIT(5)
#define YT8521_LED_10_ON_EN BIT(4)
+#define YT8522_EXTREG_SLEEP_CONTROL 0x2027
+#define YT8522_EN_SLEEP_SW 15
+
+#define YT8522_EXTENDED_COMBO_CTRL 0x4000
+#define YT8522_RXDV_SEL BIT(4)
+#define YT8522_RMII_EN BIT(1)
+
#define YTPHY_MISC_CONFIG_REG 0xA006
#define YTPHY_MCR_FIBER_SPEED_MASK BIT(0)
#define YTPHY_MCR_FIBER_1000BX (0x1 << 0)
@@ -1857,6 +1865,36 @@ static int yt8531_config_init(struct phy_device *phydev)
return 0;
}
+static int yt8522_config_init(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->mdio.dev.of_node;
+ int ret, val;
+
+ val = ytphy_read_ext_with_lock(phydev, YT8522_EXTENDED_COMBO_CTRL);
+ if (val < 0)
+ return val;
+
+ if (val & YT8522_RMII_EN) {
+ val |= YT8522_RXDV_SEL;
+ ret = ytphy_write_ext_with_lock(phydev,
+ YT8522_EXTENDED_COMBO_CTRL,
+ val);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) {
+ /* disable auto sleep */
+ ret = ytphy_modify_ext_with_lock(phydev,
+ YT8522_EXTREG_SLEEP_CONTROL,
+ YT8522_EN_SLEEP_SW, 0);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
/**
* yt8531_link_change_notify() - Adjust the tx clock direction according to
* the current speed and dts config.
@@ -3066,6 +3104,14 @@ static struct phy_driver motorcomm_phy_drvs[] = {
.led_hw_control_set = yt8521_led_hw_control_set,
.led_hw_control_get = yt8521_led_hw_control_get,
},
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_YT8522),
+ .name = "YT8522 100 Megabit Ethernet",
+ .config_aneg = genphy_config_aneg,
+ .config_init = yt8522_config_init,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ },
{
PHY_ID_MATCH_EXACT(PHY_ID_YT8531),
.name = "YT8531 Gigabit Ethernet",
@@ -3126,6 +3172,7 @@ MODULE_LICENSE("GPL");
static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {
{ PHY_ID_MATCH_EXACT(PHY_ID_YT8511) },
{ PHY_ID_MATCH_EXACT(PHY_ID_YT8521) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8522) },
{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531) },
{ PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) },
{ PHY_ID_MATCH_EXACT(PHY_ID_YT8821) },
--
2.17.1
^ permalink raw reply related
* Re: [PATCH] netfilter: xt_realm: fix null-ptr-deref in realm_mt()
From: Florian Westphal @ 2026-04-15 9:44 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Kito Xu (veritas501), phil, davem, edumazet, kuba, pabeni, horms,
jengelh, kaber, netfilter-devel, coreteam, netdev, linux-kernel
In-Reply-To: <ad9aDziQEBR0h3U8@chamomile>
Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> On Wed, Apr 15, 2026 at 11:02:15AM +0200, Florian Westphal wrote:
> > Kito Xu (veritas501) <hxzene@gmail.com> wrote:
> > > realm_mt() unconditionally dereferences skb_dst(skb) without a NULL
> > > check. The xt_realm match registers with .family = NFPROTO_UNSPEC,
> > > making it available to all netfilter protocol families. Through the
> > > nftables compat layer (nft_compat), an unprivileged user inside a
> > > user/net namespace can load this match into a bridge-family chain.
> >
> > I do not think this bug is related to nft_compat.
> > You can also use ebtables setsockopt api to request xt_realm, no?
> >
> > > Fixes: ab4f21e6fb1c ("netfilter: xtables: use NFPROTO_UNSPEC in more extensions")
> >
> > Looks correct. Alternatively we could revert the xt_realm.c change.
> > But I don't have a strong opinion here, patch looks correct.
>
> Maybe partial revert makes sense, since in ab4f21e6fb1c:
>
> - xt_MARK: OK
> - xt_NOTRACK: OK
> - xt_comment: OK
Agree.
> - xt_mac: There is a better way to do this in bridge.
Right.
> - xt_owner, no sockets in bridge.
Output/postrouting maybe?
> - xt_physdev, which makes no sense in bridge, this is for br_netfilter
> only.
Agree.
> - xt_realm (as already mentioned).
> That is, a partial revert of this patch for:
>
> - xt_mac
> - xt_owner
> - xt_physdev
> - xt_realm
I'm ok with that too.
^ permalink raw reply
* Re: [PATCH] netfilter: xt_realm: fix null-ptr-deref in realm_mt()
From: Pablo Neira Ayuso @ 2026-04-15 9:44 UTC (permalink / raw)
To: Florian Westphal
Cc: Kito Xu (veritas501), phil, davem, edumazet, kuba, pabeni, horms,
jengelh, kaber, netfilter-devel, coreteam, netdev, linux-kernel
In-Reply-To: <ad9aDziQEBR0h3U8@chamomile>
On Wed, Apr 15, 2026 at 11:27:43AM +0200, Pablo Neira Ayuso wrote:
> On Wed, Apr 15, 2026 at 11:02:15AM +0200, Florian Westphal wrote:
> > Kito Xu (veritas501) <hxzene@gmail.com> wrote:
> > > realm_mt() unconditionally dereferences skb_dst(skb) without a NULL
> > > check. The xt_realm match registers with .family = NFPROTO_UNSPEC,
> > > making it available to all netfilter protocol families. Through the
> > > nftables compat layer (nft_compat), an unprivileged user inside a
> > > user/net namespace can load this match into a bridge-family chain.
> >
> > I do not think this bug is related to nft_compat.
> > You can also use ebtables setsockopt api to request xt_realm, no?
> >
> > > Fixes: ab4f21e6fb1c ("netfilter: xtables: use NFPROTO_UNSPEC in more extensions")
> >
> > Looks correct. Alternatively we could revert the xt_realm.c change.
> > But I don't have a strong opinion here, patch looks correct.
>
> Maybe partial revert makes sense, since in ab4f21e6fb1c:
>
> - xt_MARK: OK
> - xt_NOTRACK: OK
> - xt_comment: OK
> - xt_mac: There is a better way to do this in bridge.
> - xt_owner, no sockets in bridge.
> - xt_physdev, which makes no sense in bridge, this is for br_netfilter
> only.
> - xt_realm (as already mentioned).
>
> That is, a partial revert of this patch for:
>
> - xt_mac
> - xt_owner
> - xt_physdev
> - xt_realm
"this patch" refers to ab4f21e6fb1c
^ permalink raw reply
* [net-next v1 1/3] net: phy: motorcomm: Add yt8531_set_ds() mdio_locked bool parameter
From: Minda Chen @ 2026-04-15 9:26 UTC (permalink / raw)
To: Frank, Andrew Lunn, Heiner Kallweit, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
Cc: linux-kernel, Minda Chen
In-Reply-To: <20260415092654.64907-1-minda.chen@starfivetech.com>
yt8531_set_ds() default set register with mdio lock and only called
with YT8531 PHY. But new type YT8531s support RGMII and has the same
pin strength setting with YT8531, YT8531s need to call yt8531_set_ds()
setting pin drive strength. But Its config init function
yt8521_config_init() already get the mdio lock with phy_select_page().
Need to add ytphy API without lock in yt8531_set_ds() and a new
bool parameter for YT8531s RGMII case.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
drivers/net/phy/motorcomm.c | 51 +++++++++++++++++++++++++------------
1 file changed, 35 insertions(+), 16 deletions(-)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 4d62f7b36212..35aff1519b4b 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -970,22 +970,26 @@ static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = {
{.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140},
};
-static u32 yt8531_get_ldo_vol(struct phy_device *phydev)
+static u32 yt8531_get_ldo_vol(struct phy_device *phydev, bool mdio_locked)
{
u32 val;
- val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG);
+ if (mdio_locked)
+ val = ytphy_read_ext(phydev, YT8521_CHIP_CONFIG_REG);
+ else
+ val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG);
+
val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val);
return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8;
}
-static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur)
+static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur, bool mdio_locked)
{
u32 vol;
int i;
- vol = yt8531_get_ldo_vol(phydev);
+ vol = yt8531_get_ldo_vol(phydev, mdio_locked);
for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) {
if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur)
return yt8531_ldo_vol[i].ds;
@@ -994,7 +998,7 @@ static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur)
return -EINVAL;
}
-static int yt8531_set_ds(struct phy_device *phydev)
+static int yt8531_set_ds(struct phy_device *phydev, bool mdio_locked)
{
struct device_node *node = phydev->mdio.dev.of_node;
u32 ds_field_low, ds_field_hi, val;
@@ -1002,7 +1006,7 @@ static int yt8531_set_ds(struct phy_device *phydev)
/* set rgmii rx clk driver strength */
if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) {
- ds = yt8531_get_ds_map(phydev, val);
+ ds = yt8531_get_ds_map(phydev, val, mdio_locked);
if (ds < 0)
return dev_err_probe(&phydev->mdio.dev, ds,
"No matching current value was found.\n");
@@ -1010,16 +1014,23 @@ static int yt8531_set_ds(struct phy_device *phydev)
ds = YT8531_RGMII_RX_DS_DEFAULT;
}
- ret = ytphy_modify_ext_with_lock(phydev,
- YTPHY_PAD_DRIVE_STRENGTH_REG,
- YT8531_RGMII_RXC_DS_MASK,
- FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds));
+ if (mdio_locked)
+ ret = ytphy_modify_ext(phydev,
+ YTPHY_PAD_DRIVE_STRENGTH_REG,
+ YT8531_RGMII_RXC_DS_MASK,
+ FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds));
+ else
+ ret = ytphy_modify_ext_with_lock(phydev,
+ YTPHY_PAD_DRIVE_STRENGTH_REG,
+ YT8531_RGMII_RXC_DS_MASK,
+ FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds));
+
if (ret < 0)
return ret;
/* set rgmii rx data driver strength */
if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) {
- ds = yt8531_get_ds_map(phydev, val);
+ ds = yt8531_get_ds_map(phydev, val, mdio_locked);
if (ds < 0)
return dev_err_probe(&phydev->mdio.dev, ds,
"No matching current value was found.\n");
@@ -1033,10 +1044,18 @@ static int yt8531_set_ds(struct phy_device *phydev)
ds_field_low = FIELD_GET(GENMASK(1, 0), ds);
ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low);
- ret = ytphy_modify_ext_with_lock(phydev,
- YTPHY_PAD_DRIVE_STRENGTH_REG,
- YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK,
- ds_field_low | ds_field_hi);
+ if (mdio_locked)
+ ret = ytphy_modify_ext(phydev,
+ YTPHY_PAD_DRIVE_STRENGTH_REG,
+ YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK,
+ ds_field_low | ds_field_hi);
+ else
+ ret = ytphy_modify_ext_with_lock(phydev,
+ YTPHY_PAD_DRIVE_STRENGTH_REG,
+ YT8531_RGMII_RXD_DS_LOW_MASK |
+ YT8531_RGMII_RXD_DS_HI_MASK,
+ ds_field_low | ds_field_hi);
+
if (ret < 0)
return ret;
@@ -1826,7 +1845,7 @@ static int yt8531_config_init(struct phy_device *phydev)
return ret;
}
- ret = yt8531_set_ds(phydev);
+ ret = yt8531_set_ds(phydev, false);
if (ret < 0)
return ret;
--
2.17.1
^ permalink raw reply related
* rust: net: phy: intent for MAE0621A (out-of-tree C -> Rust), request for target guidance
From: wenzhaoliao @ 2026-04-15 9:59 UTC (permalink / raw)
To: andrew, hkallweit1, fujita.tomonori
Cc: linux, tmgross, ojeda, netdev, rust-for-linux
Hello PHY and Rust maintainers,
I am a PhD student working on a C-to-Rust migration tool for systems code.
We would like to validate it in Linux with one concrete PHY target and would
like to confirm direction before posting a larger RFC series.
Scope of this intent:
- Initial target: MAE0621A (currently out-of-tree C driver).
- We do NOT intend to submit a duplicate Rust rewrite of an existing in-tree C PHY driver.
- Goal: evaluate a semi-automatic abstraction completion workflow:
reuse existing Rust PHY abstractions where possible, and add only minimal missing abstractions.
Planned deliverables:
- A gap analysis between MAE0621A C callbacks and current rust/kernel/net/phy.rs coverage.
- A small RFC patch series with minimal abstraction additions (if needed).
- A MAE0621A Rust driver prototype on top of those abstractions for linux-next/rust-next evaluation.
Quality and process commitments:
- Full human review by submitters; we can explain all submitted code.
- Transparent disclosure of tool assistance in cover letters/changelogs.
- Hardware-backed test results and explicit limitations in each posting.
Questions:
1. Is MAE0621A an acceptable first target for this direction?
2. If MAE0621A is not suitable, could you recommend one or two better out-of-tree PHY drivers for a first Rust submission?
3. For review flow, do you prefer:
(a) abstractions-first RFC, then driver, or
(b) minimal abstractions + concrete driver in one RFC series?
If there are no objections, we plan to post an RFC 0/N in about 2 weeks.
Thanks for your guidance.
Best regards,
Liao Wenzhao
Renmin University of China
^ permalink raw reply
* RE: [PATCH net-next v3 5/5] net: phy: Move phy_init_hw() from phy_resume() to __phy_resume()
From: Biju Das @ 2026-04-15 10:00 UTC (permalink / raw)
To: Andrew Lunn, Russell King
Cc: Heiner Kallweit, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Russell King, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, Geert Uytterhoeven,
Prabhakar Mahadev Lad, linux-renesas-soc@vger.kernel.org,
Chris Paterson
In-Reply-To: <TY3PR01MB113462DBCD0E25184E2B1630186252@TY3PR01MB11346.jpnprd01.prod.outlook.com>
Hi Andrew/Russell,
> -----Original Message-----
> From: Biju Das <biju.das.jz@bp.renesas.com>
> Sent: 14 April 2026 19:43
> Subject: RE: [PATCH net-next v3 5/5] net: phy: Move phy_init_hw() from phy_resume() to __phy_resume()
>
> Hi Andrew,
>
> > -----Original Message-----
> > From: Andrew Lunn <andrew@lunn.ch>
> > Sent: 14 April 2026 17:03
> > Subject: Re: [PATCH net-next v3 5/5] net: phy: Move phy_init_hw() from
> > phy_resume() to __phy_resume()
> >
> > On Sun, Apr 12, 2026 at 03:00:27PM +0100, Biju wrote:
> > > From: Biju Das <biju.das.jz@bp.renesas.com>
> > >
> > > Now that redundant locking has been removed from PHY driver
> > > callbacks,
> > > phy_init_hw() can be called with phydev->lock held.
> > >
> > > Many MAC drivers and the phylink framework resume the PHY via
> > > phy_start(), which invokes __phy_resume() directly without going
> > > through phy_resume(). Keeping phy_init_hw() in phy_resume() means it
> > > is not called in this path.
> > >
> > > Move phy_init_hw() into __phy_resume() so that PHY soft reset and
> > > re-initialisation happen unconditionally on every resume, regardless
> > > of which code path triggers it.
> >
> > I would change the order of these patches. First remove the redundant
> > locks. You can then put
> > phy_init_hw() into __phy_resume(), rather than first moving it into
> > phy_resume() and then __phy_resume().
>
> Agreed.
One of my colleague pointed out that this patch may break[1], but we don't have the hardware to
test this IP. According to him
"It does a phy_init_hw(), resetting the PHY, it applies some ethtool settings and then it calls
phy_start(). Since we are calling phy_init_hw() again during phy_start(),we might be undoing the
ethtool settings"
This kind of cleanup/fixing will be in 7.2 cycle, right?
[1] https://elixir.bootlin.com/linux/v7.0/source/drivers/net/ethernet/marvell/mv643xx_eth.c#L2327
Cheers,
Biju
^ permalink raw reply
* Re: [PATCH] gcov: use atomic counter updates to fix concurrent access crashes
From: Andrew Morton @ 2026-04-15 10:19 UTC (permalink / raw)
To: Peter Oberparleiter
Cc: Nathan Chancellor, Konstantin Khorenko, Mikhail Zaslonko,
Nicolas Schier, Masahiro Yamada, Thomas Weißschuh,
Arnd Bergmann, Steffen Klassert, Herbert Xu, linux-kbuild,
linux-kernel, netdev, Pavel Tikhomirov, Vasileios Almpanis,
Jakub Kicinski
In-Reply-To: <9fba075d-9388-483f-818e-6ee3b168f18d@linux.ibm.com>
On Thu, 9 Apr 2026 10:11:24 +0200 Peter Oberparleiter <oberpar@linux.ibm.com> wrote:
> > would be to defer it to 7.2 at this point in the development cycle so
> > that it can have most of a cycle to sit in -next.
>
> Adding Andrew since he typically integrates GCOV patches via his tree,
> and for input on how to handle this patch.
>
> To summarize the situation, this patch:
> - is only effective with GCC + GCOV profiling enabled
> - fixes a run-time crash
> - improves overall GCOV coverage data consistency
> - triggers a number of build errors due to side-effects on GCC constant
> folding and therefore depends on the associated series [1] that fixes
> these build-errors
> - has a non-zero chance to trigger additional build-time errors, e.g.
> in similar macros guarded by arch/config symbols not covered by
> current testing
>
> Given the last point, I agree with Nathan that this patch would benefit
> from additional test coverage to minimize regression risks, e.g. via a
> cycle in -next.
Great, thanks for preempting lots of dumb akpm questions ;)
Agree, I'll stash this in the post-rc1 pile.
^ permalink raw reply
* [PATCH iwl-net] i40e: set supported_extts_flags for rising edge
From: Przemyslaw Korba @ 2026-04-15 10:25 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, Przemyslaw Korba,
Arkadiusz Kubalewski, Aleksandr Loktionov
The i40e driver always supported only rising edge detection, so
advertise PTP_RISING_EDGE, and PTP_STRICT_FLAGS to ensure the
PTP core properly validates user requests.
Fixes: 7c571ac57d9d ("net: ptp: introduce .supported_extts_flags to ptp_clock_info")
Signed-off-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_ptp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
index 7d07c389bb23..c4525bfab09c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
@@ -1344,6 +1344,8 @@ static int i40e_init_pin_config(struct i40e_pf *pf)
pf->ptp_caps.n_ext_ts = 2;
pf->ptp_caps.pps = 1;
pf->ptp_caps.n_per_out = 2;
+ pf->ptp_caps.supported_extts_flags = PTP_RISING_EDGE |
+ PTP_STRICT_FLAGS;
pf->ptp_caps.pin_config = kzalloc_objs(*pf->ptp_caps.pin_config,
pf->ptp_caps.n_pins);
base-commit: d4999456017dd09ff5f7a34e236c471560d8f8e4
--
2.43.0
^ permalink raw reply related
* Re: [RFC PATCH net-next 2/2] selftests: net: add FOU multicast encapsulation resubmit test
From: Breno Leitao @ 2026-04-15 10:25 UTC (permalink / raw)
To: Anton Danilov
Cc: netdev, willemdebruijn.kernel, davem, dsahern, edumazet, kuba,
pabeni, horms, shuah, linux-kselftest
In-Reply-To: <ad7NhoxmrFJAsXe7@dau-home-pc>
On Wed, Apr 15, 2026 at 02:28:06AM +0300, Anton Danilov wrote:
> +send_fou_gre_packets() {
> + local count=$1
> +
> + ip netns exec "$NSENDER" python3 -c "
Having Python code embedded directly in the shell function makes this
difficult to review and maintain. Could you extract the Python script to
a separate file? This would simplify the code to just:
ip netns exec "$NSENDER" python3 my_python_script.py
^ permalink raw reply
* [PATCH] net: ipv4: igmp: add sysctl option to ignore inbound llm_reports
From: Steffen Trumtrar @ 2026-04-15 10:26 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Jonathan Corbet, Shuah Khan, David Ahern
Cc: netdev, linux-doc, linux-kernel, Steffen Trumtrar
Add a new sysctl option 'igmp_link_local_mcast_reports_drop' that allows
dropping inbound IGMP reports for link-local multicast groups in the
224.0.0.X range. This can be used to prevent the local system from
processing IGMP reports for link local multicast groups and therefore
let the kernel still send the own outbound IGMP reports.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
Documentation/networking/ip-sysctl.rst | 12 ++++++++++++
.../networking/net_cachelines/netns_ipv4_sysctl.rst | 1 +
include/net/netns/ipv4.h | 1 +
net/ipv4/af_inet.c | 1 +
net/ipv4/igmp.c | 2 ++
net/ipv4/sysctl_net_ipv4.c | 7 +++++++
6 files changed, 24 insertions(+)
diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index 6921d8594b849..2da4cd6ac7202 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -2306,6 +2306,18 @@ igmp_link_local_mcast_reports - BOOLEAN
Default TRUE
+igmp_link_local_mcast_reports_drop - BOOLEAN
+ Drop inbound IGMP reports for link local multicast groups in
+ the 224.0.0.X range. When enabled, IGMP membership reports for
+ link local multicast addresses are silently dropped without
+ processing.
+ When the kernel gets inbound IGMP reports it stops sending own
+ IGMP reports. With allowing to drop and process the inbound reports,
+ the kernel will not stop sending the own reports, even when IGMP
+ reports from other hosts are seen on the network.
+
+ Default FALSE
+
Alexey Kuznetsov.
kuznet@ms2.inr.ac.ru
diff --git a/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst b/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
index beaf1880a19bf..703afe2ba063b 100644
--- a/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
+++ b/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
@@ -140,6 +140,7 @@ int sysctl_udp_rmem_min
u8 sysctl_fib_notify_on_flag_change
u8 sysctl_udp_l3mdev_accept
u8 sysctl_igmp_llm_reports
+u8 sysctl_igmp_llm_reports_drop
int sysctl_igmp_max_memberships
int sysctl_igmp_max_msf
int sysctl_igmp_qrv
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 8e971c7bf1646..1453f825ffd4d 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -258,6 +258,7 @@ struct netns_ipv4 {
u8 sysctl_igmp_llm_reports;
int sysctl_igmp_max_memberships;
int sysctl_igmp_max_msf;
+ u8 sysctl_igmp_llm_reports_drop;
int sysctl_igmp_qrv;
struct ping_group_range ping_group_range;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c7731e300a442..b8f96a5d8afdc 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1825,6 +1825,7 @@ static __net_init int inet_init_net(struct net *net)
net->ipv4.sysctl_igmp_max_msf = 10;
/* IGMP reports for link-local multicast groups are enabled by default */
net->ipv4.sysctl_igmp_llm_reports = 1;
+ net->ipv4.sysctl_igmp_llm_reports_drop = 0;
net->ipv4.sysctl_igmp_qrv = 2;
net->ipv4.sysctl_fib_notify_on_flag_change = 0;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index a674fb44ec25b..3a4932e4108bd 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -931,6 +931,8 @@ static bool igmp_heard_report(struct in_device *in_dev, __be32 group)
if (ipv4_is_local_multicast(group) &&
!READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))
return false;
+ if (READ_ONCE(net->ipv4.sysctl_igmp_llm_reports_drop))
+ return true;
rcu_read_lock();
for_each_pmc_rcu(in_dev, im) {
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 5654cc9c8a0b9..24dde84d289e4 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -948,6 +948,13 @@ static struct ctl_table ipv4_net_table[] = {
.mode = 0644,
.proc_handler = proc_dou8vec_minmax,
},
+ {
+ .procname = "igmp_link_local_mcast_reports_drop",
+ .data = &init_net.ipv4.sysctl_igmp_llm_reports_drop,
+ .maxlen = sizeof(u8),
+ .mode = 0644,
+ .proc_handler = proc_dou8vec_minmax,
+ },
{
.procname = "igmp_max_memberships",
.data = &init_net.ipv4.sysctl_igmp_max_memberships,
---
base-commit: 028ef9c96e96197026887c0f092424679298aae8
change-id: 20260415-v7-0-topic-igmp-llm-drop-e4c13dbf17cc
Best regards,
--
Steffen Trumtrar <s.trumtrar@pengutronix.de>
^ permalink raw reply related
* Re: [PATCH v2] vsock/virtio: fix accept queue count leak on transport mismatch
From: Stefano Garzarella @ 2026-04-15 10:27 UTC (permalink / raw)
To: Dudu Lu; +Cc: netdev, stefanha, mst, jasowang
In-Reply-To: <20260413131409.19022-1-phx0fer@gmail.com>
On Mon, Apr 13, 2026 at 09:14:09PM +0800, Dudu Lu wrote:
>virtio_transport_recv_listen() calls sk_acceptq_added() before
>vsock_assign_transport(). If vsock_assign_transport() fails or
>selects a different transport, the error path returns without
>calling sk_acceptq_removed(), permanently incrementing
>sk_ack_backlog.
>
>After approximately backlog+1 such failures, sk_acceptq_is_full()
>returns true, causing the listener to reject all new connections.
>
>Fix by moving sk_acceptq_added() to after the transport validation,
>matching the pattern used by vmci_transport and hyperv_transport.
>
>Fixes: c0cfa2d8a788 ("vsock: add multi-transports support")
>Signed-off-by: Dudu Lu <phx0fer@gmail.com>
>---
> net/vmw_vsock/virtio_transport_common.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
^ permalink raw reply
* Re: [PATCH v2] vsock/virtio: fix accept queue count leak on transport mismatch
From: Michael S. Tsirkin @ 2026-04-15 10:28 UTC (permalink / raw)
To: Dudu Lu; +Cc: netdev, stefanha, sgarzare, jasowang
In-Reply-To: <20260413131409.19022-1-phx0fer@gmail.com>
On Mon, Apr 13, 2026 at 09:14:09PM +0800, Dudu Lu wrote:
> virtio_transport_recv_listen() calls sk_acceptq_added() before
> vsock_assign_transport(). If vsock_assign_transport() fails or
> selects a different transport, the error path returns without
> calling sk_acceptq_removed(), permanently incrementing
> sk_ack_backlog.
>
> After approximately backlog+1 such failures, sk_acceptq_is_full()
> returns true, causing the listener to reject all new connections.
>
> Fix by moving sk_acceptq_added() to after the transport validation,
> matching the pattern used by vmci_transport and hyperv_transport.
>
> Fixes: c0cfa2d8a788 ("vsock: add multi-transports support")
> Signed-off-by: Dudu Lu <phx0fer@gmail.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
> ---
> net/vmw_vsock/virtio_transport_common.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
> index 8a9fb23c6e85..e01d983488e5 100644
> --- a/net/vmw_vsock/virtio_transport_common.c
> +++ b/net/vmw_vsock/virtio_transport_common.c
> @@ -1560,8 +1560,6 @@ virtio_transport_recv_listen(struct sock *sk, struct sk_buff *skb,
> return -ENOMEM;
> }
>
> - sk_acceptq_added(sk);
> -
> lock_sock_nested(child, SINGLE_DEPTH_NESTING);
>
> child->sk_state = TCP_ESTABLISHED;
> @@ -1583,6 +1581,7 @@ virtio_transport_recv_listen(struct sock *sk, struct sk_buff *skb,
> return ret;
> }
>
> + sk_acceptq_added(sk);
> if (virtio_transport_space_update(child, skb))
> child->sk_write_space(child);
>
> --
> 2.39.3 (Apple Git-145)
^ permalink raw reply
* Re: [PATCH] rose: Fix rose_find_socket() returning without sock_hold()
From: kernel test robot @ 2026-04-15 10:36 UTC (permalink / raw)
To: Dudu Lu, netdev; +Cc: oe-kbuild-all, davem, edumazet, kuba, pabeni, Dudu Lu
In-Reply-To: <20260413090420.79932-1-phx0fer@gmail.com>
Hi Dudu,
kernel test robot noticed the following build errors:
[auto build test ERROR on net/main]
[also build test ERROR on net-next/main linus/master horms-ipvs/master v7.0 next-20260414]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Dudu-Lu/rose-Fix-rose_find_socket-returning-without-sock_hold/20260414-194608
base: net/main
patch link: https://lore.kernel.org/r/20260413090420.79932-1-phx0fer%40gmail.com
patch subject: [PATCH] rose: Fix rose_find_socket() returning without sock_hold()
config: i386-randconfig-141-20260415 (https://download.01.org/0day-ci/archive/20260415/202604151819.celyrwKo-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
smatch: v0.5.0-9007-gcf3ea02b
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260415/202604151819.celyrwKo-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604151819.celyrwKo-lkp@intel.com/
All errors (new ones prefixed by >>):
>> net/rose/af_rose.c:1:9: error: expected identifier or '(' before 'if'
1 | if (s)
| ^~
vim +1 net/rose/af_rose.c
> 1 if (s)
2 sock_hold(s);// SPDX-License-Identifier: GPL-2.0-or-later
3 /*
4 *
5 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
6 * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
7 * Copyright (C) Terry Dawson VK2KTJ (terry@animats.net)
8 * Copyright (C) Tomi Manninen OH2BNS (oh2bns@sral.fi)
9 */
10
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH net] hv_sock: Report EOF instead of -EIO for FIN
From: Stefano Garzarella @ 2026-04-15 10:38 UTC (permalink / raw)
To: Dexuan Cui
Cc: kys, haiyangz, wei.liu, longli, davem, edumazet, kuba, pabeni,
horms, niuxuewei.nxw, linux-hyperv, virtualization, netdev,
linux-kernel, stable, Ben Hillis, Mitchell Levy
In-Reply-To: <20260414234316.711578-1-decui@microsoft.com>
On Tue, Apr 14, 2026 at 04:43:16PM -0700, Dexuan Cui wrote:
>Commit f0c5827d07cb unluckily causes a regression for the FIN packet,
>and the final read syscall gets an error rather than 0.
>
>Ideally, we would want to fix hvs_channel_readable_payload() so that it
>could return 0 in the FIN scenario, but it's not good for the hv_sock
>driver to use the VMBus ringbuffer's cached priv_read_index, which is
>internal data in the VMBus driver.
>
>Fix the regression in hv_sock by returning 0 rather than -EIO.
>
>Fixes: f0c5827d07cb ("hv_sock: Return the readable bytes in hvs_stream_has_data()")
>Cc: stable@vger.kernel.org
>Reported-by: Ben Hillis <Ben.Hillis@microsoft.com>
>Reported-by: Mitchell Levy <levymitchell0@gmail.com>
>Signed-off-by: Dexuan Cui <decui@microsoft.com>
>---
> net/vmw_vsock/hyperv_transport.c | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
>diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
>index 069386a74557..63d3549125be 100644
>--- a/net/vmw_vsock/hyperv_transport.c
>+++ b/net/vmw_vsock/hyperv_transport.c
>@@ -703,8 +703,22 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk)
> switch (hvs_channel_readable_payload(hvs->chan)) {
> case 1:
> need_refill = !hvs->recv_desc;
>- if (!need_refill)
>- return -EIO;
>+ if (!need_refill) {
Can we drop `need_refill` entirly and just check `hvs->recv_desc` here?
Mainly because now the comment we are adding is confusing me about what
`need_refill` means.
The rest LGTM.
Thanks,
Stefano
>+ /* Here hvs->recv_data_len is 0, so hvs->recv_desc must
>+ * be NULL unless it points to the 0-byte-payload FIN
>+ * packet: see hvs_update_recv_data().
>+ *
>+ * Here all the payload has been dequeued, but
>+ * hvs_channel_readable_payload() still returns 1,
>+ * because the VMBus ringbuffer's read_index is not
>+ * updated for the FIN packet: hvs_stream_dequeue() ->
>+ * hv_pkt_iter_next() updates the cached priv_read_index
>+ * but has no opportunity to update the read_index in
>+ * hv_pkt_iter_close() as hvs_stream_has_data() returns
>+ * 0 for the FIN packet, so it won't get dequeued.
>+ */
>+ return 0;
>+ }
>
> hvs->recv_desc = hv_pkt_iter_first(hvs->chan);
> if (!hvs->recv_desc)
>--
>2.49.0
>
>
^ permalink raw reply
* Re: [PATCH v3 net] vsock: fix buffer size clamping order
From: Stefano Garzarella @ 2026-04-15 10:42 UTC (permalink / raw)
To: Michal Luczaj
Cc: Norbert Szetei, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, virtualization, netdev, linux-kernel
In-Reply-To: <e965ff22-37b2-406d-b885-e2736e84c0f3@rbox.co>
On Tue, Apr 14, 2026 at 04:22:04PM +0200, Michal Luczaj wrote:
>On 4/9/26 18:34, Norbert Szetei wrote:
>> In vsock_update_buffer_size(), the buffer size was being clamped to the
>> maximum first, and then to the minimum. If a user sets a minimum buffer
>> size larger than the maximum, the minimum check overrides the maximum
>> check, inverting the constraint.
>>
>> This breaks the intended socket memory boundaries by allowing the
>> vsk->buffer_size to grow beyond the configured vsk->buffer_max_size.
>>
>> Fix this by checking the minimum first, and then the maximum. This
>> ensures the buffer size never exceeds the buffer_max_size.
>
>Something may be missing. After adding another ioctl to your reproducer, I
>still see crashes.
>
> SYSCHK(setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MIN_SIZE, &min,
> sizeof(min)));
>+ SYSCHK(setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE, &min,
>+ sizeof(min)));
> }
>
>[*] Setting buffer_min_size to 0x400000000.
>[socket][0] sending...
>
>refcount_t: saturated; leaking memory.
>WARNING: lib/refcount.c:22 at refcount_warn_saturate+0x7d/0xb0, CPU#2:
>a.out/1478
>...
>refcount_t: underflow; use-after-free.
>WARNING: lib/refcount.c:28 at refcount_warn_saturate+0x50/0xb0, CPU#12:
>kworker/12:0/80
>Workqueue: vsock-loopback vsock_loopback_work
>...
>
yeah, I pointed out the same during the bug discussion
(https://lore.kernel.org/netdev/acuKUpZQq6z1DY_n@sgarzare-redhat/) and
suggested to add a sysctl or reuse net.core.wmem_max/rmem_max
(https://lore.kernel.org/netdev/adYKERRYwzMIhZAl@sgarzare-redhat/)
Thanks,
Stefano
^ permalink raw reply
* [net-next v1 2/3] net: motorcomm: phy: set drive strength in 8531s RGMII case
From: Minda Chen @ 2026-04-15 9:26 UTC (permalink / raw)
To: Frank, Andrew Lunn, Heiner Kallweit, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
Cc: linux-kernel, Minda Chen
In-Reply-To: <20260415092654.64907-1-minda.chen@starfivetech.com>
Set RXD and RX CLK pin drive strength while in 8531s RGMII
case.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
drivers/net/phy/motorcomm.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 35aff1519b4b..f3129419f7c9 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -1714,6 +1714,11 @@ static int yt8521_config_init(struct phy_device *phydev)
if (ret < 0)
goto err_restore_page;
}
+
+ if (phydev->drv->phy_id == PHY_ID_YT8531S &&
+ phydev->interface != PHY_INTERFACE_MODE_SGMII)
+ ret = yt8531_set_ds(phydev, true);
+
err_restore_page:
return phy_restore_page(phydev, old_page, ret);
}
--
2.17.1
^ 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