Linux Documentation
 help / color / mirror / Atom feed
* [PATCH 1/5] io_uring/zcrx: notify user when out of buffers
From: Clément Léger @ 2026-04-22 11:25 UTC (permalink / raw)
  To: io-uring, Pavel Begunkov, Jens Axboe
  Cc: linux-doc, linux-kernel, linux-kselftest, netdev, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Jonathan Corbet, Shuah Khan, Vishwanath Seshagiri,
	Vishwanath Seshagiri
In-Reply-To: <20260422112522.3316660-1-cleger@meta.com>

From: Pavel Begunkov <asml.silence@gmail.com>

There are currently no easy ways for the user to know if zcrx is out of
buffers and page pool fails to allocate. Add uapi for zcrx to communicate
it back.

It's implemented as a separate CQE, which for now is posted to the creator
ctx. To use it, on registration the user space needs to pass an instance
of struct zcrx_notification_desc, which tells the kernel the user_data
for resulting CQEs and which event types are expected / allowed.

When an allowed event happens, zcrx will post a CQE containing the
specified user_data, and lower bits of cqe->res will be set to the event
mask. Before the kernel could post another notification of the given
type, the user needs to acknowledge that it processed the previous one
by issuing IORING_REGISTER_ZCRX_CTRL with ZCRX_CTRL_ARM_NOTIFICATION.

The only notification type the patch implements yet is
ZCRX_NOTIF_NO_BUFFERS. Next commit adds copy fallback signaling.

Co-developed-by: Vishwanath Seshagiri <vishs@meta.com>
Signed-off-by: Vishwanath Seshagiri <vishs@meta.com>
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 include/uapi/linux/io_uring/zcrx.h | 22 ++++++-
 io_uring/zcrx.c                    | 98 +++++++++++++++++++++++++++++-
 io_uring/zcrx.h                    | 11 +++-
 3 files changed, 128 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/io_uring/zcrx.h b/include/uapi/linux/io_uring/zcrx.h
index 5ce02c7a6096..b8596d7d47b6 100644
--- a/include/uapi/linux/io_uring/zcrx.h
+++ b/include/uapi/linux/io_uring/zcrx.h
@@ -65,6 +65,18 @@ enum zcrx_features {
 	 * value in struct io_uring_zcrx_ifq_reg::rx_buf_len.
 	 */
 	ZCRX_FEATURE_RX_PAGE_SIZE	= 1 << 0,
+	ZCRX_FEATURE_NOTIFICATION	= 1 << 1,
+};
+
+enum zcrx_notification_type {
+	ZCRX_NOTIF_NO_BUFFERS = 1 << 0,
+};
+
+struct zcrx_notification_desc {
+	__u64	user_data;
+	__u32	type_mask;
+	__u32	__resv1;
+	__u64	__resv2[10];
 };
 
 /*
@@ -82,12 +94,14 @@ struct io_uring_zcrx_ifq_reg {
 	struct io_uring_zcrx_offsets offsets;
 	__u32	zcrx_id;
 	__u32	rx_buf_len;
-	__u64	__resv[3];
+	__u64	notif_desc; /* see struct zcrx_notification_desc */
+	__u64	__resv[2];
 };
 
 enum zcrx_ctrl_op {
 	ZCRX_CTRL_FLUSH_RQ,
 	ZCRX_CTRL_EXPORT,
+	ZCRX_CTRL_ARM_NOTIFICATION,
 
 	__ZCRX_CTRL_LAST,
 };
@@ -101,6 +115,11 @@ struct zcrx_ctrl_export {
 	__u32 		__resv1[11];
 };
 
+struct zcrx_ctrl_arm_notif {
+	__u32		type_mask;
+	__u32		__resv[11];
+};
+
 struct zcrx_ctrl {
 	__u32	zcrx_id;
 	__u32	op; /* see enum zcrx_ctrl_op */
@@ -109,6 +128,7 @@ struct zcrx_ctrl {
 	union {
 		struct zcrx_ctrl_export		zc_export;
 		struct zcrx_ctrl_flush_rq	zc_flush;
+		struct zcrx_ctrl_arm_notif	zc_arm_notif;
 	};
 };
 
diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index 9a83d7eb4210..35ca28cb6583 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -44,6 +44,16 @@ static inline struct io_zcrx_area *io_zcrx_iov_to_area(const struct net_iov *nio
 	return container_of(owner, struct io_zcrx_area, nia);
 }
 
+static bool zcrx_set_ring_ctx(struct io_zcrx_ifq *zcrx, struct io_ring_ctx *ctx)
+{
+	guard(spinlock_bh)(&zcrx->ctx_lock);
+	if (zcrx->master_ctx)
+		return false;
+	percpu_ref_get(&ctx->refs);
+	zcrx->master_ctx = ctx;
+	return true;
+}
+
 static inline struct page *io_zcrx_iov_page(const struct net_iov *niov)
 {
 	struct io_zcrx_area *area = io_zcrx_iov_to_area(niov);
@@ -531,6 +541,7 @@ static struct io_zcrx_ifq *io_zcrx_ifq_alloc(struct io_ring_ctx *ctx)
 
 	ifq->if_rxq = -1;
 	spin_lock_init(&ifq->rq.lock);
+	spin_lock_init(&ifq->ctx_lock);
 	mutex_init(&ifq->pp_lock);
 	refcount_set(&ifq->refs, 1);
 	refcount_set(&ifq->user_refs, 1);
@@ -585,6 +596,11 @@ static void io_zcrx_ifq_free(struct io_zcrx_ifq *ifq)
 	if (ifq->dev)
 		put_device(ifq->dev);
 
+	scoped_guard(spinlock_bh, &ifq->ctx_lock) {
+		if (ifq->master_ctx)
+			percpu_ref_put(&ifq->master_ctx->refs);
+	}
+
 	io_free_rbuf_ring(ifq);
 	mutex_destroy(&ifq->pp_lock);
 	kfree(ifq);
@@ -738,6 +754,8 @@ static int import_zcrx(struct io_ring_ctx *ctx,
 		return -EINVAL;
 	if (reg->if_rxq || reg->rq_entries || reg->area_ptr || reg->region_ptr)
 		return -EINVAL;
+	if (reg->notif_desc)
+		return -EINVAL;
 	if (reg->flags & ~ZCRX_REG_IMPORT)
 		return -EINVAL;
 
@@ -826,6 +844,7 @@ static int zcrx_register_netdev(struct io_zcrx_ifq *ifq,
 int io_register_zcrx(struct io_ring_ctx *ctx,
 		     struct io_uring_zcrx_ifq_reg __user *arg)
 {
+	struct zcrx_notification_desc notif;
 	struct io_uring_zcrx_area_reg area;
 	struct io_uring_zcrx_ifq_reg reg;
 	struct io_uring_region_desc rd;
@@ -869,10 +888,22 @@ int io_register_zcrx(struct io_ring_ctx *ctx,
 	if (copy_from_user(&area, u64_to_user_ptr(reg.area_ptr), sizeof(area)))
 		return -EFAULT;
 
+	memset(&notif, 0, sizeof(notif));
+	if (reg.notif_desc && copy_from_user(&notif, u64_to_user_ptr(reg.notif_desc),
+					     sizeof(notif)))
+		return -EFAULT;
+	if (notif.type_mask & ~ZCRX_NOTIF_TYPE_MASK)
+		return -EINVAL;
+	if (notif.__resv1 || !mem_is_zero(&notif.__resv2, sizeof(notif.__resv2)))
+		return -EINVAL;
+
 	ifq = io_zcrx_ifq_alloc(ctx);
 	if (!ifq)
 		return -ENOMEM;
 
+	ifq->notif_data = notif.user_data;
+	ifq->allowed_notif_mask = notif.type_mask;
+
 	if (ctx->user) {
 		get_uid(ctx->user);
 		ifq->user = ctx->user;
@@ -923,6 +954,9 @@ int io_register_zcrx(struct io_ring_ctx *ctx,
 		ret = -EFAULT;
 		goto err;
 	}
+
+	if (notif.type_mask)
+		zcrx_set_ring_ctx(ifq, ctx);
 	return 0;
 err:
 	scoped_guard(mutex, &ctx->mmap_lock)
@@ -1089,6 +1123,46 @@ static unsigned io_zcrx_refill_slow(struct page_pool *pp, struct io_zcrx_ifq *if
 	return allocated;
 }
 
+static void zcrx_notif_tw(struct io_tw_req tw_req, io_tw_token_t tw)
+{
+	struct io_kiocb *req = tw_req.req;
+	struct io_ring_ctx *ctx = req->ctx;
+
+	io_post_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, 0);
+	percpu_ref_put(&ctx->refs);
+	kfree_rcu(req, rcu_head);
+}
+
+static void zcrx_send_notif(struct io_zcrx_ifq *ifq, u32 type_mask)
+{
+	gfp_t gfp = GFP_ATOMIC | __GFP_NOWARN | __GFP_ZERO;
+	struct io_kiocb *req;
+
+	if (!(type_mask & ifq->allowed_notif_mask))
+		return;
+
+	guard(spinlock_bh)(&ifq->ctx_lock);
+	if (!ifq->master_ctx)
+		return;
+	if (type_mask & ifq->fired_notifs)
+		return;
+
+	req = kmem_cache_alloc(req_cachep, gfp);
+	if (unlikely(!req))
+		return;
+
+	ifq->fired_notifs |= type_mask;
+
+	req->opcode = IORING_OP_NOP;
+	req->cqe.user_data = ifq->notif_data;
+	req->cqe.res = type_mask;
+	req->ctx = ifq->master_ctx;
+	percpu_ref_get(&req->ctx->refs);
+	req->tctx = NULL;
+	req->io_task_work.func = zcrx_notif_tw;
+	io_req_task_work_add(req);
+}
+
 static netmem_ref io_pp_zc_alloc_netmems(struct page_pool *pp, gfp_t gfp)
 {
 	struct io_zcrx_ifq *ifq = io_pp_to_ifq(pp);
@@ -1105,8 +1179,10 @@ static netmem_ref io_pp_zc_alloc_netmems(struct page_pool *pp, gfp_t gfp)
 		goto out_return;
 
 	allocated = io_zcrx_refill_slow(pp, ifq, netmems, to_alloc);
-	if (!allocated)
+	if (!allocated) {
+		zcrx_send_notif(ifq, ZCRX_NOTIF_NO_BUFFERS);
 		return 0;
+	}
 out_return:
 	zcrx_sync_for_device(pp, ifq, netmems, allocated);
 	allocated--;
@@ -1255,12 +1331,30 @@ static int zcrx_flush_rq(struct io_ring_ctx *ctx, struct io_zcrx_ifq *zcrx,
 	return 0;
 }
 
+static int zcrx_arm_notif(struct io_ring_ctx *ctx, struct io_zcrx_ifq *zcrx,
+			  struct zcrx_ctrl *ctrl)
+{
+	const struct zcrx_ctrl_arm_notif *an = &ctrl->zc_arm_notif;
+
+	if (an->type_mask & ~ZCRX_NOTIF_TYPE_MASK)
+		return -EINVAL;
+	if (!mem_is_zero(&an->__resv, sizeof(an->__resv)))
+		return -EINVAL;
+
+	guard(spinlock_bh)(&zcrx->ctx_lock);
+	if (an->type_mask & ~zcrx->fired_notifs)
+		return -EINVAL;
+	zcrx->fired_notifs &= ~an->type_mask;
+	return 0;
+}
+
 int io_zcrx_ctrl(struct io_ring_ctx *ctx, void __user *arg, unsigned nr_args)
 {
 	struct zcrx_ctrl ctrl;
 	struct io_zcrx_ifq *zcrx;
 
 	BUILD_BUG_ON(sizeof(ctrl.zc_export) != sizeof(ctrl.zc_flush));
+	BUILD_BUG_ON(sizeof(ctrl.zc_export) != sizeof(ctrl.zc_arm_notif));
 
 	if (nr_args)
 		return -EINVAL;
@@ -1278,6 +1372,8 @@ int io_zcrx_ctrl(struct io_ring_ctx *ctx, void __user *arg, unsigned nr_args)
 		return zcrx_flush_rq(ctx, zcrx, &ctrl);
 	case ZCRX_CTRL_EXPORT:
 		return zcrx_export(ctx, zcrx, &ctrl, arg);
+	case ZCRX_CTRL_ARM_NOTIFICATION:
+		return zcrx_arm_notif(ctx, zcrx, &ctrl);
 	}
 
 	return -EOPNOTSUPP;
diff --git a/io_uring/zcrx.h b/io_uring/zcrx.h
index 75e0a4e6ef6e..3ddebed06d57 100644
--- a/io_uring/zcrx.h
+++ b/io_uring/zcrx.h
@@ -9,7 +9,9 @@
 #include <net/net_trackers.h>
 
 #define ZCRX_SUPPORTED_REG_FLAGS	(ZCRX_REG_IMPORT | ZCRX_REG_NODEV)
-#define ZCRX_FEATURES			(ZCRX_FEATURE_RX_PAGE_SIZE)
+#define ZCRX_FEATURES			(ZCRX_FEATURE_RX_PAGE_SIZE |\
+					 ZCRX_FEATURE_NOTIFICATION)
+#define ZCRX_NOTIF_TYPE_MASK		(ZCRX_NOTIF_NO_BUFFERS)
 
 struct io_zcrx_mem {
 	unsigned long			size;
@@ -72,6 +74,13 @@ struct io_zcrx_ifq {
 	 */
 	struct mutex			pp_lock;
 	struct io_mapped_region		rq_region;
+
+	/* Locks the access to notifification context data */
+	spinlock_t			ctx_lock;
+	struct io_ring_ctx		*master_ctx;
+	u32				allowed_notif_mask;
+	u32				fired_notifs;
+	u64				notif_data;
 };
 
 #if defined(CONFIG_IO_URING_ZCRX)
-- 
2.52.0


^ permalink raw reply related

* [PATCH 2/5] io_uring/zcrx: notify user on frag copy fallback
From: Clément Léger @ 2026-04-22 11:25 UTC (permalink / raw)
  To: io-uring, Pavel Begunkov, Jens Axboe
  Cc: Clément Léger, linux-doc, linux-kernel, linux-kselftest,
	netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	Vishwanath Seshagiri
In-Reply-To: <20260422112522.3316660-1-cleger@meta.com>

Add a ZCRX_NOTIF_COPY notification type to signal userspace when a
received fragment could not be delivered using zero-copy and was
instead copied into a buffer.

Signed-off-by: Clément Léger <cleger@meta.com>
---
 include/uapi/linux/io_uring/zcrx.h | 1 +
 io_uring/zcrx.c                    | 7 ++++++-
 io_uring/zcrx.h                    | 3 ++-
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/io_uring/zcrx.h b/include/uapi/linux/io_uring/zcrx.h
index b8596d7d47b6..e0c0079626c8 100644
--- a/include/uapi/linux/io_uring/zcrx.h
+++ b/include/uapi/linux/io_uring/zcrx.h
@@ -70,6 +70,7 @@ enum zcrx_features {
 
 enum zcrx_notification_type {
 	ZCRX_NOTIF_NO_BUFFERS = 1 << 0,
+	ZCRX_NOTIF_COPY = 1 << 1
 };
 
 struct zcrx_notification_desc {
diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index 35ca28cb6583..732e585aa13a 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -1510,8 +1510,13 @@ static int io_zcrx_copy_frag(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
 			     const skb_frag_t *frag, int off, int len)
 {
 	struct page *page = skb_frag_page(frag);
+	int ret;
+
+	ret = io_zcrx_copy_chunk(req, ifq, page, off + skb_frag_off(frag), len);
+	if (ret > 0)
+		zcrx_send_notif(ifq, ZCRX_NOTIF_COPY);
 
-	return io_zcrx_copy_chunk(req, ifq, page, off + skb_frag_off(frag), len);
+	return ret;
 }
 
 static int io_zcrx_recv_frag(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
diff --git a/io_uring/zcrx.h b/io_uring/zcrx.h
index 3ddebed06d57..1bd63adaa711 100644
--- a/io_uring/zcrx.h
+++ b/io_uring/zcrx.h
@@ -11,7 +11,8 @@
 #define ZCRX_SUPPORTED_REG_FLAGS	(ZCRX_REG_IMPORT | ZCRX_REG_NODEV)
 #define ZCRX_FEATURES			(ZCRX_FEATURE_RX_PAGE_SIZE |\
 					 ZCRX_FEATURE_NOTIFICATION)
-#define ZCRX_NOTIF_TYPE_MASK		(ZCRX_NOTIF_NO_BUFFERS)
+#define ZCRX_NOTIF_TYPE_MASK		(ZCRX_NOTIF_NO_BUFFERS |\
+					 ZCRX_NOTIF_COPY)
 
 struct io_zcrx_mem {
 	unsigned long			size;
-- 
2.52.0


^ permalink raw reply related

* [PATCH 3/5] io_uring/zcrx: add shared-memory notification statistics
From: Clément Léger @ 2026-04-22 11:25 UTC (permalink / raw)
  To: io-uring, Pavel Begunkov, Jens Axboe
  Cc: Clément Léger, linux-doc, linux-kernel, linux-kselftest,
	netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	Vishwanath Seshagiri
In-Reply-To: <20260422112522.3316660-1-cleger@meta.com>

Add support for an optional stats struct embedded in the refill queue
region, allowing userspace to monitor copy-fallback and no-buffers events
in real-time.

Userspace queries the stats struct size and alignment via
IO_URING_QUERY_ZCRX (notif_stats_size / notif_stats_alignment), then
provides a stats_offset in zcrx_notification_desc pointing to a location
within the refill queue region.

The kernel updates the stats counters in-place using atomic ops on every
copy-fallback and no-buffers event.

Signed-off-by: Clément Léger <cleger@meta.com>
---
 include/uapi/linux/io_uring/query.h | 12 +++++++
 include/uapi/linux/io_uring/zcrx.h  | 15 +++++++--
 io_uring/query.c                    | 14 ++++++++
 io_uring/zcrx.c                     | 50 +++++++++++++++++++++++++++--
 io_uring/zcrx.h                     |  1 +
 5 files changed, 88 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/io_uring/query.h b/include/uapi/linux/io_uring/query.h
index 95500759cc13..738c35c7d05c 100644
--- a/include/uapi/linux/io_uring/query.h
+++ b/include/uapi/linux/io_uring/query.h
@@ -23,6 +23,7 @@ enum {
 	IO_URING_QUERY_OPCODES			= 0,
 	IO_URING_QUERY_ZCRX			= 1,
 	IO_URING_QUERY_SCQ			= 2,
+	IO_URING_QUERY_ZCRX_NOTIF		= 3,
 
 	__IO_URING_QUERY_MAX,
 };
@@ -62,6 +63,17 @@ struct io_uring_query_zcrx {
 	__u64 __resv2;
 };
 
+struct io_uring_query_zcrx_notif {
+	/* Bitmask of supported ZCRX_NOTIF_* flags*/
+	__u32 notif_flags;
+	/* Size of io_uring_zcrx_notif_stats */
+	__u32 notif_stats_size;
+	/* Required alignment for the stats struct within the region (ie stats_offset) */
+	__u32 notif_stats_off_alignment;
+	__u32 resv1;
+	__u64 __resv2[10];
+};
+
 struct io_uring_query_scq {
 	/* The SQ/CQ rings header size */
 	__u64 hdr_size;
diff --git a/include/uapi/linux/io_uring/zcrx.h b/include/uapi/linux/io_uring/zcrx.h
index e0c0079626c8..ae9bbca3004c 100644
--- a/include/uapi/linux/io_uring/zcrx.h
+++ b/include/uapi/linux/io_uring/zcrx.h
@@ -73,11 +73,22 @@ enum zcrx_notification_type {
 	ZCRX_NOTIF_COPY = 1 << 1
 };
 
+enum zcrx_notification_desc_flags {
+	/* If set, stats_offset holds a valid offset to a notif_stats struct */
+	ZCRX_NOTIF_DESC_FLAG_STATS = 1 << 0,
+};
+
+struct io_uring_zcrx_notif_stats {
+	__u64	copy_count;	/* cumulative copy-fallback CQEs */
+	__u64	copy_bytes;	/* cumulative bytes copied */
+};
+
 struct zcrx_notification_desc {
 	__u64	user_data;
 	__u32	type_mask;
-	__u32	__resv1;
-	__u64	__resv2[10];
+	__u32	flags; /* see enum zcrx_notification_desc_flags */
+	__u64	stats_offset; /* offset from the beginning of refill ring region for stats */
+	__u64	__resv2[9];
 };
 
 /*
diff --git a/io_uring/query.c b/io_uring/query.c
index c1704d088374..3591106e139d 100644
--- a/io_uring/query.c
+++ b/io_uring/query.c
@@ -9,6 +9,7 @@
 union io_query_data {
 	struct io_uring_query_opcode opcodes;
 	struct io_uring_query_zcrx zcrx;
+	struct io_uring_query_zcrx_notif zcrx_notif;
 	struct io_uring_query_scq scq;
 };
 
@@ -44,6 +45,16 @@ static ssize_t io_query_zcrx(union io_query_data *data)
 	return sizeof(*e);
 }
 
+static ssize_t io_query_zcrx_notif(union io_query_data *data)
+{
+	struct io_uring_query_zcrx_notif *e = &data->zcrx_notif;
+
+	e->notif_flags = ZCRX_NOTIF_TYPE_MASK;
+	e->notif_stats_size = sizeof(struct io_uring_zcrx_notif_stats);
+	e->notif_stats_off_alignment = __alignof__(struct io_uring_zcrx_notif_stats);
+	return sizeof(*e);
+}
+
 static ssize_t io_query_scq(union io_query_data *data)
 {
 	struct io_uring_query_scq *e = &data->scq;
@@ -83,6 +94,9 @@ static int io_handle_query_entry(union io_query_data *data, void __user *uhdr,
 	case IO_URING_QUERY_ZCRX:
 		ret = io_query_zcrx(data);
 		break;
+	case IO_URING_QUERY_ZCRX_NOTIF:
+		ret = io_query_zcrx_notif(data);
+		break;
 	case IO_URING_QUERY_SCQ:
 		ret = io_query_scq(data);
 		break;
diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index 732e585aa13a..c61f94fb14c3 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -414,6 +414,7 @@ static void io_free_rbuf_ring(struct io_zcrx_ifq *ifq)
 	io_free_region(ifq->user, &ifq->rq_region);
 	ifq->rq.ring = NULL;
 	ifq->rq.rqes = NULL;
+	ifq->notif_stats = NULL;
 }
 
 static void io_zcrx_free_area(struct io_zcrx_ifq *ifq,
@@ -841,6 +842,33 @@ static int zcrx_register_netdev(struct io_zcrx_ifq *ifq,
 	return ret;
 }
 
+static int zcrx_validate_notif_stats(struct io_zcrx_ifq *ifq,
+				     const struct io_uring_zcrx_ifq_reg *reg,
+				     const struct zcrx_notification_desc *notif)
+{
+	size_t stats_off = notif->stats_offset;
+	size_t used, end;
+
+	used = reg->offsets.rqes +
+	       sizeof(struct io_uring_zcrx_rqe) * reg->rq_entries;
+
+	if (!IS_ALIGNED(stats_off, __alignof__(struct io_uring_zcrx_notif_stats)))
+		return -EINVAL;
+	if (stats_off < used)
+		return -ERANGE;
+	if (check_add_overflow(stats_off,
+			       sizeof(struct io_uring_zcrx_notif_stats),
+			       &end))
+		return -ERANGE;
+	if (end > io_region_size(&ifq->rq_region))
+		return -ERANGE;
+
+	ifq->notif_stats = io_region_get_ptr(&ifq->rq_region) + stats_off;
+	memset(ifq->notif_stats, 0, sizeof(*ifq->notif_stats));
+
+	return 0;
+}
+
 int io_register_zcrx(struct io_ring_ctx *ctx,
 		     struct io_uring_zcrx_ifq_reg __user *arg)
 {
@@ -894,7 +922,9 @@ int io_register_zcrx(struct io_ring_ctx *ctx,
 		return -EFAULT;
 	if (notif.type_mask & ~ZCRX_NOTIF_TYPE_MASK)
 		return -EINVAL;
-	if (notif.__resv1 || !mem_is_zero(&notif.__resv2, sizeof(notif.__resv2)))
+	if (notif.flags & ~ZCRX_NOTIF_DESC_FLAG_STATS)
+		return -EINVAL;
+	if (!mem_is_zero(&notif.__resv2, sizeof(notif.__resv2)))
 		return -EINVAL;
 
 	ifq = io_zcrx_ifq_alloc(ctx);
@@ -925,6 +955,12 @@ int io_register_zcrx(struct io_ring_ctx *ctx,
 	if (ret)
 		goto err;
 
+	if (notif.flags & ZCRX_NOTIF_DESC_FLAG_STATS) {
+		ret = zcrx_validate_notif_stats(ifq, &reg, &notif);
+		if (ret)
+			goto err;
+	}
+
 	ifq->kern_readable = !(area.flags & IORING_ZCRX_AREA_DMABUF);
 
 	if (!(reg.flags & ZCRX_REG_NODEV)) {
@@ -1133,6 +1169,11 @@ static void zcrx_notif_tw(struct io_tw_req tw_req, io_tw_token_t tw)
 	kfree_rcu(req, rcu_head);
 }
 
+static void zcrx_stat_add(__u64 *p, s64 v)
+{
+	WRITE_ONCE(*p, READ_ONCE(*p) + v);
+}
+
 static void zcrx_send_notif(struct io_zcrx_ifq *ifq, u32 type_mask)
 {
 	gfp_t gfp = GFP_ATOMIC | __GFP_NOWARN | __GFP_ZERO;
@@ -1513,8 +1554,13 @@ static int io_zcrx_copy_frag(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
 	int ret;
 
 	ret = io_zcrx_copy_chunk(req, ifq, page, off + skb_frag_off(frag), len);
-	if (ret > 0)
+	if (ret > 0) {
+		if (ifq->notif_stats) {
+			zcrx_stat_add(&ifq->notif_stats->copy_count, 1);
+			zcrx_stat_add(&ifq->notif_stats->copy_bytes, ret);
+		}
 		zcrx_send_notif(ifq, ZCRX_NOTIF_COPY);
+	}
 
 	return ret;
 }
diff --git a/io_uring/zcrx.h b/io_uring/zcrx.h
index 1bd63adaa711..0dcf486ff530 100644
--- a/io_uring/zcrx.h
+++ b/io_uring/zcrx.h
@@ -82,6 +82,7 @@ struct io_zcrx_ifq {
 	u32				allowed_notif_mask;
 	u32				fired_notifs;
 	u64				notif_data;
+	struct io_uring_zcrx_notif_stats *notif_stats;
 };
 
 #if defined(CONFIG_IO_URING_ZCRX)
-- 
2.52.0


^ permalink raw reply related

* [PATCH 4/5] Documentation: networking: document zcrx notifications and statistics
From: Clément Léger @ 2026-04-22 11:25 UTC (permalink / raw)
  To: io-uring, Pavel Begunkov, Jens Axboe
  Cc: Clément Léger, linux-doc, linux-kernel, linux-kselftest,
	netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	Vishwanath Seshagiri
In-Reply-To: <20260422112522.3316660-1-cleger@meta.com>

Document the zcrx notification system and shared-memory statistics
that were introduced to let userspace monitor zero-copy receive health.
The notification section covers the two notification types
(ZCRX_NOTIF_NO_BUFFERS, ZCRX_NOTIF_COPY), registration via
zcrx_notification_desc, and the fire-once / re-arm mechanism via
ZCRX_CTRL_ARM_NOTIFICATION. The statistics section covers the optional
shared-memory io_uring_zcrx_notif_stats structure placed in the refill
ring region, including how to query its layout via
IO_URING_QUERY_ZCRX_NOTIF.

Signed-off-by: Clément Léger <cleger@meta.com>
---
 Documentation/networking/iou-zcrx.rst | 106 ++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/Documentation/networking/iou-zcrx.rst b/Documentation/networking/iou-zcrx.rst
index 7f3f4b2e6cf2..b17205fe55aa 100644
--- a/Documentation/networking/iou-zcrx.rst
+++ b/Documentation/networking/iou-zcrx.rst
@@ -196,6 +196,112 @@ Return buffers back to the kernel to be used again::
   rqe->len = cqe->res;
   IO_URING_WRITE_ONCE(*refill_ring.ktail, ++refill_ring.rq_tail);
 
+Notifications
+-------------
+
+When zero-copy receive encounters conditions that affect performance or
+functionality, the kernel can notify userspace via dedicated CQE notifications.
+The application must register a notification descriptor during
+``IORING_REGISTER_ZCRX_IFQ`` to receive them.
+
+Supported features can be detected by checking for ``ZCRX_FEATURE_NOTIFICATION``
+in the features bitmask returned by ``IO_URING_QUERY_ZCRX``.
+
+**Notification types**
+
+``ZCRX_NOTIF_NO_BUFFERS``
+  Fired when the page pool fails to allocate because the zcrx buffer area is
+  exhausted.
+
+``ZCRX_NOTIF_COPY``
+  Fired when a received fragment could not be delivered zero-copy and was
+  instead copied into a buffer.
+
+**Registering notifications**
+
+Allocate and fill a ``struct zcrx_notification_desc``::
+
+  struct zcrx_notification_desc notif = {
+    .user_data = MY_NOTIF_USER_DATA,
+    .type_mask = ZCRX_NOTIF_NO_BUFFERS | ZCRX_NOTIF_COPY,
+  };
+
+  reg.notif_desc = (__u64)(unsigned long)&notif;
+
+``user_data`` is the value that will appear in the notification CQE's
+``user_data`` field. ``type_mask`` selects which notification types the
+application wants to receive.
+
+When a registered event occurs, the kernel posts a CQE with the specified
+``user_data`` and ``cqe->res`` set to a bitmask of the triggered notification
+types.
+
+**Rate limiting**
+
+Each notification type fires once until the application explicitly re-arms it.
+To re-arm, issue ``IORING_REGISTER_ZCRX_CTRL`` with
+``ZCRX_CTRL_ARM_NOTIFICATION``::
+
+  struct zcrx_ctrl ctrl = {
+    .zcrx_id = zcrx_id,
+    .op = ZCRX_CTRL_ARM_NOTIFICATION,
+    .zc_arm_notif = {
+      .type_mask = ZCRX_NOTIF_NO_BUFFERS | ZCRX_NOTIF_COPY,
+    },
+  };
+
+  io_uring_register(ring_fd, IORING_REGISTER_ZCRX_CTRL, &ctrl, 0);
+
+Only notification types that have previously fired can be re-armed.
+
+Notification statistics
+-----------------------
+
+In addition to CQE-based notifications, the kernel can maintain a shared-memory
+statistics structure that is updated on every relevant event. All stats are
+updated regardless of which notification flags were registered.
+
+The statistics structure layout and alignment requirements can be queried via
+``IO_URING_QUERY_ZCRX_NOTIF``. The application must query the structure size
+and alignment requirements so that it allocates enough memory for the region
+to fit both the refill ring and the stats structure.
+
+To enable statistics, place the stats structure after the refill ring entries
+within the same mapped region, and set the ``ZCRX_NOTIF_DESC_FLAG_STATS`` flag
+in the notification descriptor::
+
+  /* Compute offset for the stats struct (after refill ring entries) */
+  size_t stats_offset = ring_size;
+  ring_size += ALIGN_UP(sizeof(struct io_uring_zcrx_notif_stats), PAGE_SIZE);
+
+  /* Map the region with the extra space */
+  ring_ptr = mmap(NULL, ring_size, PROT_READ | PROT_WRITE,
+                  MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+
+  struct zcrx_notification_desc notif = {
+    .user_data = MY_NOTIF_USER_DATA,
+    .type_mask = ZCRX_NOTIF_COPY,
+    .flags = ZCRX_NOTIF_DESC_FLAG_STATS,
+    .stats_offset = stats_offset,
+  };
+
+The ``stats_offset`` must satisfy the alignment reported by
+``notif_stats_off_alignment`` and must point to a location within the mapped
+region that does not overlap with the refill ring header or entries.
+
+Application can read stat counters them at any time::
+
+  volatile struct io_uring_zcrx_notif_stats *stats =
+    (void *)((char *)ring_ptr + stats_offset);
+
+  printf("copy fallbacks: %llu (%llu bytes)\n",
+         IO_URING_READ_ONCE(stats->copy_count),
+	 IO_URING_READ_ONCE(stats->copy_bytes));
+
+``copy_count`` is incremented each time a fragment is copied instead of being
+delivered via zero-copy. ``copy_bytes`` accumulates the total number of bytes
+copied.
+
 Area chunking
 -------------
 
-- 
2.52.0


^ permalink raw reply related

* [PATCH 5/5] selftests: iou-zcrx: add notification and stats test for zcrx
From: Clément Léger @ 2026-04-22 11:25 UTC (permalink / raw)
  To: io-uring, Pavel Begunkov, Jens Axboe
  Cc: Clément Léger, linux-doc, linux-kernel, linux-kselftest,
	netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	Vishwanath Seshagiri
In-Reply-To: <20260422112522.3316660-1-cleger@meta.com>

Add a selftest to verify that ZCRX notification are properly delivered
to userspace and that the shared-memory notification stats (copy_count,
copy_bytes) are correctly incremented when zero-copy RX falls back to
copying or when it runs out of buffers.

The test registers a notification descriptor during
IORING_REGISTER_ZCRX_IFQ with a stats region placed after the refill
queue entries. A new -n flag verifies that the copy fallback is
triggered and -b/-a flags allows to check for out of buffer
notification.

To reliably trigger copy fallback, the Python test uses a new
single_no_flow() setup variant that configures tcp-data-split and RSS
but without ethtool flow rule. Without flow steering, traffic arrives
on non-zcrx queues as regular pages, forcing the kernel copy-fallback
path in io_zcrx_copy_frag().

Out-of-buffer notification is verified by using a smaller receive area
and by avoiding recycling the buffers so that the kernel runs out of
buffer quickly.

Signed-off-by: Clément Léger <cleger@meta.com>
---
 .../selftests/drivers/net/hw/iou-zcrx.c       | 112 ++++++++++++++++--
 .../selftests/drivers/net/hw/iou-zcrx.py      |  49 +++++++-
 2 files changed, 149 insertions(+), 12 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/hw/iou-zcrx.c b/tools/testing/selftests/drivers/net/hw/iou-zcrx.c
index 240d13dbc54e..3c95e6460c24 100644
--- a/tools/testing/selftests/drivers/net/hw/iou-zcrx.c
+++ b/tools/testing/selftests/drivers/net/hw/iou-zcrx.c
@@ -52,7 +52,27 @@ struct t_io_uring_zcrx_ifq_reg {
 	struct io_uring_zcrx_offsets offsets;
 	__u32	zcrx_id;
 	__u32	rx_buf_len;
-	__u64	__resv[3];
+	__u64	notif_desc;
+	__u64	__resv[2];
+};
+
+#define ZCRX_NOTIF_NO_BUFFERS		(1 << 0)
+#define ZCRX_NOTIF_COPY			(1 << 1)
+#define ZCRX_NOTIF_DESC_FLAG_STATS	(1 << 0)
+
+#define NOTIF_USER_DATA			3
+
+struct t_zcrx_notification_desc {
+	__u64	user_data;
+	__u32	type_mask;
+	__u32	flags;
+	__u64	stats_offset;
+	__u64	__resv2[9];
+};
+
+struct t_io_uring_zcrx_notif_stats {
+	__u64	copy_count;
+	__u64	copy_bytes;
 };
 
 static long page_size;
@@ -84,7 +104,10 @@ static int cfg_oneshot_recvs;
 static int cfg_send_size = SEND_SIZE;
 static struct sockaddr_in6 cfg_addr;
 static unsigned int cfg_rx_buf_len;
+static size_t cfg_area_size;
 static bool cfg_dry_run;
+static bool cfg_copy_fallback;
+static bool cfg_no_buffers;
 
 static char *payload;
 static void *area_ptr;
@@ -95,6 +118,8 @@ static unsigned long area_token;
 static int connfd;
 static bool stop;
 static size_t received;
+static unsigned int notif_received_mask;
+static size_t notif_stats_offset;
 
 static unsigned long gettimeofday_ms(void)
 {
@@ -142,6 +167,7 @@ static void setup_zcrx(struct io_uring *ring)
 {
 	unsigned int ifindex;
 	unsigned int rq_entries = 4096;
+	size_t area_size = cfg_area_size ? cfg_area_size : AREA_SIZE;
 	int ret;
 
 	ifindex = if_nametoindex(cfg_ifname);
@@ -150,7 +176,7 @@ static void setup_zcrx(struct io_uring *ring)
 
 	if (cfg_rx_buf_len && cfg_rx_buf_len != page_size) {
 		area_ptr = mmap(NULL,
-				AREA_SIZE,
+				area_size,
 				PROT_READ | PROT_WRITE,
 				MAP_ANONYMOUS | MAP_PRIVATE |
 				MAP_HUGETLB | MAP_HUGE_2MB,
@@ -162,7 +188,7 @@ static void setup_zcrx(struct io_uring *ring)
 		}
 	} else {
 		area_ptr = mmap(NULL,
-				AREA_SIZE,
+				area_size,
 				PROT_READ | PROT_WRITE,
 				MAP_ANONYMOUS | MAP_PRIVATE,
 				0,
@@ -172,6 +198,12 @@ static void setup_zcrx(struct io_uring *ring)
 	}
 
 	ring_size = get_refill_ring_size(rq_entries);
+
+	if (cfg_copy_fallback) {
+		notif_stats_offset = ring_size;
+		ring_size += ALIGN_UP(sizeof(struct t_io_uring_zcrx_notif_stats), page_size);
+	}
+
 	ring_ptr = mmap(NULL,
 			ring_size,
 			PROT_READ | PROT_WRITE,
@@ -187,10 +219,11 @@ static void setup_zcrx(struct io_uring *ring)
 
 	struct io_uring_zcrx_area_reg area_reg = {
 		.addr = (__u64)(unsigned long)area_ptr,
-		.len = AREA_SIZE,
+		.len = area_size,
 		.flags = 0,
 	};
 
+	struct t_zcrx_notification_desc notif_desc;
 	struct t_io_uring_zcrx_ifq_reg reg = {
 		.if_idx = ifindex,
 		.if_rxq = cfg_queue_id,
@@ -200,11 +233,32 @@ static void setup_zcrx(struct io_uring *ring)
 		.rx_buf_len = cfg_rx_buf_len,
 	};
 
+	if (cfg_copy_fallback || cfg_no_buffers) {
+		__u32 type_mask = 0;
+
+		if (cfg_copy_fallback)
+			type_mask = ZCRX_NOTIF_COPY;
+		if (cfg_no_buffers)
+			type_mask = ZCRX_NOTIF_NO_BUFFERS;
+
+		memset(&notif_desc, 0, sizeof(notif_desc));
+		notif_desc.user_data = NOTIF_USER_DATA;
+		notif_desc.type_mask = type_mask;
+		if (cfg_copy_fallback) {
+			notif_desc.flags = ZCRX_NOTIF_DESC_FLAG_STATS;
+			notif_desc.stats_offset = notif_stats_offset;
+		}
+		reg.notif_desc = (__u64)(unsigned long)&notif_desc;
+	}
+
 	ret = io_uring_register_ifq(ring, (void *)&reg);
 	if (cfg_rx_buf_len && (ret == -EINVAL || ret == -EOPNOTSUPP ||
 			       ret == -ERANGE)) {
 		printf("Large chunks are not supported %i\n", ret);
 		exit(SKIP_CODE);
+	} else if ((cfg_copy_fallback || cfg_no_buffers) && ret == -EINVAL) {
+		printf("Notifications not supported %i\n", ret);
+		exit(SKIP_CODE);
 	} else if (ret) {
 		error(1, 0, "io_uring_register_ifq(): %d", ret);
 	}
@@ -304,10 +358,13 @@ static void process_recvzc(struct io_uring *ring, struct io_uring_cqe *cqe)
 	}
 	received += n;
 
-	rqe = &rq_ring.rqes[(rq_ring.rq_tail & rq_mask)];
-	rqe->off = (rcqe->off & ~IORING_ZCRX_AREA_MASK) | area_token;
-	rqe->len = cqe->res;
-	io_uring_smp_store_release(rq_ring.ktail, ++rq_ring.rq_tail);
+	/* Skip ring refill so that we ran out of buffers quickly */
+	if (!cfg_no_buffers) {
+		rqe = &rq_ring.rqes[(rq_ring.rq_tail & rq_mask)];
+		rqe->off = (rcqe->off & ~IORING_ZCRX_AREA_MASK) | area_token;
+		rqe->len = cqe->res;
+		io_uring_smp_store_release(rq_ring.ktail, ++rq_ring.rq_tail);
+	}
 }
 
 static void server_loop(struct io_uring *ring)
@@ -324,8 +381,15 @@ static void server_loop(struct io_uring *ring)
 			process_accept(ring, cqe);
 		else if (cqe->user_data == 2)
 			process_recvzc(ring, cqe);
-		else
+		else if ((cfg_copy_fallback || cfg_no_buffers) &&
+			 cqe->user_data == NOTIF_USER_DATA) {
+			notif_received_mask |= cqe->res;
+			if (cfg_no_buffers &&
+			    (cqe->res & ZCRX_NOTIF_NO_BUFFERS))
+				stop = true;
+		} else {
 			error(1, 0, "unknown cqe");
+		}
 		count++;
 	}
 	io_uring_cq_advance(ring, count);
@@ -374,6 +438,23 @@ static void run_server(void)
 
 	if (!stop)
 		error(1, 0, "test failed\n");
+
+	if (cfg_copy_fallback) {
+		struct t_io_uring_zcrx_notif_stats *stats =
+			(void *)((char *)ring_ptr + notif_stats_offset);
+
+		if (!(notif_received_mask & ZCRX_NOTIF_COPY))
+			error(1, 0, "expected copy fallback notification");
+		if (!IO_URING_READ_ONCE(stats->copy_count))
+			error(1, 0, "expected copy_count > 0");
+		if (!IO_URING_READ_ONCE(stats->copy_bytes))
+			error(1, 0, "expected copy_bytes > 0");
+	}
+
+	if (cfg_no_buffers) {
+		if (!(notif_received_mask & ZCRX_NOTIF_NO_BUFFERS))
+			error(1, 0, "expected no-buffers notification");
+	}
 }
 
 static void run_client(void)
@@ -425,7 +506,7 @@ static void parse_opts(int argc, char **argv)
 		usage(argv[0]);
 	cfg_payload_len = max_payload_len;
 
-	while ((c = getopt(argc, argv, "sch:p:l:i:q:o:z:x:d")) != -1) {
+	while ((c = getopt(argc, argv, "sch:p:l:i:q:o:z:x:a:dnb")) != -1) {
 		switch (c) {
 		case 's':
 			if (cfg_client)
@@ -466,8 +547,19 @@ static void parse_opts(int argc, char **argv)
 		case 'd':
 			cfg_dry_run = true;
 			break;
+		case 'n':
+			cfg_copy_fallback = true;
+			break;
+		case 'b':
+			cfg_no_buffers = true;
+			break;
+		case 'a':
+			cfg_area_size = strtoul(optarg, NULL, 0) * page_size;
+			break;
 		}
 	}
+	if (cfg_copy_fallback && cfg_no_buffers)
+		error(1, 0, "Pass one of -n or -b");
 
 	if (cfg_server && addr)
 		error(1, 0, "Receiver cannot have -h specified");
diff --git a/tools/testing/selftests/drivers/net/hw/iou-zcrx.py b/tools/testing/selftests/drivers/net/hw/iou-zcrx.py
index e81724cb5542..f7f1cbff5959 100755
--- a/tools/testing/selftests/drivers/net/hw/iou-zcrx.py
+++ b/tools/testing/selftests/drivers/net/hw/iou-zcrx.py
@@ -41,7 +41,9 @@ def set_flow_rule_rss(cfg, rss_ctx_id):
     return int(values)
 
 
-def single(cfg):
+def single_no_flow(cfg):
+    """Like single() but without a flow rule."""
+
     channels = cfg.ethnl.channels_get({'header': {'dev-index': cfg.ifindex}})
     channels = channels['combined-count']
     if channels < 2:
@@ -65,6 +67,9 @@ def single(cfg):
     ethtool(f"-X {cfg.ifname} equal {cfg.target}")
     defer(ethtool, f"-X {cfg.ifname} default")
 
+def single(cfg):
+    single_no_flow(cfg)
+
     flow_rule_id = set_flow_rule(cfg)
     defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")
 
@@ -130,6 +135,26 @@ def test_zcrx_oneshot(cfg, setup) -> None:
         cmd(tx_cmd, host=cfg.remote)
 
 
+@ksft_variants([
+    KsftNamedVariant("single", single_no_flow),
+])
+def test_zcrx_notif(cfg, setup) -> None:
+    """Test zcrx copy fallback notification.
+
+    Omits the flow rule so traffic arrives on non-zcrx queues as regular
+    pages, forcing the kernel copy-fallback path. Asserts that the
+    ZCRX_NOTIF_COPY notification CQE is delivered."""
+
+    cfg.require_ipver('6')
+
+    setup(cfg)
+    rx_cmd = f"{cfg.bin_local} -s -p {cfg.port} -i {cfg.ifname} -q {cfg.target} -n"
+    tx_cmd = f"{cfg.bin_remote} -c -h {cfg.addr_v['6']} -p {cfg.port} -l 12840"
+    with bkg(rx_cmd, exit_wait=True):
+        wait_port_listen(cfg.port, proto="tcp")
+        cmd(tx_cmd, host=cfg.remote)
+
+
 def test_zcrx_large_chunks(cfg) -> None:
     """Test zcrx with large buffer chunks."""
 
@@ -157,6 +182,25 @@ def test_zcrx_large_chunks(cfg) -> None:
         cmd(tx_cmd, host=cfg.remote)
 
 
+@ksft_variants([
+    KsftNamedVariant("single", single),
+])
+def test_zcrx_notif_no_buffers(cfg, setup) -> None:
+    """Test zcrx out-of-buffer notification.
+
+    Skips buffer refill so the pool is quickly exhausted, triggering
+    a ZCRX_NOTIF_NO_BUFFERS notification CQE."""
+
+    cfg.require_ipver('6')
+
+    setup(cfg)
+    rx_cmd = f"{cfg.bin_local} -s -p {cfg.port} -i {cfg.ifname} -q {cfg.target} -b -a 64"
+    tx_cmd = f"{cfg.bin_remote} -c -h {cfg.addr_v['6']} -p {cfg.port} -l 12840"
+    with bkg(rx_cmd, exit_wait=True):
+        wait_port_listen(cfg.port, proto="tcp")
+        cmd(tx_cmd, host=cfg.remote, fail=False)
+
+
 def main() -> None:
     with NetDrvEpEnv(__file__) as cfg:
         cfg.bin_local = path.abspath(path.dirname(__file__) + "/../../../drivers/net/hw/iou-zcrx")
@@ -166,7 +210,8 @@ def main() -> None:
         cfg.netnl = NetdevFamily()
         cfg.port = rand_port()
         ksft_run(globs=globals(), cases=[test_zcrx, test_zcrx_oneshot,
-                                        test_zcrx_large_chunks], args=(cfg, ))
+                                        test_zcrx_large_chunks, test_zcrx_notif,
+                                        test_zcrx_notif_no_buffers], args=(cfg, ))
     ksft_exit()
 
 
-- 
2.52.0


^ permalink raw reply related

* [PATCH 0/2] Add support for LX1308
From: Brian Chiang @ 2026-04-22 12:06 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jonathan Corbet, Shuah Khan
  Cc: linux-hwmon, devicetree, linux-kernel, linux-doc, Brian Chiang

The LX1308 is a high-efficiency, non-isolated power module. The module
operates from a 40V to 60V DC primary bus and a 12V regulated output
voltage. It can deliver up to 860W continuous and 1300W in transient.
The built-in digital controller can store and restore module
configurations. The fault status, input voltage, output voltage, output
current, and temperature are monitored via the PMBus interface.

Add support for this driver.

Signed-off-by: Brian Chiang <chiang.brian@inventec.com>
---
Brian Chiang (2):
      dt-bindings: (pmbus/lx1308) Add LX1308 support
      hwmon: (pmbus/lx1308) Add support for LX1308

 .../bindings/hwmon/pmbus/luxshare,lx1308.yaml      |  49 +++++
 .../devicetree/bindings/vendor-prefixes.yaml       |   2 +
 Documentation/hwmon/index.rst                      |   1 +
 Documentation/hwmon/lx1308.rst                     |  90 +++++++++
 MAINTAINERS                                        |   8 +
 drivers/hwmon/pmbus/Kconfig                        |  10 +
 drivers/hwmon/pmbus/Makefile                       |   1 +
 drivers/hwmon/pmbus/lx1308.c                       | 204 +++++++++++++++++++++
 8 files changed, 365 insertions(+)
---
base-commit: 591cd656a1bf5ea94a222af5ef2ee76df029c1d2
change-id: 20260415-add-support-lx1308-165a4206ab69

Best regards,
-- 
Brian Chiang <chiang.brian@inventec.com>


^ permalink raw reply

* [PATCH 1/2] dt-bindings: (pmbus/lx1308) Add LX1308 support
From: Brian Chiang @ 2026-04-22 12:06 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jonathan Corbet, Shuah Khan
  Cc: linux-hwmon, devicetree, linux-kernel, linux-doc, Brian Chiang
In-Reply-To: <20260422-add-support-lx1308-v1-0-9b8322f45aae@inventec.com>

Add device tree bindings for the Luxshare LX1308, a high-efficiency
12V 860W DC/DC power module with PMBus interface.

Signed-off-by: Brian Chiang <chiang.brian@inventec.com>
---
 .../bindings/hwmon/pmbus/luxshare,lx1308.yaml      | 49 ++++++++++++++++++++++
 .../devicetree/bindings/vendor-prefixes.yaml       |  2 +
 MAINTAINERS                                        |  8 ++++
 3 files changed, 59 insertions(+)

diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/luxshare,lx1308.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/luxshare,lx1308.yaml
new file mode 100644
index 000000000000..a8d92447508d
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/luxshare,lx1308.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/pmbus/luxshare,lx1308.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Luxshare LX1308 Digital DC/DC Power Module
+
+maintainers:
+  - Brian Chiang <chiang.brian@inventec.com>
+
+description: |
+  The LX1308 is a high-efficiency, non-isolated, regulated 12V, 860W,
+  digital DC/DC power module. The module operates from a 40V to 60V DC
+  primary bus and provides a 12V regulated output voltage. It can deliver
+  up to 860W continuous and 1300W in transient.
+
+properties:
+  compatible:
+    enum:
+      - luxshare,lx1308lch
+      - luxshare,lx1308nch
+      - luxshare,lx1308sch
+      - luxshare,lx1308ldh
+      - luxshare,lx1308ndh
+      - luxshare,lx1308sdh
+      - luxshare,lx1308
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      power-module@60 {
+        compatible = "luxshare,lx1308";
+        reg = <0x60>;
+      };
+    };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index ee7fd3cfe203..67fb1592daaa 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -967,6 +967,8 @@ patternProperties:
     description: Shenzhen Luckfox Technology Co., Ltd.
   "^lunzn,.*":
     description: Shenzhen Lunzn Technology Co., Ltd.
+  "^luxshare,.*":
+    description: Luxshare-ICT Co., Ltd.
   "^luxul,.*":
     description: Lagrand | AV
   "^lwn,.*":
diff --git a/MAINTAINERS b/MAINTAINERS
index c3fe46d7c4bc..58fa595cff6a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15175,6 +15175,14 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/iio/light/liteon,ltr390.yaml
 F:	drivers/iio/light/ltr390.c
 
+LUXSHARE LX1308 PMBUS DRIVER
+M:	Brian Chiang <chiang.brian@inventec.com>
+L:	linux-hwmon@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/hwmon/pmbus/luxshare,lx1308.yaml
+F:	Documentation/hwmon/lx1308.rst
+F:	drivers/hwmon/pmbus/lx1308.c
+
 LYNX 28G SERDES PHY DRIVER
 M:	Ioana Ciornei <ioana.ciornei@nxp.com>
 L:	netdev@vger.kernel.org

-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/2] hwmon: (pmbus/lx1308) Add support for LX1308
From: Brian Chiang @ 2026-04-22 12:06 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jonathan Corbet, Shuah Khan
  Cc: linux-hwmon, devicetree, linux-kernel, linux-doc, Brian Chiang
In-Reply-To: <20260422-add-support-lx1308-v1-0-9b8322f45aae@inventec.com>

Add support for the Luxshare LX1308, a high-efficiency 12V 860W
DC/DC power module. The module operates from 40-60V input voltage.

Signed-off-by: Brian Chiang <chiang.brian@inventec.com>
---
 Documentation/hwmon/index.rst  |   1 +
 Documentation/hwmon/lx1308.rst |  90 ++++++++++++++++++
 drivers/hwmon/pmbus/Kconfig    |  10 ++
 drivers/hwmon/pmbus/Makefile   |   1 +
 drivers/hwmon/pmbus/lx1308.c   | 204 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 306 insertions(+)

diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index b2ca8513cfcd..c86c21554c37 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -145,6 +145,7 @@ Hardware Monitoring Kernel Drivers
    ltc4261
    ltc4282
    ltc4286
+   lx1308
    macsmc-hwmon
    max127
    max15301
diff --git a/Documentation/hwmon/lx1308.rst b/Documentation/hwmon/lx1308.rst
new file mode 100644
index 000000000000..c1b72e1647c5
--- /dev/null
+++ b/Documentation/hwmon/lx1308.rst
@@ -0,0 +1,90 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver lx1308
+====================
+
+Supported chips:
+
+  * Luxshare LX1308
+
+    Prefixes: 'lx1308'
+
+    Addresses scanned: -
+
+    Datasheet: Datasheet is not publicly available.
+
+Author: Brian Chiang <chiang.brian@inventec.com>
+
+
+Description
+-----------
+
+The LX1308 is a high-efficiency, non-isolated, regulated 12V, 860W,
+digital DC/DC power module. The module operates from a 40V to 60V DC
+primary bus and provides a 12V regulated output voltage. It can deliver
+up to 860W continuous and 1300W in transient.
+
+The module has slow OCP and fast OCP. If the module output current is higher
+than slow OCP set point and the lasting time is also longer than the delay,
+the module will shut down and retry 3 time, if the fault still exists then
+module enter latch mode.
+
+If the module output current is higher than fast OCP set point then it shut
+down and enter latch mode.
+
+The driver is a client driver to the core PMBus driver.
+Please see Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for
+details.
+
+
+Sysfs entries
+-------------
+
+======================= ======================================================
+curr1_alarm             Input current alarm
+curr1_input             Input current (IIN)
+curr1_label             "iin"
+curr2_crit              Output over current fault threshold (slow OCP, 60ms delay)
+curr2_crit_alarm        Output over current fault alarm
+curr2_input             Output current (IOUT)
+curr2_label             "iout1"
+curr2_max               Output over current warning threshold (slow OCP, 60ms delay)
+curr2_max_alarm         Output over current warning alarm
+in1_crit                Input over voltage fault threshold
+in1_crit_alarm          Input over voltage fault alarm
+in1_input               Input voltage (VIN)
+in1_label               "vin"
+in1_lcrit               Input under voltage fault threshold
+in1_lcrit_alarm         Input under voltage fault alarm
+in1_max                 Input over voltage warning threshold
+in1_max_alarm           Input over voltage warning alarm
+in1_min                 Input under voltage warning threshold
+in1_min_alarm           Input under voltage warning alarm
+in2_crit                Output over voltage fault threshold
+in2_crit_alarm          Output over voltage fault alarm
+in2_input               Output voltage (VOUT)
+in2_label               "vout1"
+in2_lcrit               Output under voltage fault threshold
+in2_lcrit_alarm         Output under voltage fault alarm
+in2_max                 Output over voltage warning threshold
+in2_max_alarm           Output over voltage warning alarm
+in2_min                 Output under voltage warning threshold
+in2_min_alarm           Output under voltage warning alarm
+power1_alarm            Input power alarm
+power1_input            Input power (PIN)
+power1_label            "pin"
+power2_input            Output power (POUT)
+power2_label            "pout1"
+temp1_crit              Over temperature fault threshold
+temp1_crit_alarm        Over temperature fault alarm
+temp1_input             Module hot spot temperature
+temp1_max               Over temperature warning threshold
+temp1_max_alarm         Over temperature warning alarm
+======================= ======================================================
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index fc1273abe357..1c5dc4294248 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -221,6 +221,16 @@ config SENSORS_ISL68137
 	  This driver can also be built as a module. If so, the module will
 	  be called isl68137.
 
+config SENSORS_LX1308
+	tristate "Luxshare LX1308 DC/DC Power Module"
+	help
+	  If you say yes here you get hardware monitoring support for
+	  Luxshare LX1308, a high-efficiency 12V 860W DC/DC power module
+	  with PMBus interface.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called lx1308.
+
 config SENSORS_LM25066
 	tristate "National Semiconductor LM25066 and compatibles"
 	help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index d6c86924f887..4861e144c7e7 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_SENSORS_IR36021)	+= ir36021.o
 obj-$(CONFIG_SENSORS_IR38064)	+= ir38064.o
 obj-$(CONFIG_SENSORS_IRPS5401)	+= irps5401.o
 obj-$(CONFIG_SENSORS_ISL68137)	+= isl68137.o
+obj-$(CONFIG_SENSORS_LX1308)	+= lx1308.o
 obj-$(CONFIG_SENSORS_LM25066)	+= lm25066.o
 obj-$(CONFIG_SENSORS_LT3074)	+= lt3074.o
 obj-$(CONFIG_SENSORS_LT7182S)	+= lt7182s.o
diff --git a/drivers/hwmon/pmbus/lx1308.c b/drivers/hwmon/pmbus/lx1308.c
new file mode 100644
index 000000000000..c7a7a1fd4f21
--- /dev/null
+++ b/drivers/hwmon/pmbus/lx1308.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include "pmbus.h"
+
+#define LX1308_MFR_IOUT_OCP3_FAULT	0xBE
+#define LX1308_MFR_IOUT_OCP3_WARN	0xBF
+
+/*
+ * Decode a Linear11-encoded word to an integer value.
+ * Linear11 format: bits[15:11] = signed 5-bit exponent,
+ * bits[10:0] = signed 11-bit mantissa. Result = mant * 2^exp.
+ */
+static inline int linear11_to_int(u16 word)
+{
+	s16 exp = ((s16)word) >> 11;
+	s16 mant = ((s16)((word & 0x7ff) << 5)) >> 5;
+
+	return (exp >= 0) ? (mant << exp) : (mant / (1 << (-exp)));
+}
+
+static int lx1308_read_word_data(struct i2c_client *client, int page,
+				 int phase, int reg)
+{
+	int ret;
+
+	if (page > 0)
+		return -ENXIO;
+
+	switch (reg) {
+	/*
+	 * The LX1308 OCP3 registers (slow OCP, 60ms delay) use a
+	 * manufacturer-specific U8.0 format. Read the byte value N and present
+	 * it as a Linear11 word with exponent 0.
+	 */
+	case PMBUS_IOUT_OC_FAULT_LIMIT:
+		ret = i2c_smbus_read_byte_data(client, LX1308_MFR_IOUT_OCP3_FAULT);
+		if (ret < 0)
+			break;
+		ret &= 0x7FF;
+		break;
+
+	case PMBUS_IOUT_OC_WARN_LIMIT:
+		ret = i2c_smbus_read_byte_data(client, LX1308_MFR_IOUT_OCP3_WARN);
+		if (ret < 0)
+			break;
+		ret &= 0x7FF;
+		break;
+
+	/*
+	 * The following registers are not implemented by the LX1308. Return
+	 * -ENXIO to suppress the corresponding sysfs attributes.
+	 */
+	case PMBUS_IIN_OC_WARN_LIMIT:
+	case PMBUS_IIN_OC_FAULT_LIMIT:
+	case PMBUS_IOUT_UC_FAULT_LIMIT:
+	case PMBUS_PIN_OP_WARN_LIMIT:
+	case PMBUS_POUT_OP_WARN_LIMIT:
+	case PMBUS_UT_WARN_LIMIT:
+	case PMBUS_UT_FAULT_LIMIT:
+	case PMBUS_MFR_IIN_MAX:
+	case PMBUS_MFR_IOUT_MAX:
+	case PMBUS_MFR_VIN_MIN:
+	case PMBUS_MFR_VIN_MAX:
+	case PMBUS_MFR_VOUT_MIN:
+	case PMBUS_MFR_VOUT_MAX:
+	case PMBUS_MFR_PIN_MAX:
+	case PMBUS_MFR_POUT_MAX:
+	case PMBUS_MFR_MAX_TEMP_1:
+		ret = -ENXIO;
+		break;
+
+	default:
+		ret = -ENODATA;
+		break;
+	}
+
+	return ret;
+}
+
+static int lx1308_write_word_data(struct i2c_client *client, int page,
+				  int reg, u16 word)
+{
+	int ret;
+
+	if (page > 0)
+		return -ENXIO;
+
+	switch (reg) {
+	case PMBUS_IOUT_OC_FAULT_LIMIT:
+		/*
+		 * Decode Linear11 word from pmbus_core back to a plain integer
+		 * and write as the U8.0 byte the device expects.
+		 */
+		ret = i2c_smbus_write_byte_data(client, LX1308_MFR_IOUT_OCP3_FAULT,
+						clamp_val(linear11_to_int(word), 0, 255));
+		break;
+
+	case PMBUS_IOUT_OC_WARN_LIMIT:
+		ret = i2c_smbus_write_byte_data(client, LX1308_MFR_IOUT_OCP3_WARN,
+						clamp_val(linear11_to_int(word), 0, 255));
+		break;
+
+	default:
+		ret = -ENODATA;
+		break;
+	}
+
+	return ret;
+}
+
+static struct pmbus_driver_info lx1308_info = {
+	.pages = 1,
+	.format[PSC_VOLTAGE_IN] = linear,
+	.format[PSC_VOLTAGE_OUT] = linear,
+	.format[PSC_CURRENT_IN] = linear,
+	.format[PSC_CURRENT_OUT] = linear,
+	.format[PSC_POWER] = linear,
+	.format[PSC_TEMPERATURE] = linear,
+
+	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		| PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+		| PMBUS_HAVE_PIN | PMBUS_HAVE_POUT
+		| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
+		| PMBUS_HAVE_STATUS_INPUT,
+
+	.read_word_data  = lx1308_read_word_data,
+	.write_word_data = lx1308_write_word_data,
+};
+
+static const struct i2c_device_id lx1308_id[] = {
+	{ "lx1308" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, lx1308_id);
+
+static int lx1308_probe(struct i2c_client *client)
+{
+	u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
+	const struct i2c_device_id *mid;
+	int ret;
+
+	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
+	if (ret < 0)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to read manufacturer id\n");
+	buf[ret] = '\0';
+
+	if (ret != 12 || strncmp(buf, "LUXSHARE", 8))
+		return dev_err_probe(&client->dev, -ENODEV,
+				     "Unsupported Manufacturer ID '%s'\n", buf);
+
+	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
+	if (ret < 0)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to read Manufacturer Model\n");
+	buf[ret] = '\0';
+
+	for (mid = lx1308_id; mid->name[0]; mid++) {
+		if (!strncasecmp(mid->name, buf, strlen(mid->name)))
+			break;
+	}
+	if (!mid->name[0])
+		return dev_err_probe(&client->dev, -ENODEV,
+				     "Unsupported Manufacturer Model '%s'\n", buf);
+
+	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_REVISION, buf);
+	if (ret < 0)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to read Manufacturer Revision\n");
+	buf[ret] = '\0';
+
+	if (ret != 12 || buf[0] != 'V')
+		return dev_err_probe(&client->dev, -ENODEV,
+				     "Unsupported Manufacturer Revision '%s'\n", buf);
+	return pmbus_do_probe(client, &lx1308_info);
+}
+
+static const struct of_device_id lx1308_of_match[] = {
+	{ .compatible = "luxshare,lx1308" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, lx1308_of_match);
+
+static struct i2c_driver lx1308_driver = {
+	.driver = {
+		.name = "lx1308",
+		.of_match_table = lx1308_of_match,
+	},
+	.probe = lx1308_probe,
+	.id_table = lx1308_id,
+};
+
+module_i2c_driver(lx1308_driver);
+
+MODULE_AUTHOR("Brian Chiang <chiang.brian@inventec.com>");
+MODULE_DESCRIPTION("PMBus driver for Luxshare LX1308");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("PMBUS");

-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v2 3/3] Documentation: deprecated.rst: kmalloc-family: mark argument as optional
From: Manuel Ebner @ 2026-04-22 12:09 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Jonathan Corbet, Shuah Khan, linux-doc, Kees Cook, linux-kernel,
	workflows
In-Reply-To: <CAMuHMdV70GhNsxPiuhY92seZRMkr6jk9eFCke7shc08GYerLpg@mail.gmail.com>

On Wed, 2026-04-22 at 09:14 +0200, Geert Uytterhoeven wrote:
> Hi Manuel,
> 
> Thanks for your patch!

That's good to read.

> On Tue, 21 Apr 2026 at 20:09, Manuel Ebner <manuelebner@mailbox.org> wrote:
> > put the optional argument (gfp) in square brackets
> > 
> > eg. ptr = kmalloc_obj(*ptr, gfp);
> >  -> ptr = kmalloc_obj(*ptr, [gfp]);
> 
> Shouldn't that be "[, gfp]", e.g.
> 
>     kmalloc_obj(*ptr [, gfp]);

I think technically it should be 

    kmalloc_obj(*ptr[, gfp]);

but that's difficult to grasp, so i went for my notation. Yours
is a good tradeoff. I'll think about it and choose the right one.

> 
> everywhere?
> 
> > Signed-off-by: Manuel Ebner <manuelebner@mailbox.org>
> 
> Gr{oetje,eeting}s,
> 
>                         Geert

^ permalink raw reply

* Re: [PATCH net 00/18] Remove a number of ISA and PCMCIA Ethernet drivers
From: Andrew Lunn @ 2026-04-22 12:11 UTC (permalink / raw)
  To: Byron Stanoszek
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	linux-kernel, netdev, linux-doc
In-Reply-To: <9a0bc592-fb74-f646-1752-4359c0ac31a2@polinggroup.com>

On Tue, Apr 21, 2026 at 11:03:28PM -0400, Byron Stanoszek wrote:
> On Wed, 22 Apr 2026, Andrew Lunn wrote:
> > 
> > Could you live with v6.18, which has an expected EOL of December 2028?
> > If you are only updating once per year, security is not an issue, you
> > just want stability.
> 
> I could for the time being, but this hasn't worked for me in the past. Usually
> what happens is the PC breaks down, and the customer swaps in a new
> backplane+SBC and moves all their PCI cards over. I then find I need to update
> the kernel just to get the Intel DRM to work properly on the new CPU. Some of
> these systems were installed back in the Linux 2.6 era, so I've gone through
> several "Intel DRM not working" steps ever since CPUs started getting
> integrated graphics. 2028 will come fast.

Hi Byron

I will drop this driver from the patchset.

	Andrew

^ permalink raw reply

* Re: [PATCH net 11/18] drivers: net: cirrus: cs89x0: Remove this driver
From: Andrew Lunn @ 2026-04-22 12:13 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	linux-kernel, netdev, linux-doc
In-Reply-To: <CAMuHMdWz=ucmKxHXmzKj=oTn6yMVxPnkNxtG6X2C3ts_ZCg4Cw@mail.gmail.com>

> > -config CS89x0_PLATFORM
> > -       tristate "CS89x0 platform driver support"
> > -       depends on ARM || (COMPILE_TEST && !PPC)
> > -       select CS89x0
> > -       help
> > -         Say Y to compile the cs89x0 platform driver. This makes this driver
> > -         suitable for use on certain evaluation boards such as the iMX21ADS.
> > -
> > -         To compile this driver as a module, choose M here. The module
> > -         will be called cs89x0.
> 
> This is the more modern DT-based part...

No dependency on OF?

> However, no users of these compatible values ever appeared upstream.

Thanks for the information. That helps with the removal.

       Andrew

^ permalink raw reply

* Re: [PATCH v2 3/3] Documentation: deprecated.rst: kmalloc-family: mark argument as optional
From: Geert Uytterhoeven @ 2026-04-22 12:15 UTC (permalink / raw)
  To: Manuel Ebner
  Cc: Jonathan Corbet, Shuah Khan, linux-doc, Kees Cook, linux-kernel,
	workflows
In-Reply-To: <a5522bdaf37c7f1d2fdf03e1755061a4d803efb2.camel@mailbox.org>

Hi Manuel,

On Wed, 22 Apr 2026 at 14:10, Manuel Ebner <manuelebner@mailbox.org> wrote:
> On Wed, 2026-04-22 at 09:14 +0200, Geert Uytterhoeven wrote:
> > On Tue, 21 Apr 2026 at 20:09, Manuel Ebner <manuelebner@mailbox.org> wrote:
> > > put the optional argument (gfp) in square brackets
> > >
> > > eg. ptr = kmalloc_obj(*ptr, gfp);
> > >  -> ptr = kmalloc_obj(*ptr, [gfp]);
> >
> > Shouldn't that be "[, gfp]", e.g.
> >
> >     kmalloc_obj(*ptr [, gfp]);
>
> I think technically it should be
>
>     kmalloc_obj(*ptr[, gfp]);
>
> but that's difficult to grasp, so i went for my notation. Yours
> is a good tradeoff. I'll think about it and choose the right one.

A third option is

    kmalloc_obj(*ptr [, gfp] );

or even:

    kmalloc_obj(*ptr [ , gfp ] );

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH net 14/18] drivers: net: xircom: xirc2ps: Remove this driver
From: Andrew Lunn @ 2026-04-22 12:15 UTC (permalink / raw)
  To: Michael Fritscher
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Jonathan Corbet, Shuah Khan, linux-kernel, netdev,
	linux-doc
In-Reply-To: <73e3a34c-f1dc-403b-b007-18ff85d66ea1@fritscher.net>

On Wed, Apr 22, 2026 at 08:21:23AM +0200, Michael Fritscher wrote:
> Good day,
> 
> actually, I do use Xircom PCMCIA network cards (yes, the 16 bit ones) on
> Lenovo X60/X61 laptops as a second LAN card for server maintenances with
> current 64 bit distros (e.g. Debian Trixie, which I plan to update to
> Trixie+1 when available). Why? Because I have them and they are working ;-)
 
Hi Michael

I will drop this from the patchset for the moment.

Would you be willing to take up the Maintainer role for it?

	Andrew


^ permalink raw reply

* Re: [PATCH net 11/18] drivers: net: cirrus: cs89x0: Remove this driver
From: Geert Uytterhoeven @ 2026-04-22 12:17 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	linux-kernel, netdev, linux-doc
In-Reply-To: <c6696785-6f1f-4747-996a-d86a60a23d0b@lunn.ch>

Hi Andrew,

On Wed, 22 Apr 2026 at 14:13, Andrew Lunn <andrew@lunn.ch> wrote:
> > > -config CS89x0_PLATFORM
> > > -       tristate "CS89x0 platform driver support"
> > > -       depends on ARM || (COMPILE_TEST && !PPC)
> > > -       select CS89x0
> > > -       help
> > > -         Say Y to compile the cs89x0 platform driver. This makes this driver
> > > -         suitable for use on certain evaluation boards such as the iMX21ADS.
> > > -
> > > -         To compile this driver as a module, choose M here. The module
> > > -         will be called cs89x0.
> >
> > This is the more modern DT-based part...
>
> No dependency on OF?

I guess no one bothered to add it, as it presumably builds fine without.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH v7 1/5] bug/kunit: Core support for suppressing warning backtraces
From: David Gow @ 2026-04-22 12:19 UTC (permalink / raw)
  To: Albert Esteve, Arnd Bergmann, Brendan Higgins, Rae Moar,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton
  Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
	workflows, linux-doc, peterz, Alessandro Carminati, Guenter Roeck,
	Kees Cook
In-Reply-To: <20260420-kunit_add_support-v7-1-e8bc6e0f70de@redhat.com>

Thanks very much for keeping this series alive! I'm very much in favour 
of it, and I think the overall design is good. Lots of more detailed 
nitpicks below, though.

Le 20/04/2026 à 8:28 PM, Albert Esteve a écrit :
> From: Alessandro Carminati <acarmina@redhat.com>
> 
> Some unit tests intentionally trigger warning backtraces by passing bad
> parameters to kernel API functions. Such unit tests typically check the
> return value from such calls, not the existence of the warning backtrace.
> 
> Such intentionally generated warning backtraces are neither desirable
> nor useful for a number of reasons:
> - They can result in overlooked real problems.
> - A warning that suddenly starts to show up in unit tests needs to be
>    investigated and has to be marked to be ignored, for example by
>    adjusting filter scripts. Such filters are ad hoc because there is
>    no real standard format for warnings. On top of that, such filter
>    scripts would require constant maintenance.
> 
> Solve the problem by providing a means to identify and suppress specific
> warning backtraces while executing test code. Support suppressing multiple
> backtraces while at the same time limiting changes to generic code to the
> absolute minimum.

It sounds from the description here that suppressing "specific 
backtraces" means that we're matching on the _contents_ of the stack 
trace. This sort-of does that implicitly by checking they're in the same 
kthread, but I think the fact that it's matching based on kthread should 
be explicit in the commit message, like it is in the documentation.

> 
> Implementation details:
> Suppression is checked at two points in the warning path:
> - In warn_slowpath_fmt(), the check runs before any output, fully
>    suppressing both message and backtrace.
> - In __report_bug(), the check runs before __warn() is called,
>    suppressing the backtrace and stack dump. Note that on this path,
>    the WARN() format message may still appear in the kernel log since
>    __warn_printk() runs before the trap that enters __report_bug().

Would it make sense to output a 'backtrace suppressed due to running 
test' message in this latter case, so we don't just end up with the 
WARN() format message by itself? (My gut feeling is 'no, it isn't worth 
it', but it's food for thought.)

> 
> A helper function, `__kunit_is_suppressed_warning()`, walks an
> RCU-protected list of active suppressions, matching by current task.
> The suppression state is tied to the KUnit test lifecycle via
> kunit_add_action(), ensuring automatic cleanup at test exit.
> 
> The list of suppressed warnings is protected with RCU to allow
> concurrent read access without locks.
> 
> The implementation is deliberately simple and avoids architecture-specific
> optimizations to preserve portability.
> 
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
> Reviewed-by: Kees Cook <kees@kernel.org>
> Signed-off-by: Albert Esteve <aesteve@redhat.com>
> ---
>   include/kunit/bug.h  | 56 +++++++++++++++++++++++++++++++++++
>   include/kunit/test.h |  1 +
>   kernel/panic.c       |  8 ++++-
>   lib/bug.c            |  8 +++++
>   lib/kunit/Kconfig    |  9 ++++++
>   lib/kunit/Makefile   |  6 ++--
>   lib/kunit/bug.c      | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   7 files changed, 169 insertions(+), 3 deletions(-)
> 
> diff --git a/include/kunit/bug.h b/include/kunit/bug.h
> new file mode 100644
> index 0000000000000..e52c9d21d9fe6
> --- /dev/null
> +++ b/include/kunit/bug.h

It's a bit confusing to name this bug.h when we have the (admittedly 
terribly-named) test-bug.h header already. I'm pretty tempted to rename 
the latter to something like 'hooks.h', as that's really what it's for, 
and having a separate bug.h would be an incentive to do so, though, sit 
it's not a big problem.

I do think that it'd be reasonable to include the backtrace suppression 
tuff in the same file, though, if you'd rather. The 
__kunit_is_suppressed_warning() stuff in particular fits the category of 
"code called to change behaviour based on whether or not a test is 
running", which is generally what the hooks are for. (And, if you'd 
rather, there's a bunch of existing hooks and hook infrastructure you 
could use.)

> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * KUnit helpers for backtrace suppression
> + *
> + * Copyright (C) 2025 Alessandro Carminati <acarmina@redhat.com>
> + * Copyright (C) 2024 Guenter Roeck <linux@roeck-us.net>
> + */
> +
> +#ifndef _KUNIT_BUG_H
> +#define _KUNIT_BUG_H
> +
> +#ifndef __ASSEMBLY__
> +
> +#include <linux/kconfig.h>
> +
> +struct kunit;
> +
> +#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
> +
> +#include <linux/types.h>
> +
> +struct task_struct;
> +
> +struct __suppressed_warning {
> +	struct list_head node;
> +	struct task_struct *task;
> +	int counter;
> +};
> +
> +struct __suppressed_warning *
> +__kunit_start_suppress_warning(struct kunit *test);
> +void __kunit_end_suppress_warning(struct kunit *test,
> +				  struct __suppressed_warning *warning);
> +int __kunit_suppressed_warning_count(struct __suppressed_warning *warning);
> +bool __kunit_is_suppressed_warning(void);
> +
> +#define KUNIT_START_SUPPRESSED_WARNING(test) \
> +	struct __suppressed_warning *__kunit_suppress =	\
> +		__kunit_start_suppress_warning(test)
> +
> +#define KUNIT_END_SUPPRESSED_WARNING(test) \
> +	__kunit_end_suppress_warning(test, __kunit_suppress)
> +
> +#define KUNIT_SUPPRESSED_WARNING_COUNT() \
> +	__kunit_suppressed_warning_count(__kunit_suppress)

Using a local variable (__kunit_suppress) here means that all of the 
above macros must live in the same function. This is probably okay for 
most use-cases, but more complicated tests may have to structure things 
carefully. It also prevents there from being multiple START/END pairs in 
the same function, and the KUNIT_SUPPRESSED_WARNING_COUNT() macro from 
appearing before _START().

It also makes it less obvious that this cleans up nicely if the test 
exits uncleanly, as the variable will have gone out-of-scope. (But given 
we're just storing a pointer to heap-allocated memory, and 
kunit_add_action() is used, it should be okay.)

One other option would be to allocate the suppression as a named 
resource, which could then be retrieved from anywhere within the test 
with kunit_find_named_resource(). (Though handling nested suppressions 
gets a little more complicated here.)

Or you could make the struct __suppressed_warning pointer returned 
explicitly user-visible, and let the user pass it around (though that 
seems more work).


> +
> +#else /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
> +
> +#define KUNIT_START_SUPPRESSED_WARNING(test)
> +#define KUNIT_END_SUPPRESSED_WARNING(test)
> +#define KUNIT_SUPPRESSED_WARNING_COUNT() 0
> +static inline bool __kunit_is_suppressed_warning(void) { return false; }
> +
> +#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
> +#endif /* __ASSEMBLY__ */
> +#endif /* _KUNIT_BUG_H */
> diff --git a/include/kunit/test.h b/include/kunit/test.h
> index 9cd1594ab697d..4ec07b3fa0204 100644
> --- a/include/kunit/test.h
> +++ b/include/kunit/test.h
> @@ -10,6 +10,7 @@
>   #define _KUNIT_TEST_H
>   
>   #include <kunit/assert.h>
> +#include <kunit/bug.h>
>   #include <kunit/try-catch.h>
>   
>   #include <linux/args.h>
> diff --git a/kernel/panic.c b/kernel/panic.c
> index c78600212b6c1..d7a7a679f56c4 100644
> --- a/kernel/panic.c
> +++ b/kernel/panic.c
> @@ -39,6 +39,7 @@
>   #include <linux/sys_info.h>
>   #include <trace/events/error_report.h>
>   #include <asm/sections.h>
> +#include <kunit/bug.h>
>   
>   #define PANIC_TIMER_STEP 100
>   #define PANIC_BLINK_SPD 18
> @@ -1080,9 +1081,14 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
>   void warn_slowpath_fmt(const char *file, int line, unsigned taint,
>   		       const char *fmt, ...)
>   {
> -	bool rcu = warn_rcu_enter();
> +	bool rcu;
>   	struct warn_args args;
>   
> +	if (__kunit_is_suppressed_warning())
> +		return;
> +
> +	rcu = warn_rcu_enter();
> +
>   	pr_warn(CUT_HERE);
>   
>   	if (!fmt) {
> diff --git a/lib/bug.c b/lib/bug.c
> index 623c467a8b76c..606205c8c302f 100644
> --- a/lib/bug.c
> +++ b/lib/bug.c
> @@ -48,6 +48,7 @@
>   #include <linux/rculist.h>
>   #include <linux/ftrace.h>
>   #include <linux/context_tracking.h>
> +#include <kunit/bug.h>
>   
>   extern struct bug_entry __start___bug_table[], __stop___bug_table[];
>   
> @@ -223,6 +224,13 @@ static enum bug_trap_type __report_bug(struct bug_entry *bug, unsigned long buga
>   	no_cut   = bug->flags & BUGFLAG_NO_CUT_HERE;
>   	has_args = bug->flags & BUGFLAG_ARGS;
>   
> +	/*
> +	 * Before the once logic so suppressed warnings do not consume
> +	 * the single-fire budget of WARN_ON_ONCE().
> +	 */
> +	if (warning && __kunit_is_suppressed_warning())
> +		return BUG_TRAP_TYPE_WARN;
> +

While any competant optimiser should get rid of this entirely, it might 
be clearer to anyone reading it that this disappears if we just put it 
behind an #ifdef?

>   	if (warning && once) {
>   		if (done)
>   			return BUG_TRAP_TYPE_WARN;
> diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig
> index 498cc51e493dc..57527418fcf09 100644
> --- a/lib/kunit/Kconfig
> +++ b/lib/kunit/Kconfig
> @@ -15,6 +15,15 @@ menuconfig KUNIT
>   
>   if KUNIT
>   
> +config KUNIT_SUPPRESS_BACKTRACE
> +	bool "KUnit - Enable backtrace suppression"
> +	default y
> +	help
> +	  Enable backtrace suppression for KUnit. If enabled, backtraces
> +	  generated intentionally by KUnit tests are suppressed. Disable
> +	  to reduce kernel image size if image size is more important than
> +	  suppression of backtraces generated by KUnit tests.
> +
>   config KUNIT_DEBUGFS
>   	bool "KUnit - Enable /sys/kernel/debug/kunit debugfs representation" if !KUNIT_ALL_TESTS
>   	default KUNIT_ALL_TESTS
> diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
> index 656f1fa35abcc..fe177ff3ebdef 100644
> --- a/lib/kunit/Makefile
> +++ b/lib/kunit/Makefile
> @@ -16,8 +16,10 @@ ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
>   kunit-objs +=				debugfs.o
>   endif
>   
> -# KUnit 'hooks' are built-in even when KUnit is built as a module.
> -obj-$(if $(CONFIG_KUNIT),y) +=		hooks.o
> +# KUnit 'hooks' and bug handling are built-in even when KUnit is built
> +# as a module.
> +obj-$(if $(CONFIG_KUNIT),y) +=		hooks.o \
> +					bug.o

Is there any reason we couldn't implement this on top of the hooks 
mechanism? Then we could include the bug suppression code in the 
kunit.ko module (albeit, with fewer possibilities for the compiler to 
optimise things, as they'd have to go through an indirect pointer).


>   
>   obj-$(CONFIG_KUNIT_TEST) +=		kunit-test.o
>   obj-$(CONFIG_KUNIT_TEST) +=		platform-test.o
> diff --git a/lib/kunit/bug.c b/lib/kunit/bug.c
> new file mode 100644
> index 0000000000000..356c8a5928828
> --- /dev/null
> +++ b/lib/kunit/bug.c
> @@ -0,0 +1,84 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * KUnit helpers for backtrace suppression
> + *
> + * Copyright (C) 2025 Alessandro Carminati <acarmina@redhat.com>
> + * Copyright (C) 2024 Guenter Roeck <linux@roeck-us.net>
> + */
> +
> +#include <kunit/bug.h>
> +#include <kunit/resource.h>
> +#include <linux/export.h>
> +#include <linux/rculist.h>
> +#include <linux/sched.h>
> +
> +#ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
> +
> +static LIST_HEAD(suppressed_warnings);
> +
> +static void __kunit_suppress_warning_remove(struct __suppressed_warning *warning)
> +{
> +	list_del_rcu(&warning->node);
> +	synchronize_rcu(); /* Wait for readers to finish */
> +}
> +
> +KUNIT_DEFINE_ACTION_WRAPPER(__kunit_suppress_warning_cleanup,
> +			    __kunit_suppress_warning_remove,
> +			    struct __suppressed_warning *);
> +
> +struct __suppressed_warning *
> +__kunit_start_suppress_warning(struct kunit *test)
> +{
> +	struct __suppressed_warning *warning;
> +	int ret;
> +
> +	warning = kunit_kzalloc(test, sizeof(*warning), GFP_KERNEL);
> +	if (!warning)
> +		return NULL;
> +
> +	warning->task = current;
> +	list_add_rcu(&warning->node, &suppressed_warnings);
> +
> +	ret = kunit_add_action_or_reset(test,
> +					__kunit_suppress_warning_cleanup,
> +					warning);
> +	if (ret)
> +		return NULL;
> +
> +	return warning;
> +}
> +EXPORT_SYMBOL_GPL(__kunit_start_suppress_warning);
> +
> +void __kunit_end_suppress_warning(struct kunit *test,
> +				  struct __suppressed_warning *warning)
> +{
> +	if (!warning)
> +		return;
> +	kunit_release_action(test, __kunit_suppress_warning_cleanup, warning);
> +}
> +EXPORT_SYMBOL_GPL(__kunit_end_suppress_warning);
> +
> +int __kunit_suppressed_warning_count(struct __suppressed_warning *warning)
> +{
> +	return warning ? warning->counter : 0;
> +}
> +EXPORT_SYMBOL_GPL(__kunit_suppressed_warning_count);
> +
> +bool __kunit_is_suppressed_warning(void)
> +{
> +	struct __suppressed_warning *warning;
> +
> +	rcu_read_lock();
> +	list_for_each_entry_rcu(warning, &suppressed_warnings, node) {
> +		if (warning->task == current) {
> +			warning->counter++;
> +			rcu_read_unlock();
> +			return true;
> +		}
> +	}
> +	rcu_read_unlock();
> +
> +	return false;
> +}

Note to self: this is _not_ exported, as bug.c is being built-in 
regardless of whether or not KUnit is a module. If we used the hook 
system, it could live in kunit.ko, and would be manually exported by 
kunit_install_hooks()

> +
> +#endif /* CONFIG_KUNIT_SUPPRESS_BACKTRACE */
> 


Thanks again,
-- David

^ permalink raw reply

* Re: [PATCH v7 2/5] bug/kunit: Reduce runtime impact of warning backtrace suppression
From: David Gow @ 2026-04-22 12:19 UTC (permalink / raw)
  To: Albert Esteve, Arnd Bergmann, Brendan Higgins, Rae Moar,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton
  Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
	workflows, linux-doc, peterz, Alessandro Carminati
In-Reply-To: <20260420-kunit_add_support-v7-2-e8bc6e0f70de@redhat.com>

Le 20/04/2026 à 8:28 PM, Albert Esteve a écrit :
> From: Alessandro Carminati <acarmina@redhat.com>
> 
> KUnit support is not consistently present across distributions, some
> include it in their stock kernels, while others do not.
> While both KUNIT and KUNIT_SUPPRESS_BACKTRACE can be considered debug
> features, the fact that some distros ship with KUnit enabled means it's
> important to minimize the runtime impact of this patch.
> 
> To that end, this patch adds an atomic counter that tracks the number
> of active suppressions. __kunit_is_suppressed_warning() checks this
> counter first and returns immediately when no suppressions are active,
> avoiding RCU-protected list traversal in the common case.
> 
> Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
> Signed-off-by: Albert Esteve <aesteve@redhat.com>
> ---

I'm not sure how much of an improvement this is.

It might be worth putting things behind the kunit_running static branch.

You could even add a new kunit_has_suppressed_warnings static branch, 
though I doubt anyone's too worried about the runtime performance of 
WARN() during testing, but with no suppressions, so it's likely not 
worth it.

Have a look at, e.g., kunit_fail_current_test() in 
include/kunit/test-bug.h, which uses the existing hooks implementation 
and static branch to reduce the overhead as much as I'd expect we need. 
That'd also potentially let you move the backtrace suppression code into 
the kunit.ko module, so you're not even paying more than ~a pointer's 
worth of memory if no tests are even loaded.

Cheers,
-- David


^ permalink raw reply

* Re: [PATCH v7 3/5] kunit: Add backtrace suppression self-tests
From: David Gow @ 2026-04-22 12:20 UTC (permalink / raw)
  To: Albert Esteve, Arnd Bergmann, Brendan Higgins, Rae Moar,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton
  Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
	workflows, linux-doc, peterz, Guenter Roeck,
	Linux Kernel Functional Testing, Dan Carpenter,
	Alessandro Carminati, Kees Cook
In-Reply-To: <20260420-kunit_add_support-v7-3-e8bc6e0f70de@redhat.com>

Le 20/04/2026 à 8:28 PM, Albert Esteve a écrit :
> From: Guenter Roeck <linux@roeck-us.net>
> 
> Add unit tests to verify that warning backtrace suppression works,
> covering WARN() and WARN_ON() with direct calls, indirect calls
> through helper functions, and multiple warnings in a single window.
> 
> If backtrace suppression does _not_ work, the unit tests will likely
> trigger unsuppressed backtraces, which should actually help to get
> the affected architectures / platforms fixed.
> 
> Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
> Acked-by: Dan Carpenter <dan.carpenter@linaro.org>
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
> Signed-off-by: Albert Esteve <aesteve@redhat.com>
> ---

Thanks very much for including tests!

Maybe it'd be nice to test that the suppression is disabled after 
KUNIT_END_SUPPRESSED_WARNING(). Of course, then triggering an actual 
stacktrace would be a pain, but maybe we could check that 
__kunit_is_suppressed_warning() returns false? If you wanted to be 
really fancy, you could test that it returns false on another kthread 
even while the suppression is active, too, but I won't hold you to it. 
Equally, you could try setting up a fake test context and ensuring the 
cleanup is called correctly, but I think that's mostly covered by the 
existing KUnit resource tests.

Otherwise, looking good. A couple of other minor suggestions below, 
which may require some reworking of the __kunit_suppress scope, but all 
optional suggestions.

Reviewed-by: David Gow <david@davidgow.net>

>   lib/kunit/Makefile                     |  3 ++
>   lib/kunit/backtrace-suppression-test.c | 90 ++++++++++++++++++++++++++++++++++
>   2 files changed, 93 insertions(+)
> 
> diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
> index fe177ff3ebdef..b2f2b8ada7b71 100644
> --- a/lib/kunit/Makefile
> +++ b/lib/kunit/Makefile
> @@ -23,6 +23,9 @@ obj-$(if $(CONFIG_KUNIT),y) +=		hooks.o \
>   
>   obj-$(CONFIG_KUNIT_TEST) +=		kunit-test.o
>   obj-$(CONFIG_KUNIT_TEST) +=		platform-test.o
> +ifeq ($(CONFIG_KUNIT_SUPPRESS_BACKTRACE),y)
> +obj-$(CONFIG_KUNIT_TEST) +=		backtrace-suppression-test.o
> +endif
>   
>   # string-stream-test compiles built-in only.
>   ifeq ($(CONFIG_KUNIT_TEST),y)
> diff --git a/lib/kunit/backtrace-suppression-test.c b/lib/kunit/backtrace-suppression-test.c
> new file mode 100644
> index 0000000000000..2ba5dcb5fef35
> --- /dev/null
> +++ b/lib/kunit/backtrace-suppression-test.c
> @@ -0,0 +1,90 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * KUnit test for suppressing warning tracebacks.
> + *
> + * Copyright (C) 2024, Guenter Roeck
> + * Author: Guenter Roeck <linux@roeck-us.net>
> + */
> +
> +#include <kunit/test.h>
> +#include <linux/bug.h>
> +
> +static void backtrace_suppression_test_warn_direct(struct kunit *test)
> +{
> +	KUNIT_START_SUPPRESSED_WARNING(test);
> +	WARN(1, "This backtrace should be suppressed");
> +	KUNIT_END_SUPPRESSED_WARNING(test);
> +
> +	KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 1);
> +}
> +
> +static void trigger_backtrace_warn(void)
> +{
> +	WARN(1, "This backtrace should be suppressed");
> +}
> +
> +static void backtrace_suppression_test_warn_indirect(struct kunit *test)
> +{
> +	KUNIT_START_SUPPRESSED_WARNING(test);
> +	trigger_backtrace_warn();
> +	KUNIT_END_SUPPRESSED_WARNING(test);
> +
> +	KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 1);
> +}
> +
> +static void backtrace_suppression_test_warn_multi(struct kunit *test)
> +{
> +	KUNIT_START_SUPPRESSED_WARNING(test);
> +	WARN(1, "This backtrace should be suppressed");
> +	trigger_backtrace_warn();
> +	KUNIT_END_SUPPRESSED_WARNING(test);
> +
> +	KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 2);

Would it make sense to test KUNIT_SUPPRESSED_WARNING_COUNT() more 
thoroughly here by checking that it's 0 before any warnings, and 
checking that it's 1 in-between the two warnings?

Of course, the first case doesn't work due to __kunit_suppress not being 
defined, but if the implementation changes to support this, let's add it 
to the test, too.

> +}
> +
> +static void backtrace_suppression_test_warn_on_direct(struct kunit *test)
> +{
> +	if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE) && !IS_ENABLED(CONFIG_KALLSYMS))
> +		kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE or CONFIG_KALLSYMS");
> +
> +	KUNIT_START_SUPPRESSED_WARNING(test);
> +	WARN_ON(1);
> +	KUNIT_END_SUPPRESSED_WARNING(test);
> +
> +	KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 1);
> +}
> +
> +static void trigger_backtrace_warn_on(void)
> +{
> +	WARN_ON(1);
> +}
> +
> +static void backtrace_suppression_test_warn_on_indirect(struct kunit *test)
> +{
> +	if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE))
> +		kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE");
> +
> +	KUNIT_START_SUPPRESSED_WARNING(test);
> +	trigger_backtrace_warn_on();
> +	KUNIT_END_SUPPRESSED_WARNING(test);
> +
> +	KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 1);
> +}
> +
> +static struct kunit_case backtrace_suppression_test_cases[] = {
> +	KUNIT_CASE(backtrace_suppression_test_warn_direct),
> +	KUNIT_CASE(backtrace_suppression_test_warn_indirect),
> +	KUNIT_CASE(backtrace_suppression_test_warn_multi),
> +	KUNIT_CASE(backtrace_suppression_test_warn_on_direct),
> +	KUNIT_CASE(backtrace_suppression_test_warn_on_indirect),
> +	{}
> +};
> +
> +static struct kunit_suite backtrace_suppression_test_suite = {
> +	.name = "backtrace-suppression-test",
> +	.test_cases = backtrace_suppression_test_cases,
> +};
> +kunit_test_suites(&backtrace_suppression_test_suite);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("KUnit test to verify warning backtrace suppression");
> 


^ permalink raw reply

* Re: [PATCH v7 4/5] drm: Suppress intentional warning backtraces in scaling unit tests
From: David Gow @ 2026-04-22 12:20 UTC (permalink / raw)
  To: Albert Esteve, Arnd Bergmann, Brendan Higgins, Rae Moar,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton
  Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
	workflows, linux-doc, peterz, Guenter Roeck,
	Linux Kernel Functional Testing, Dan Carpenter, Maíra Canal,
	Alessandro Carminati, Simona Vetter
In-Reply-To: <20260420-kunit_add_support-v7-4-e8bc6e0f70de@redhat.com>

Le 20/04/2026 à 8:28 PM, Albert Esteve a écrit :
> From: Guenter Roeck <linux@roeck-us.net>
> 
> The drm_test_rect_calc_hscale and drm_test_rect_calc_vscale unit tests
> intentionally trigger warning backtraces by providing bad parameters to
> the tested functions. What is tested is the return value, not the existence
> of a warning backtrace. Suppress the backtraces to avoid clogging the
> kernel log and distraction from real problems.
> 
> Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
> Acked-by: Dan Carpenter <dan.carpenter@linaro.org>
> Acked-by: Maíra Canal <mcanal@igalia.com>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: David Airlie <airlied@gmail.com>
> Cc: Daniel Vetter <daniel@ffwll.ch>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
> Signed-off-by: Albert Esteve <aesteve@redhat.com>
> ---

Acked-by: David Gow <david@davidgow.net>

Some of the suggestions in the thread around __cleanup() et al. sound 
good to me, too. I suspect that it should work given the 
kunit_add_action() / resource system use anyway, so even if an assertion 
fires, things should be cleaned up properly.

Cheers,
-- David

>   drivers/gpu/drm/tests/drm_rect_test.c | 14 ++++++++++++++
>   1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/gpu/drm/tests/drm_rect_test.c b/drivers/gpu/drm/tests/drm_rect_test.c
> index 17e1f34b76101..1dd7d819165e7 100644
> --- a/drivers/gpu/drm/tests/drm_rect_test.c
> +++ b/drivers/gpu/drm/tests/drm_rect_test.c
> @@ -409,8 +409,15 @@ static void drm_test_rect_calc_hscale(struct kunit *test)
>   	const struct drm_rect_scale_case *params = test->param_value;
>   	int scaling_factor;
>   
> +	/*
> +	 * drm_rect_calc_hscale() generates a warning backtrace whenever bad
> +	 * parameters are passed to it. This affects all unit tests with an
> +	 * error code in expected_scaling_factor.
> +	 */
> +	KUNIT_START_SUPPRESSED_WARNING(test);
>   	scaling_factor = drm_rect_calc_hscale(&params->src, &params->dst,
>   					      params->min_range, params->max_range);
> +	KUNIT_END_SUPPRESSED_WARNING(test);
>   
>   	KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
>   }
> @@ -420,8 +427,15 @@ static void drm_test_rect_calc_vscale(struct kunit *test)
>   	const struct drm_rect_scale_case *params = test->param_value;
>   	int scaling_factor;
>   
> +	/*
> +	 * drm_rect_calc_vscale() generates a warning backtrace whenever bad
> +	 * parameters are passed to it. This affects all unit tests with an
> +	 * error code in expected_scaling_factor.
> +	 */
> +	KUNIT_START_SUPPRESSED_WARNING(test);
>   	scaling_factor = drm_rect_calc_vscale(&params->src, &params->dst,
>   					      params->min_range, params->max_range);
> +	KUNIT_END_SUPPRESSED_WARNING(test);
>   
>   	KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
>   }
> 


^ permalink raw reply

* Re: [PATCH v7 5/5] kunit: Add documentation for warning backtrace suppression API
From: David Gow @ 2026-04-22 12:20 UTC (permalink / raw)
  To: Albert Esteve, Arnd Bergmann, Brendan Higgins, Rae Moar,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Jonathan Corbet, Shuah Khan, Andrew Morton
  Cc: linux-kernel, linux-arch, linux-kselftest, kunit-dev, dri-devel,
	workflows, linux-doc, peterz, Guenter Roeck,
	Linux Kernel Functional Testing, Dan Carpenter,
	Alessandro Carminati, Kees Cook
In-Reply-To: <20260420-kunit_add_support-v7-5-e8bc6e0f70de@redhat.com>

Le 20/04/2026 à 8:28 PM, Albert Esteve a écrit :
> From: Guenter Roeck <linux@roeck-us.net>
> 
> Document API functions for suppressing warning backtraces.
> 
> Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
> Acked-by: Dan Carpenter <dan.carpenter@linaro.org>
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> Reviewed-by: David Gow <davidgow@google.com>
> Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
> Signed-off-by: Albert Esteve <aesteve@redhat.com>
> ---

Thanks -- it's always good to have documentation.

Apart from one note below, this looks good to me.

Reviewed-by: David Gow <david@davidgow.net>

Cheers,
-- David

>   Documentation/dev-tools/kunit/usage.rst | 30 +++++++++++++++++++++++++++++-
>   1 file changed, 29 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst
> index ebd06f5ea4550..76e85412f240e 100644
> --- a/Documentation/dev-tools/kunit/usage.rst
> +++ b/Documentation/dev-tools/kunit/usage.rst
> @@ -157,6 +157,34 @@ Alternatively, one can take full control over the error message by using
>   	if (some_setup_function())
>   		KUNIT_FAIL(test, "Failed to setup thing for testing");
>   
> +Suppressing warning backtraces
> +------------------------------
> +
> +Some unit tests trigger warning backtraces either intentionally or as side
> +effect. Such backtraces are normally undesirable since they distract from
> +the actual test and may result in the impression that there is a problem.
> +
> +Such backtraces can be suppressed with **task scope suppression**: while
> +``START`` / ``END`` is active on the current task, the backtrace and stack
> +dump from warnings on that task are suppressed. Wrap the call from your test
> +in that window, like shown in the following code.
> +
> +.. code-block:: c
> +
> +	static void some_test(struct kunit *test)
> +	{
> +		KUNIT_START_SUPPRESSED_WARNING(test);
> +		trigger_backtrace();
> +		KUNIT_END_SUPPRESSED_WARNING(test);
> +	}
> +
> +``KUNIT_SUPPRESSED_WARNING_COUNT()`` returns the number of suppressed backtraces.
> +If the suppressed backtrace was triggered on purpose, this can be used to check
> +if the backtrace was actually triggered.
> +
> +.. code-block:: c
> +
> +	KUNIT_EXPECT_EQ(test, KUNIT_SUPPRESSED_WARNING_COUNT(), 1);


It might be worth noting that all of these must be in the same function, 
and the KUNIT_START_SUPPRESSED_WARNING() must be first. (And, in 
addition, there can't be more than one START/END pair per-function).

Of course, if the implementation is changed, that wouldn't be necessary. :-)
>   
>   Test Suites
>   ~~~~~~~~~~~
> @@ -1211,4 +1239,4 @@ For example:
>   		dev_managed_string = devm_kstrdup(fake_device, "Hello, World!");
>   
>   		// Everything is cleaned up automatically when the test ends.
> -	}
> \ No newline at end of file
> +	}
> 


^ permalink raw reply

* Re: [PATCH net 14/18] drivers: net: xircom: xirc2ps: Remove this driver
From: michael @ 2026-04-22 12:46 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Jonathan Corbet, Shuah Khan, linux-kernel, netdev,
	linux-doc
In-Reply-To: <408d1987-6ecb-4d3b-afed-8e202c8ff21d@lunn.ch>

Am 2026-04-22 14:15, schrieb Andrew Lunn:
> On Wed, Apr 22, 2026 at 08:21:23AM +0200, Michael Fritscher wrote:
>> Good day,
>> 
>> actually, I do use Xircom PCMCIA network cards (yes, the 16 bit ones) 
>> on
>> Lenovo X60/X61 laptops as a second LAN card for server maintenances 
>> with
>> current 64 bit distros (e.g. Debian Trixie, which I plan to update to
>> Trixie+1 when available). Why? Because I have them and they are 
>> working ;-)
> 
> Hi Michael
> 
> I will drop this from the patchset for the moment.
> 
> Would you be willing to take up the Maintainer role for it?
> 
> 	Andrew

Hello Andrew,

thanks! If someone mentors me I could try... I have experience with C 
programming, esp. in the embedded world, but (almost) no experience with 
the Linux kernel development.
But regression tests etc. can be conducted by me - on 32 and 64 bit 
machines. The oldest being a P120, the newest the mentioned X61 with its 
C2D CPU.

Best regards
Michael

^ permalink raw reply

* Re: [PATCH net 06/18] drivers: net: amd: Remove hplance and mvme147
From: Andrew Lunn @ 2026-04-22 12:50 UTC (permalink / raw)
  To: Daniel Palmer
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	linux-kernel, netdev, linux-doc
In-Reply-To: <CAFr9PXk=3md2oVDqFbmQLNiVMkRr32pHMPNSeskdTpM-1huB=A@mail.gmail.com>

On Wed, Apr 22, 2026 at 06:38:28AM +0900, Daniel Palmer wrote:
> Hi Andrew,
> 
> On Wed, 22 Apr 2026 at 04:39, Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > These drivers use the 7990 core with wrappers for the HP300 and
> > Motorola MVME147 SBC circa 1998. It is unlikely they are used with a
> > modern kernel.
> 
> I have an MVME147 blinking away running mainline using the mvme147 driver.
> I think some of these need to be CC'd to the specific arch lists so
> the few people using them get a chance to pipe up.

That is part of the problem. No MAINTAINERs entry. so
./scripts/get_maintainers.py does not add an Cc: to the list.

> I think I'm the last person to have touched the mvme147, I don't mind
> being a maintainer for it.

Please submit an entry for MAINTAINERs.

I will drop this patch.

  Andrew

^ permalink raw reply

* Re: [PATCH net-deletions v2] net: remove unused ATM protocols and legacy ATM device drivers
From: David Woodhouse @ 2026-04-22 13:05 UTC (permalink / raw)
  To: Jakub Kicinski, davem, openwrt-devel, Guy Ellis
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, corbet, skhan,
	linux, tsbogend, maddy, mpe, npiggin, chleroy, 3chas3, razor,
	idosch, jani.nikula, mchehab+huawei, tytso, herbert, geert,
	ebiggers, johannes.berg, jonathan.cameron, kees, kuniyu,
	fourier.thomas, andriy.shevchenko, rdunlap, akpm, linux-doc,
	linux-mips, linuxppc-dev, bridge
In-Reply-To: <20260422041846.2035118-1-kuba@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 885 bytes --]

On Tue, 2026-04-21 at 21:18 -0700, Jakub Kicinski wrote:
> 
>    I'm still deleting the solos driver, chances are nobody uses it.
>    Easy enough to revert back in since core is still around.
>    The guiding principle is to keep USB modems and delete
>    the rest as USB ADSL2+ CPEs were most popular historically.

Still not entirely convinced; I worked on both USB ATM modems and on
Solos, and the Solos is both the most modern and the only one I still
actually have. And the only one we have native support for that could
ever do full 24Mb/s ADSL2+, I believe.

If we drop it, OpenWrt will need to drop support for these, which I
think were quite popular at the time; there were a few UK resellers:
https://openwrt.org/toh/traverse/geos1_1

I still don't actually care *enough* to try to find an ADSL line I
could plug one into for testing though... :)

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]

^ permalink raw reply

* Re: [PATCH net 14/18] drivers: net: xircom: xirc2ps: Remove this driver
From: Andrew Lunn @ 2026-04-22 13:09 UTC (permalink / raw)
  To: michael
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Jonathan Corbet, Shuah Khan, linux-kernel, netdev,
	linux-doc
In-Reply-To: <e36510873a1909a1bfd9a05cde99fef0@fritscher.net>

> thanks! If someone mentors me I could try... I have experience with C
> programming, esp. in the embedded world, but (almost) no experience with the
> Linux kernel development.
> But regression tests etc. can be conducted by me - on 32 and 64 bit
> machines. The oldest being a P120, the newest the mentioned X61 with its C2D
> CPU.

For a driver like this, regression testing is mostly what we need,
when we see patches for it.

Please take a look at the MAINTAINERs file, and see if you can send us
a patch adding yourself as the Maintainer of this driver.

Some documents to read:

https://docs.kernel.org/process/submitting-patches.html
https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html

For patches to MAINTAINERS, please base the patch on net.

    Andrew

^ permalink raw reply

* Re: [PATCH net-deletions v2] net: remove unused ATM protocols and legacy ATM device drivers
From: Nikolay Aleksandrov @ 2026-04-22 13:17 UTC (permalink / raw)
  To: Jakub Kicinski, davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, corbet, skhan,
	linux, tsbogend, maddy, mpe, npiggin, chleroy, 3chas3, idosch,
	jani.nikula, mchehab+huawei, tytso, herbert, geert, ebiggers,
	johannes.berg, jonathan.cameron, kees, kuniyu, fourier.thomas,
	andriy.shevchenko, rdunlap, akpm, linux-doc, linux-mips,
	linuxppc-dev, bridge, dwmw2
In-Reply-To: <20260422041846.2035118-1-kuba@kernel.org>

On 22/04/2026 07:18, Jakub Kicinski wrote:
> Remove the ATM protocol modules and PCI/SBUS ATM device drivers
> that are no longer in active use.
> 
> The ATM core protocol stack, PPPoATM, BR2684, and USB DSL modem
> drivers (drivers/usb/atm/) are retained in-tree to maintain PPP
> over ATM (PPPoA) and PPPoE-over-BR2684 support for DSL connections.
> 
> Removed ATM protocol modules:
>   - net/atm/clip.c - Classical IP over ATM (RFC 2225)
>   - net/atm/lec.c - LAN Emulation Client (LANE)
>   - net/atm/mpc.c, mpoa_caches.c, mpoa_proc.c - Multi-Protocol Over ATM
> 
> Removed PCI/SBUS ATM device drivers (drivers/atm/):
>   - adummy, atmtcp - software/testing ATM devices
>   - eni - Efficient Networks ENI155P (OC-3, ~1995)
>   - fore200e - FORE Systems 200E PCI/SBUS (OC-3, ~1999)
>   - he - ForeRunner HE (OC-3/OC-12, ~2000)
>   - idt77105 - IDT 77105 25 Mbps ATM PHY
>   - idt77252 - IDT 77252 NICStAR II (OC-3, ~2000)
>   - iphase - Interphase ATM PCI (OC-3/DS3/E3)
>   - lanai - Efficient Networks Speedstream 3010
>   - nicstar - IDT 77201 NICStAR (155/25 Mbps, ~1999)
>   - solos-pci - Traverse Technologies ADSL2+ PCI
>   - suni - PMC S/UNI SONET PHY library
> 
> Also clean up references in:
>   - net/bridge/ - remove ATM LANE hook (br_fdb_test_addr_hook,
>     br_fdb_test_addr)
>   - net/core/dev.c - remove br_fdb_test_addr_hook export
>   - defconfig files - remove ATM driver config options
> 
> The removed code is moved to an out-of-tree module package (mod-orphan).
> 
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> v2:
>   - keep BR2684
>   - correct the claim that Traverse Technologies is defunct,
>     I'm still deleting the solos driver, chances are nobody uses it.
>     Easy enough to revert back in since core is still around.
>     The guiding principle is to keep USB modems and delete
>     the rest as USB ADSL2+ CPEs were most popular historically.
> v1: https://lore.kernel.org/20260421021943.1295109-1-kuba@kernel.org
> 
> CC: corbet@lwn.net
> CC: skhan@linuxfoundation.org
> CC: linux@armlinux.org.uk
> CC: tsbogend@alpha.franken.de
> CC: maddy@linux.ibm.com
> CC: mpe@ellerman.id.au
> CC: npiggin@gmail.com
> CC: chleroy@kernel.org
> CC: 3chas3@gmail.com
> CC: razor@blackwall.org
> CC: idosch@nvidia.com
> CC: jani.nikula@intel.com
> CC: mchehab+huawei@kernel.org
> CC: tytso@mit.edu
> CC: herbert@gondor.apana.org.au
> CC: geert@linux-m68k.org
> CC: ebiggers@kernel.org
> CC: johannes.berg@intel.com
> CC: jonathan.cameron@huawei.com
> CC: kees@kernel.org
> CC: kuniyu@google.com
> CC: fourier.thomas@gmail.com
> CC: andriy.shevchenko@intel.com
> CC: rdunlap@infradead.org
> CC: akpm@linux-foundation.org
> CC: linux-doc@vger.kernel.org
> CC: linux-mips@vger.kernel.org
> CC: linuxppc-dev@lists.ozlabs.org
> CC: bridge@lists.linux.dev
> CC: dwmw2@infradead.org
> CC: herbert@gondor.apana.org.au
> ---
>   MAINTAINERS                                   |    3 +-
>   Documentation/.renames.txt                    |    2 -
>   .../device_drivers/atm/fore200e.rst           |   66 -
>   .../networking/device_drivers/atm/index.rst   |    2 -
>   .../networking/device_drivers/atm/iphase.rst  |  193 -
>   drivers/atm/Kconfig                           |  325 --
>   drivers/net/Kconfig                           |    2 -
>   net/atm/Kconfig                               |   37 -
>   drivers/Makefile                              |    1 -
>   drivers/atm/Makefile                          |   32 -
>   net/atm/Makefile                              |    4 -
>   drivers/atm/eni.h                             |  136 -
>   drivers/atm/fore200e.h                        |  973 -----
>   drivers/atm/he.h                              |  845 ----
>   drivers/atm/idt77105.h                        |   92 -
>   drivers/atm/idt77252.h                        |  816 ----
>   drivers/atm/idt77252_tables.h                 |  781 ----
>   drivers/atm/iphase.h                          | 1452 -------
>   drivers/atm/midway.h                          |  266 --
>   drivers/atm/nicstar.h                         |  759 ----
>   drivers/atm/suni.h                            |  242 --
>   drivers/atm/tonga.h                           |   21 -
>   drivers/atm/zeprom.h                          |   35 -
>   net/atm/lec.h                                 |  155 -
>   net/atm/lec_arpc.h                            |   97 -
>   net/atm/mpc.h                                 |   65 -
>   net/atm/mpoa_caches.h                         |   99 -
>   net/bridge/br_private.h                       |    4 -
>   drivers/atm/adummy.c                          |  202 -
>   drivers/atm/atmtcp.c                          |  513 ---
>   drivers/atm/eni.c                             | 2321 ----------
>   drivers/atm/fore200e.c                        | 3012 -------------
>   drivers/atm/he.c                              | 2861 -------------
>   drivers/atm/idt77105.c                        |  376 --
>   drivers/atm/idt77252.c                        | 3797 -----------------
>   drivers/atm/iphase.c                          | 3283 --------------
>   drivers/atm/lanai.c                           | 2603 -----------
>   drivers/atm/nicstar.c                         | 2759 ------------
>   drivers/atm/nicstarmac.c                      |  244 --
>   drivers/atm/solos-attrlist.c                  |   83 -
>   drivers/atm/solos-pci.c                       | 1496 -------
>   drivers/atm/suni.c                            |  391 --
>   net/atm/clip.c                                |  960 -----
>   net/atm/lec.c                                 | 2274 ----------
>   net/atm/mpc.c                                 | 1538 -------
>   net/atm/mpoa_caches.c                         |  565 ---
>   net/atm/mpoa_proc.c                           |  307 --
>   net/bridge/br.c                               |    7 -
>   net/bridge/br_fdb.c                           |   29 -
>   net/core/dev.c                                |    7 -
>   arch/arm/configs/ixp4xx_defconfig             |    5 -
>   arch/mips/configs/gpr_defconfig               |   13 -
>   arch/mips/configs/mtx1_defconfig              |   13 -
>   arch/powerpc/configs/ppc6xx_defconfig         |    9 -
>   drivers/atm/.gitignore                        |    5 -
>   drivers/atm/nicstarmac.copyright              |   61 -
>   56 files changed, 2 insertions(+), 37237 deletions(-)
>   delete mode 100644 Documentation/networking/device_drivers/atm/fore200e.rst
>   delete mode 100644 Documentation/networking/device_drivers/atm/iphase.rst
>   delete mode 100644 drivers/atm/Kconfig
>   delete mode 100644 drivers/atm/Makefile
>   delete mode 100644 drivers/atm/eni.h
>   delete mode 100644 drivers/atm/fore200e.h
>   delete mode 100644 drivers/atm/he.h
>   delete mode 100644 drivers/atm/idt77105.h
>   delete mode 100644 drivers/atm/idt77252.h
>   delete mode 100644 drivers/atm/idt77252_tables.h
>   delete mode 100644 drivers/atm/iphase.h
>   delete mode 100644 drivers/atm/midway.h
>   delete mode 100644 drivers/atm/nicstar.h
>   delete mode 100644 drivers/atm/suni.h
>   delete mode 100644 drivers/atm/tonga.h
>   delete mode 100644 drivers/atm/zeprom.h
>   delete mode 100644 net/atm/lec.h
>   delete mode 100644 net/atm/lec_arpc.h
>   delete mode 100644 net/atm/mpc.h
>   delete mode 100644 net/atm/mpoa_caches.h
>   delete mode 100644 drivers/atm/adummy.c
>   delete mode 100644 drivers/atm/atmtcp.c
>   delete mode 100644 drivers/atm/eni.c
>   delete mode 100644 drivers/atm/fore200e.c
>   delete mode 100644 drivers/atm/he.c
>   delete mode 100644 drivers/atm/idt77105.c
>   delete mode 100644 drivers/atm/idt77252.c
>   delete mode 100644 drivers/atm/iphase.c
>   delete mode 100644 drivers/atm/lanai.c
>   delete mode 100644 drivers/atm/nicstar.c
>   delete mode 100644 drivers/atm/nicstarmac.c
>   delete mode 100644 drivers/atm/solos-attrlist.c
>   delete mode 100644 drivers/atm/solos-pci.c
>   delete mode 100644 drivers/atm/suni.c
>   delete mode 100644 net/atm/clip.c
>   delete mode 100644 net/atm/lec.c
>   delete mode 100644 net/atm/mpc.c
>   delete mode 100644 net/atm/mpoa_caches.c
>   delete mode 100644 net/atm/mpoa_proc.c
>   delete mode 100644 drivers/atm/.gitignore
>   delete mode 100644 drivers/atm/nicstarmac.copyright
> 

FWIW,
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>



^ permalink raw reply

* Incorrect auto formatting of struct
From: Daniel Lundberg Pedersen @ 2026-04-22 13:37 UTC (permalink / raw)
  To: linux-doc

Hi

I've just noticed that between v6.16 and v6.17 the documentation has started to
highlight struct that are not structs, e.g `struct inside`:

https://www.kernel.org/doc/html/v6.17/driver-api/media/v4l2-device.html

Previously it did not highlight this as a struct:

https://www.kernel.org/doc/html/v6.16/driver-api/media/v4l2-device.html

I couldn't find anything about whether this is intentional and thus needs doc
fixes, or if it was already reported, it's not that easy to search for.


Regards Daniel

^ permalink raw reply


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