Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 1/1] selftests: net: fix file owner for broadcast_ether_dst test
From: Jakub Kicinski @ 2026-06-13 21:32 UTC (permalink / raw)
  To: ross.porter
  Cc: Jakub Kicinski, linux-kselftest, netdev, stable, edoardo.canepa,
	davem, edumazet, pabeni, horms, shuah, oscmaes92, bacs,
	linux-kernel
In-Reply-To: <20260610062230.71573-2-ross.porter@canonical.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
selftests: net: fix file owner for broadcast_ether_dst test

This commit ensures the tcpdump output file in the broadcast_ether_dst test
is always owned by root by passing the -Z root argument.

> diff --git a/tools/testing/selftests/net/broadcast_ether_dst.sh b/tools/testing/selftests/net/broadcast_ether_dst.sh
> --- a/tools/testing/selftests/net/broadcast_ether_dst.sh
> +++ b/tools/testing/selftests/net/broadcast_ether_dst.sh
> @@ -44,7 +44,7 @@ test_broadcast_ether_dst() {
>  	# tcpdump will exit after receiving a single packet
>  	# timeout will kill tcpdump if it is still running after 2s
>  	timeout 2s ip netns exec "${CLIENT_NS}" \
> -		tcpdump -i link0 -c 1 -w "${CAPFILE}" icmp &> "${OUTPUT}" &
> +		tcpdump -i link0 -c 1 -w "${CAPFILE}" icmp -Z root &> "${OUTPUT}" &

[Severity: Medium]
Will this tcpdump command fail with a syntax error in test_broadcast_ether_dst()
on systems that use musl libc or when POSIXLY_CORRECT is set?

By placing the -Z root option after the positional filter expression icmp,
standard POSIX option parsing will stop at the first non-option argument.

While this works on glibc systems because getopt() permutes arguments by
default, on strict POSIX systems tcpdump might treat -Z root as part of the
filter expression. This would concatenate the arguments into "icmp -Z root"
and cause a fatal pcap filter compilation error, breaking the selftest
unconditionally in those environments.

Could the -Z root argument be moved before the icmp filter expression?
-- 
pw-bot: cr

^ permalink raw reply

* Re: [PATCH net v2] net/sched: cake: reject overhead values that underflow length
From: Jakub Kicinski @ 2026-06-13 21:26 UTC (permalink / raw)
  To: Samuel Moelius
  Cc: Toke Høiland-Jørgensen, Jamal Hadi Salim, Jiri Pirko,
	David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman,
	moderated list:CAKE QDISC, open list:TC subsystem, open list
In-Reply-To: <20260609232935.1602659.8545fdb04fbe.cake-overhead-underflow@trailofbits.com>

On Tue,  9 Jun 2026 23:29:36 +0000 Samuel Moelius wrote:
> +static const struct netlink_range_validation_signed cake_overhead_range = {
> +	.min = -64,
> +	.max = 256,

Both Sashiko's complain - these values are neither safe nor sufficient.

How was the -64 chosen? It looks suspiciously close the min ethernet
frame length. But in that case (a) FCS doesn't count so 60, and 
(b) even IPv4 TCP packets can be shorter (at qdisc layer) than 64B
leading to underflow...

I see min rate in cake is 64 but I don't see any other meaning of the
64 literal.

Toke, WDYT? Should we use a smaller constant (ETH_HLEN?) or do the
check on the datapath?

Also - small constants fit directly in nla_policy, you don't need
struct netlink_range_validation_signed 
-- 
pw-bot: cr

^ permalink raw reply

* Re: [RFC PATCH bpf-next 0/5] tcp: opportunistic loopback splice for BPF-paired sockets
From: Cong Wang @ 2026-06-13 21:25 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Alexei Starovoitov, Cong Wang, Network Development, bpf,
	John Fastabend, Jakub Sitnicki, Jiayuan Chen, Hemanth Malla,
	zijianzhang
In-Reply-To: <20260613105730.0ca1ca07@kernel.org>

On Sat, Jun 13, 2026 at 10:57:30AM -0700, Jakub Kicinski wrote:
> On Fri, 12 Jun 2026 09:01:43 -0700 Alexei Starovoitov wrote:
> > Just saying that the code is free nowadays, so whether it's 1k lines
> > or 10 lines is irrelevant for the discussion.
> > 
> > As far as the idea goes, I think, it would be interesting in pre-AI era,
> > but today splice and friends are a prime target for bugs and more bugs.
> > skmsg and tcp_bpf are reeling from unfixed bugs too,
> > so my take is that we should not add any new features to skmsg
> > and instead deprecate what is already there.
> 
> 100% agreed. There are so many unfixed skmsg bugs it's hard to know
> were to start :( Kernel "intelligence" to help unoptimized applications
> is particularly unappealing right now.

You are absolutely right. :)

Thanks for offering opportunity for me to make profit out of it.

^ permalink raw reply

* Re: [PATCH 1/3 net-next v6] ipv4: centralize devconf sysctl handling
From: patchwork-bot+netdevbpf @ 2026-06-13 21:20 UTC (permalink / raw)
  To: Fernando Fernandez Mancera
  Cc: netdev, horms, pabeni, kuba, edumazet, dsahern, idosch, davem,
	nicolas.dichtel
In-Reply-To: <20260609204520.4670-1-fmancera@suse.de>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Tue,  9 Jun 2026 22:45:18 +0200 you wrote:
> The logic for handling IPv4 devconf sysctls is scattered. Notification
> and cache flushes are managed in devinet_conf_proc(), while a separate
> ipv4_doint_and_flush() function and DEVINET_SYSCTL_FLUSHING_ENTRY macro
> is used for properties that solely require a cache flush.
> 
> This patch refactors the sysctl handling by introducing a centralized
> helper, devinet_conf_post_set(). This new function evaluates the changed
> attribute and handles all necessary operations like triggering netlink
> notifications. It returns a boolean indicating whether a routing cache
> flush is required.
> 
> [...]

Here is the summary with links:
  - [1/3,net-next,v6] ipv4: centralize devconf sysctl handling
    https://git.kernel.org/netdev/net-next/c/3a29b55505f3
  - [2/3,net-next,v6] ipv4: handle devconf post-set actions on netlink updates
    https://git.kernel.org/netdev/net-next/c/489730ec2a73
  - [3/3,net-next,v6] selftests: net: add test for IPv4 devconf netlink notifications
    https://git.kernel.org/netdev/net-next/c/32229484e381

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH net-next] tcp: refine tcp_sequence() for the FIN exception
From: patchwork-bot+netdevbpf @ 2026-06-13 21:20 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: davem, kuba, pabeni, horms, ncardwell, kuniyu, netdev,
	eric.dumazet, gmbnomis
In-Reply-To: <20260608151452.706822-1-edumazet@google.com>

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Mon,  8 Jun 2026 15:14:52 +0000 you wrote:
> Commit 0e24d17bd966 ("tcp: implement RFC 7323 window retraction
> receiver requirements") removed the special FIN case that
> was added in commit 1e3bb184e941 ("tcp: re-enable acceptance of
> FIN packets when RWIN is 0").
> 
> If a peer sends a segment containing data and a FIN flag before
> it learns about our window retraction and has a buggy TCP stack,
> it might place the FIN one byte beyond what it thinks is the
> right edge of the window (i.e., max_window_edge + 1).
> 
> [...]

Here is the summary with links:
  - [net-next] tcp: refine tcp_sequence() for the FIN exception
    https://git.kernel.org/netdev/net-next/c/91934d44468d

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* [PATCH net-next v4] net: mana: Add Interrupt Moderation support
From: Haiyang Zhang @ 2026-06-13 20:57 UTC (permalink / raw)
  To: linux-hyperv, netdev, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
	Dexuan Cui, Long Li, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Konstantin Taranov, Simon Horman,
	Shradha Gupta, Erni Sri Satya Vennela, Dipayaan Roy, Aditya Garg,
	Breno Leitao, linux-kernel, linux-rdma
  Cc: paulros

From: Haiyang Zhang <haiyangz@microsoft.com>

Add Static and Dynamic Interrupt Moderation (DIM) support for
Rx and Tx.
Update queue creation procedure with new data struct with the related
settings.
Add functions to collect stat for DIM, and workers to update DIM data
and settings.
Update ethtool handler to get/set the moderation settings from a user.
To avoid detach/re-attach ops, ring DIM doorbell to change settings
at run time.
By default, adaptive-rx/tx (DIM) are enabled if supported by HW.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
v4:
  Fixed tx stat, concurrency, and mb issues from Simon's review.

v3:
  Updated to avoid detach/re-attach ops as suggested by Paolo.

v2:
  Updated with comments from Jedrzej.

---
 drivers/net/ethernet/microsoft/Kconfig        |   1 +
 .../net/ethernet/microsoft/mana/gdma_main.c   |  29 +++
 drivers/net/ethernet/microsoft/mana/mana_en.c | 171 ++++++++++++++++++
 .../ethernet/microsoft/mana/mana_ethtool.c    | 167 ++++++++++++++++-
 include/net/mana/gdma.h                       |  24 ++-
 include/net/mana/mana.h                       |  54 ++++++
 6 files changed, 437 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/Kconfig b/drivers/net/ethernet/microsoft/Kconfig
index 3f36ee6a8ece..e9be18c92ca5 100644
--- a/drivers/net/ethernet/microsoft/Kconfig
+++ b/drivers/net/ethernet/microsoft/Kconfig
@@ -21,6 +21,7 @@ config MICROSOFT_MANA
 	depends on X86_64 || (ARM64 && !CPU_BIG_ENDIAN)
 	depends on PCI_HYPERV
 	select AUXILIARY_BUS
+	select DIMLIB
 	select PAGE_POOL
 	select NET_SHAPER
 	help
diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
index c9ec80a1dd6f..7a012b1e5751 100644
--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /* Copyright (c) 2021, Microsoft Corporation. */
 
+#include <linux/bitfield.h>
 #include <linux/debugfs.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -464,6 +465,7 @@ static int mana_gd_disable_queue(struct gdma_queue *queue)
 #define DOORBELL_OFFSET_RQ	0x400
 #define DOORBELL_OFFSET_CQ	0x800
 #define DOORBELL_OFFSET_EQ	0xFF8
+#define DOORBELL_OFFSET_DIM	0x820
 
 static void mana_gd_ring_doorbell(struct gdma_context *gc, u32 db_index,
 				  enum gdma_queue_type q_type, u32 qid,
@@ -504,6 +506,16 @@ static void mana_gd_ring_doorbell(struct gdma_context *gc, u32 db_index,
 		addr += DOORBELL_OFFSET_SQ;
 		break;
 
+	case GDMA_DIM:
+		e.dim.id = qid;
+		e.dim.mod_usec = FIELD_GET(MANA_INTR_MODR_USEC_MAX, tail_ptr);
+		e.dim.mod_usec_vld = !!(tail_ptr & MANA_INTR_MODR_USEC_VLD);
+		e.dim.mod_comps = FIELD_GET(MANA_INTR_MODR_COMP_MASK, tail_ptr);
+		e.dim.mod_comps_vld = num_req;
+
+		addr += DOORBELL_OFFSET_DIM;
+		break;
+
 	default:
 		WARN_ON(1);
 		return;
@@ -538,6 +550,23 @@ void mana_gd_ring_cq(struct gdma_queue *cq, u8 arm_bit)
 }
 EXPORT_SYMBOL_NS(mana_gd_ring_cq, "NET_MANA");
 
+void mana_gd_ring_dim(struct gdma_queue *cq, u32 mod_usec, bool mod_usec_vld,
+		      u32 mod_comps, bool mod_comps_vld)
+{
+	struct gdma_context *gc = cq->gdma_dev->gdma_context;
+	u32 dim_val;
+
+	/* Convert the DIM values to doorbell parameters */
+	dim_val = FIELD_PREP(MANA_INTR_MODR_USEC_MAX, mod_usec) |
+		  FIELD_PREP(MANA_INTR_MODR_COMP_MASK, mod_comps);
+	if (mod_usec_vld)
+		dim_val |= MANA_INTR_MODR_USEC_VLD;
+
+	mana_gd_ring_doorbell(gc, cq->gdma_dev->doorbell, GDMA_DIM, cq->id,
+			      dim_val, mod_comps_vld);
+}
+EXPORT_SYMBOL_NS(mana_gd_ring_dim, "NET_MANA");
+
 #define MANA_SERVICE_PERIOD 10
 
 static void mana_serv_rescan(struct pci_dev *pdev)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 26aef21c6c2c..d36850084f2e 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1579,6 +1579,9 @@ int mana_create_wq_obj(struct mana_port_context *apc,
 
 	mana_gd_init_req_hdr(&req.hdr, MANA_CREATE_WQ_OBJ,
 			     sizeof(req), sizeof(resp));
+
+	req.hdr.req.msg_version = GDMA_MESSAGE_V3;
+	req.hdr.resp.msg_version = GDMA_MESSAGE_V2;
 	req.vport = vport;
 	req.wq_type = wq_type;
 	req.wq_gdma_region = wq_spec->gdma_region;
@@ -1587,6 +1590,9 @@ int mana_create_wq_obj(struct mana_port_context *apc,
 	req.cq_size = cq_spec->queue_size;
 	req.cq_moderation_ctx_id = cq_spec->modr_ctx_id;
 	req.cq_parent_qid = cq_spec->attached_eq;
+	req.req_cq_moderation = cq_spec->req_cq_moderation;
+	req.cq_moderation_comp = cq_spec->cq_moderation_comp;
+	req.cq_moderation_usec = cq_spec->cq_moderation_usec;
 
 	err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
 				sizeof(resp));
@@ -1844,6 +1850,7 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
 	struct gdma_posted_wqe_info *wqe_info;
 	unsigned int pkt_transmitted = 0;
 	unsigned int wqe_unit_cnt = 0;
+	unsigned int tx_bytes = 0;
 	struct mana_txq *txq = cq->txq;
 	struct mana_port_context *apc;
 	struct netdev_queue *net_txq;
@@ -1925,6 +1932,8 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
 
 		mana_unmap_skb(skb, apc);
 
+		tx_bytes += skb->len;
+
 		napi_consume_skb(skb, cq->budget);
 
 		pkt_transmitted++;
@@ -1955,6 +1964,10 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
 	if (atomic_sub_return(pkt_transmitted, &txq->pending_sends) < 0)
 		WARN_ON_ONCE(1);
 
+	/* Feed DIM with the completion rate observed here, in NAPI context. */
+	cq->tx_dim_pkts += pkt_transmitted;
+	cq->tx_dim_bytes += tx_bytes;
+
 	cq->work_done = pkt_transmitted;
 }
 
@@ -2306,6 +2319,119 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
 		xdp_do_flush();
 }
 
+static void mana_rx_dim_work(struct work_struct *work)
+{
+	struct dim *dim = container_of(work, struct dim, work);
+	struct dim_cq_moder cur_moder;
+	struct mana_cq *cq;
+
+	cur_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
+	cq = container_of(dim, struct mana_cq, dim);
+
+	cur_moder.usec = min_t(u16, cur_moder.usec, MANA_INTR_MODR_USEC_MAX);
+	cur_moder.pkts = min_t(u16, cur_moder.pkts, MANA_INTR_MODR_COMP_MAX);
+
+	mana_gd_ring_dim(cq->gdma_cq, cur_moder.usec, true,
+			 cur_moder.pkts, true);
+
+	dim->state = DIM_START_MEASURE;
+}
+
+static void mana_tx_dim_work(struct work_struct *work)
+{
+	struct dim *dim = container_of(work, struct dim, work);
+	struct dim_cq_moder cur_moder;
+	struct mana_cq *cq;
+
+	cur_moder = net_dim_get_tx_moderation(dim->mode, dim->profile_ix);
+	cq = container_of(dim, struct mana_cq, dim);
+
+	cur_moder.usec = min_t(u16, cur_moder.usec, MANA_INTR_MODR_USEC_MAX);
+	cur_moder.pkts = min_t(u16, cur_moder.pkts, MANA_INTR_MODR_COMP_MAX);
+
+	mana_gd_ring_dim(cq->gdma_cq, cur_moder.usec, true,
+			 cur_moder.pkts, true);
+
+	dim->state = DIM_START_MEASURE;
+}
+
+/* The caller must update apc->rx/tx_dim_enabled before disabling and
+ * after enabling. And synchronize_net() before draining the DIM work,
+ * so that NAPI cannot observe a stale flag.
+ */
+int mana_dim_change(struct mana_cq *cq, bool enable)
+{
+	bool is_rx = cq->type == MANA_CQ_TYPE_RX;
+	struct mana_port_context *apc;
+	work_func_t work_func;
+	u32 usec, comp;
+
+	if (is_rx) {
+		apc = netdev_priv(cq->rxq->ndev);
+		usec = apc->intr_modr_rx_usec;
+		comp = apc->intr_modr_rx_comp;
+		work_func = mana_rx_dim_work;
+	} else {
+		apc = netdev_priv(cq->txq->ndev);
+		usec = apc->intr_modr_tx_usec;
+		comp = apc->intr_modr_tx_comp;
+		work_func = mana_tx_dim_work;
+	}
+
+	/* On enable, zero the DIM state so net_dim() starts measuring from
+	 * scratch.
+	 * On disable, drain any pending DIM work and restore the static
+	 * moderation values.
+	 */
+	if (enable) {
+		memset(&cq->dim, 0, sizeof(cq->dim));
+		cq->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
+		INIT_WORK(&cq->dim.work, work_func);
+	} else {
+		cancel_work_sync(&cq->dim.work);
+		mana_gd_ring_dim(cq->gdma_cq, usec, true, comp, true);
+	}
+
+	return 0;
+}
+
+static void mana_update_rx_dim(struct mana_cq *cq)
+{
+	struct mana_port_context *apc = netdev_priv(cq->rxq->ndev);
+	struct dim_sample dim_sample = {};
+	struct mana_rxq *rxq = cq->rxq;
+
+	/* Pairs with smp_store_release() in mana_set_coalesce(): observing the
+	 * enable flag set guarantees the DIM (re)initialization is visible.
+	 */
+	if (!smp_load_acquire(&apc->rx_dim_enabled))
+		return;
+
+	dim_update_sample(READ_ONCE(cq->dim_event_ctr), rxq->stats.packets,
+			  rxq->stats.bytes, &dim_sample);
+	net_dim(&cq->dim, &dim_sample);
+}
+
+static void mana_update_tx_dim(struct mana_cq *cq)
+{
+	struct mana_port_context *apc = netdev_priv(cq->txq->ndev);
+	struct dim_sample dim_sample = {};
+
+	/* Pairs with smp_store_release() in mana_set_coalesce(): observing the
+	 * enable flag set guarantees the DIM (re)initialization is visible.
+	 */
+	if (!smp_load_acquire(&apc->tx_dim_enabled))
+		return;
+
+	/* cq->tx_dim_pkts/bytes are accumulated in mana_poll_tx_cq(), in the
+	 * same NAPI context as this read, so they track the hardware
+	 * completion rate and need no u64_stats_sync protection.
+	 */
+	dim_update_sample(READ_ONCE(cq->dim_event_ctr), cq->tx_dim_pkts,
+			  cq->tx_dim_bytes, &dim_sample);
+	net_dim(&cq->dim, &dim_sample);
+}
+
 static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue)
 {
 	struct mana_cq *cq = context;
@@ -2324,6 +2450,15 @@ static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue)
 	if (w < cq->budget) {
 		mana_gd_ring_cq(gdma_queue, SET_ARM_BIT);
 		cq->work_done_since_doorbell = 0;
+
+		/* Update DIM before napi_complete_done() to prevent running
+		 * net_dim() concurrently.
+		 */
+		if (cq->type == MANA_CQ_TYPE_RX)
+			mana_update_rx_dim(cq);
+		else
+			mana_update_tx_dim(cq);
+
 		napi_complete_done(&cq->napi, w);
 	} else if (cq->work_done_since_doorbell >=
 		   (cq->gdma_cq->queue_size / COMP_ENTRY_SIZE) * 4) {
@@ -2356,6 +2491,7 @@ static void mana_schedule_napi(void *context, struct gdma_queue *gdma_queue)
 {
 	struct mana_cq *cq = context;
 
+	WRITE_ONCE(cq->dim_event_ctr, cq->dim_event_ctr + 1);
 	napi_schedule_irqoff(&cq->napi);
 }
 
@@ -2398,6 +2534,7 @@ static void mana_destroy_txq(struct mana_port_context *apc)
 		if (apc->tx_qp[i]->txq.napi_initialized) {
 			napi_synchronize(napi);
 			napi_disable_locked(napi);
+			cancel_work_sync(&apc->tx_qp[i]->tx_cq.dim.work);
 			netif_napi_del_locked(napi);
 			apc->tx_qp[i]->txq.napi_initialized = false;
 		}
@@ -2529,6 +2666,11 @@ static int mana_create_txq(struct mana_port_context *apc,
 		cq_spec.modr_ctx_id = 0;
 		cq_spec.attached_eq = cq->gdma_cq->cq.parent->id;
 
+		/* DIM setting can be changed at runtime */
+		cq_spec.req_cq_moderation = true;
+		cq_spec.cq_moderation_usec = apc->intr_modr_tx_usec;
+		cq_spec.cq_moderation_comp = apc->intr_modr_tx_comp;
+
 		err = mana_create_wq_obj(apc, apc->port_handle, GDMA_SQ,
 					 &wq_spec, &cq_spec,
 					 &apc->tx_qp[i]->tx_object);
@@ -2559,6 +2701,13 @@ static int mana_create_txq(struct mana_port_context *apc,
 
 		set_bit(NAPI_STATE_NO_BUSY_POLL, &cq->napi.state);
 		netif_napi_add_locked(net, &cq->napi, mana_poll);
+
+		/* Initialize the DIM work before enabling NAPI, so that a poll
+		 * cannot reach net_dim() with an uninitialized cq->dim.work.
+		 */
+		INIT_WORK(&cq->dim.work, mana_tx_dim_work);
+		cq->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
+
 		napi_enable_locked(&cq->napi);
 		txq->napi_initialized = true;
 
@@ -2596,6 +2745,7 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
 		napi_synchronize(napi);
 
 		napi_disable_locked(napi);
+		cancel_work_sync(&rxq->rx_cq.dim.work);
 		netif_napi_del_locked(napi);
 	}
 
@@ -2834,6 +2984,11 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
 	cq_spec.modr_ctx_id = 0;
 	cq_spec.attached_eq = cq->gdma_cq->cq.parent->id;
 
+	/* DIM setting can be changed at runtime */
+	cq_spec.req_cq_moderation = true;
+	cq_spec.cq_moderation_usec = apc->intr_modr_rx_usec;
+	cq_spec.cq_moderation_comp = apc->intr_modr_rx_comp;
+
 	err = mana_create_wq_obj(apc, apc->port_handle, GDMA_RQ,
 				 &wq_spec, &cq_spec, &rxq->rxobj);
 	if (err)
@@ -2866,6 +3021,12 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
 	WARN_ON(xdp_rxq_info_reg_mem_model(&rxq->xdp_rxq, MEM_TYPE_PAGE_POOL,
 					   rxq->page_pool));
 
+	/* Initialize the DIM work before enabling NAPI, so that a poll
+	 * cannot reach net_dim() with an uninitialized cq->dim.work.
+	 */
+	INIT_WORK(&cq->dim.work, mana_rx_dim_work);
+	cq->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
+
 	napi_enable_locked(&cq->napi);
 
 	mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT);
@@ -3532,6 +3693,16 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
 	apc->link_cfg_error = 1;
 	apc->cqe_coalescing_enable = 0;
 
+	/* Initialize interrupt moderation settings if supported by HW */
+	if (gc->pf_cap_flags1 & GDMA_PF_CAP_FLAG_1_DYN_INTERRUPT_MODERATION) {
+		apc->intr_modr_rx_usec = MANA_INTR_MODR_USEC_DEF;
+		apc->intr_modr_rx_comp = MANA_INTR_MODR_COMP_DEF;
+		apc->intr_modr_tx_usec = MANA_INTR_MODR_USEC_DEF;
+		apc->intr_modr_tx_comp = MANA_INTR_MODR_COMP_DEF;
+		apc->rx_dim_enabled = MANA_ADAPTIVE_RX_DEF;
+		apc->tx_dim_enabled = MANA_ADAPTIVE_TX_DEF;
+	}
+
 	mutex_init(&apc->vport_mutex);
 	apc->vport_use_count = 0;
 
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 94e658d07a27..5e5fb5b18bbf 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -419,6 +419,15 @@ static int mana_get_coalesce(struct net_device *ndev,
 	    !kernel_coal->rx_cqe_nsecs)
 		kernel_coal->rx_cqe_nsecs = MANA_RX_CQE_NSEC_DEF;
 
+	ec->rx_coalesce_usecs = apc->intr_modr_rx_usec;
+	ec->rx_max_coalesced_frames = apc->intr_modr_rx_comp;
+
+	ec->tx_coalesce_usecs = apc->intr_modr_tx_usec;
+	ec->tx_max_coalesced_frames = apc->intr_modr_tx_comp;
+
+	ec->use_adaptive_rx_coalesce = apc->rx_dim_enabled;
+	ec->use_adaptive_tx_coalesce = apc->tx_dim_enabled;
+
 	return 0;
 }
 
@@ -428,9 +437,34 @@ static int mana_set_coalesce(struct net_device *ndev,
 			     struct netlink_ext_ack *extack)
 {
 	struct mana_port_context *apc = netdev_priv(ndev);
-	u8 saved_cqe_coalescing_enable;
+	struct {
+		u16 intr_modr_rx_usec;
+		u16 intr_modr_rx_comp;
+		u16 intr_modr_tx_usec;
+		u16 intr_modr_tx_comp;
+		u8 cqe_coalescing_enable;
+		bool rx_dim_enabled;
+		bool tx_dim_enabled;
+	} saved;
+	bool modr_changed = false;
+	bool dim_changed = false;
+	struct gdma_context *gc;
 	int err;
 
+	gc = apc->ac->gdma_dev->gdma_context;
+
+	/* Both static and dynamic interrupt moderation (DIM) rely on the
+	 * same HW capability advertised by the PF.
+	 */
+	if ((ec->use_adaptive_rx_coalesce || ec->use_adaptive_tx_coalesce ||
+	     ec->rx_coalesce_usecs || ec->tx_coalesce_usecs ||
+	     ec->rx_max_coalesced_frames || ec->tx_max_coalesced_frames) &&
+	    !(gc->pf_cap_flags1 & GDMA_PF_CAP_FLAG_1_DYN_INTERRUPT_MODERATION)) {
+		NL_SET_ERR_MSG(extack,
+			       "Interrupt Moderation is not supported by HW");
+		return -EOPNOTSUPP;
+	}
+
 	if (kernel_coal->rx_cqe_frames != 1 &&
 	    kernel_coal->rx_cqe_frames != MANA_RXCOMP_OOB_NUM_PPI) {
 		NL_SET_ERR_MSG_FMT(extack,
@@ -440,18 +474,129 @@ static int mana_set_coalesce(struct net_device *ndev,
 		return -EINVAL;
 	}
 
-	saved_cqe_coalescing_enable = apc->cqe_coalescing_enable;
+	if (ec->rx_coalesce_usecs > MANA_INTR_MODR_USEC_MAX ||
+	    ec->tx_coalesce_usecs > MANA_INTR_MODR_USEC_MAX) {
+		NL_SET_ERR_MSG_FMT(extack,
+				   "coalesce usecs must be <= %lu",
+				   MANA_INTR_MODR_USEC_MAX);
+		return -EINVAL;
+	}
+
+	if (ec->rx_max_coalesced_frames > MANA_INTR_MODR_COMP_MAX ||
+	    ec->tx_max_coalesced_frames > MANA_INTR_MODR_COMP_MAX) {
+		NL_SET_ERR_MSG_FMT(extack,
+				   "coalesce frames must be <= %lu",
+				   MANA_INTR_MODR_COMP_MAX);
+		return -EINVAL;
+	}
+
+	if (ec->rx_coalesce_usecs != apc->intr_modr_rx_usec ||
+	    ec->rx_max_coalesced_frames != apc->intr_modr_rx_comp ||
+	    ec->tx_coalesce_usecs != apc->intr_modr_tx_usec ||
+	    ec->tx_max_coalesced_frames != apc->intr_modr_tx_comp)
+		modr_changed = true;
+
+	saved.intr_modr_rx_usec = apc->intr_modr_rx_usec;
+	saved.intr_modr_rx_comp = apc->intr_modr_rx_comp;
+	saved.intr_modr_tx_usec = apc->intr_modr_tx_usec;
+	saved.intr_modr_tx_comp = apc->intr_modr_tx_comp;
+
+	apc->intr_modr_rx_usec = ec->rx_coalesce_usecs;
+	apc->intr_modr_rx_comp = ec->rx_max_coalesced_frames;
+	apc->intr_modr_tx_usec = ec->tx_coalesce_usecs;
+	apc->intr_modr_tx_comp = ec->tx_max_coalesced_frames;
+
+	if (!!ec->use_adaptive_rx_coalesce != apc->rx_dim_enabled ||
+	    !!ec->use_adaptive_tx_coalesce != apc->tx_dim_enabled)
+		dim_changed = true;
+
+	saved.rx_dim_enabled = apc->rx_dim_enabled;
+	saved.tx_dim_enabled = apc->tx_dim_enabled;
+
+	saved.cqe_coalescing_enable = apc->cqe_coalescing_enable;
 	apc->cqe_coalescing_enable =
 		kernel_coal->rx_cqe_frames == MANA_RXCOMP_OOB_NUM_PPI;
 
-	if (!apc->port_is_up)
+	if (!apc->port_is_up) {
+		WRITE_ONCE(apc->rx_dim_enabled, !!ec->use_adaptive_rx_coalesce);
+		WRITE_ONCE(apc->tx_dim_enabled, !!ec->use_adaptive_tx_coalesce);
 		return 0;
+	}
 
-	err = mana_config_rss(apc, TRI_STATE_TRUE, false, false);
-	if (err)
-		apc->cqe_coalescing_enable = saved_cqe_coalescing_enable;
+	if (apc->cqe_coalescing_enable != saved.cqe_coalescing_enable) {
+		/* CQE coalescing setting is applied via RSS configuration. */
+		err = mana_config_rss(apc, TRI_STATE_TRUE, false, false);
+		if (err) {
+			netdev_err(ndev, "Change CQE coalescing failed: %d\n",
+				   err);
+			apc->cqe_coalescing_enable =
+				saved.cqe_coalescing_enable;
+			apc->intr_modr_rx_usec = saved.intr_modr_rx_usec;
+			apc->intr_modr_rx_comp = saved.intr_modr_rx_comp;
+			apc->intr_modr_tx_usec = saved.intr_modr_tx_usec;
+			apc->intr_modr_tx_comp = saved.intr_modr_tx_comp;
+			return err;
+		}
+	}
 
-	return err;
+	if (modr_changed || dim_changed) {
+		bool new_rx_dim = !!ec->use_adaptive_rx_coalesce;
+		bool new_tx_dim = !!ec->use_adaptive_tx_coalesce;
+		bool disable_rx_dim = saved.rx_dim_enabled && !new_rx_dim;
+		bool disable_tx_dim = saved.tx_dim_enabled && !new_tx_dim;
+		bool enable_rx_dim = !saved.rx_dim_enabled && new_rx_dim;
+		bool enable_tx_dim = !saved.tx_dim_enabled && new_tx_dim;
+		int q;
+
+		/* On disable: clear the per-port flag first and
+		 * synchronize_net() so any in-flight NAPI poll observes
+		 * the new value and will not schedule further DIM work;
+		 * then drain pending work and restore the static
+		 * moderation values.
+		 */
+		if (disable_rx_dim)
+			WRITE_ONCE(apc->rx_dim_enabled, false);
+		if (disable_tx_dim)
+			WRITE_ONCE(apc->tx_dim_enabled, false);
+		if (disable_rx_dim || disable_tx_dim)
+			synchronize_net();
+
+		for (q = 0; q < apc->num_queues; q++) {
+			struct mana_cq *rx_cq = &apc->rxqs[q]->rx_cq;
+			struct mana_cq *tx_cq = &apc->tx_qp[q]->tx_cq;
+
+			if (disable_rx_dim)
+				mana_dim_change(rx_cq, false);
+			else if (enable_rx_dim)
+				mana_dim_change(rx_cq, true);
+			else if (!new_rx_dim && modr_changed)
+				mana_gd_ring_dim(rx_cq->gdma_cq,
+						 apc->intr_modr_rx_usec, true,
+						 apc->intr_modr_rx_comp, true);
+
+			if (disable_tx_dim)
+				mana_dim_change(tx_cq, false);
+			else if (enable_tx_dim)
+				mana_dim_change(tx_cq, true);
+			else if (!new_tx_dim && modr_changed)
+				mana_gd_ring_dim(tx_cq->gdma_cq,
+						 apc->intr_modr_tx_usec, true,
+						 apc->intr_modr_tx_comp, true);
+		}
+
+		/* Publish the enable flag with release semantics so a
+		 * concurrent NAPI poll that observes it set also sees the DIM
+		 * (re)init done by mana_dim_change() above.
+		 */
+		if (enable_rx_dim)
+			/* pairs with smp_load_acquire() in mana_update_rx_dim() */
+			smp_store_release(&apc->rx_dim_enabled, true);
+		if (enable_tx_dim)
+			/* pairs with smp_load_acquire() in mana_update_tx_dim() */
+			smp_store_release(&apc->tx_dim_enabled, true);
+	}
+
+	return 0;
 }
 
 /* mana_set_channels - change the number of queues on a port
@@ -595,7 +740,13 @@ static int mana_get_link_ksettings(struct net_device *ndev,
 }
 
 const struct ethtool_ops mana_ethtool_ops = {
-	.supported_coalesce_params = ETHTOOL_COALESCE_RX_CQE_FRAMES,
+	.supported_coalesce_params = ETHTOOL_COALESCE_RX_CQE_FRAMES |
+				     ETHTOOL_COALESCE_RX_USECS |
+				     ETHTOOL_COALESCE_RX_MAX_FRAMES |
+				     ETHTOOL_COALESCE_TX_USECS |
+				     ETHTOOL_COALESCE_TX_MAX_FRAMES |
+				     ETHTOOL_COALESCE_USE_ADAPTIVE_RX |
+				     ETHTOOL_COALESCE_USE_ADAPTIVE_TX,
 	.op_needs_rtnl		= ETHTOOL_OP_NEEDS_RTNL_SCHANNELS |
 				  ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM,
 	.get_ethtool_stats	= mana_get_ethtool_stats,
diff --git a/include/net/mana/gdma.h b/include/net/mana/gdma.h
index 0c395917b214..8529cef0d7c4 100644
--- a/include/net/mana/gdma.h
+++ b/include/net/mana/gdma.h
@@ -47,6 +47,7 @@ enum gdma_queue_type {
 	GDMA_RQ,
 	GDMA_CQ,
 	GDMA_EQ,
+	GDMA_DIM,
 };
 
 enum gdma_work_request_flags {
@@ -126,6 +127,17 @@ union gdma_doorbell_entry {
 		u64 tail_ptr	: 31;
 		u64 arm		: 1;
 	} eq;
+
+	struct {
+		u64 id           : 24;
+		u64 reserved     : 8;
+		u64 mod_usec     : 10;
+		u64 reserve1     : 5;
+		u64 mod_usec_vld : 1;
+		u64 mod_comps    : 8;
+		u64 reserve2     : 7;
+		u64 mod_comps_vld: 1;
+	} dim;
 }; /* HW DATA */
 
 struct gdma_msg_hdr {
@@ -502,6 +514,9 @@ void mana_gd_ring_cq(struct gdma_queue *cq, u8 arm_bit);
 
 int mana_schedule_serv_work(struct gdma_context *gc, enum gdma_eqe_type type);
 
+void mana_gd_ring_dim(struct gdma_queue *cq, u32 mod_usec, bool mod_usec_vld,
+		      u32 mod_comps, bool mod_comps_vld);
+
 struct gdma_wqe {
 	u32 reserved	:24;
 	u32 last_vbytes	:8;
@@ -650,6 +665,9 @@ enum {
 /* Driver supports self recovery on Hardware Channel timeouts */
 #define GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECOVERY BIT(25)
 
+/* Driver supports dynamic interrupt moderation - DIM */
+#define GDMA_DRV_CAP_FLAG_1_DYN_INTERRUPT_MODERATION BIT(28)
+
 #define GDMA_DRV_CAP_FLAGS1 \
 	(GDMA_DRV_CAP_FLAG_1_EQ_SHARING_MULTI_VPORT | \
 	 GDMA_DRV_CAP_FLAG_1_NAPI_WKDONE_FIX | \
@@ -665,7 +683,8 @@ enum {
 	 GDMA_DRV_CAP_FLAG_1_PROBE_RECOVERY | \
 	 GDMA_DRV_CAP_FLAG_1_HANDLE_STALL_SQ_RECOVERY | \
 	 GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECOVERY | \
-	 GDMA_DRV_CAP_FLAG_1_EQ_MSI_UNSHARE_MULTI_VPORT)
+	 GDMA_DRV_CAP_FLAG_1_EQ_MSI_UNSHARE_MULTI_VPORT | \
+	 GDMA_DRV_CAP_FLAG_1_DYN_INTERRUPT_MODERATION)
 
 #define GDMA_DRV_CAP_FLAGS2 0
 
@@ -701,6 +720,9 @@ struct gdma_verify_ver_req {
 	u8 os_ver_str4[128];
 }; /* HW DATA */
 
+/* HW supports dynamic interrupt moderation - DIM */
+#define GDMA_PF_CAP_FLAG_1_DYN_INTERRUPT_MODERATION BIT(15)
+
 struct gdma_verify_ver_resp {
 	struct gdma_resp_hdr hdr;
 	u64 gdma_protocol_ver;
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 13c87baf018e..df4c4a3f68fa 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -4,6 +4,7 @@
 #ifndef _MANA_H
 #define _MANA_H
 
+#include <linux/dim.h>
 #include <net/xdp.h>
 #include <net/net_shaper.h>
 
@@ -64,6 +65,19 @@ enum TRI_STATE {
 /* Maximum number of packets per coalesced CQE */
 #define MANA_RXCOMP_OOB_NUM_PPI 4
 
+/* Default/max interrupt moderation settings */
+#define MANA_INTR_MODR_USEC_DEF 0
+#define MANA_INTR_MODR_COMP_DEF 0
+
+#define MANA_ADAPTIVE_RX_DEF true
+#define MANA_ADAPTIVE_TX_DEF true
+
+/* DIM doorbell value field layout */
+#define MANA_INTR_MODR_USEC_MAX    GENMASK(9, 0)
+#define MANA_INTR_MODR_USEC_VLD    BIT(15)
+#define MANA_INTR_MODR_COMP_MAX    GENMASK(7, 0)
+#define MANA_INTR_MODR_COMP_MASK   GENMASK(23, 16)
+
 /* Update this count whenever the respective structures are changed */
 #define MANA_STATS_RX_COUNT (6 + MANA_RXCOMP_OOB_NUM_PPI - 1)
 #define MANA_STATS_TX_COUNT 11
@@ -297,6 +311,17 @@ struct mana_cq {
 	int work_done;
 	int work_done_since_doorbell;
 	int budget;
+
+	/* DIM - Dynamic Interrupt Moderation */
+	struct dim dim;
+	u16 dim_event_ctr;
+
+	/* Cumulative TX completions fed to DIM. Updated and read only in
+	 * NAPI context (mana_poll_tx_cq() / mana_update_tx_dim()), so they
+	 * measure the hardware completion rate and need no u64_stats_sync.
+	 */
+	u64 tx_dim_pkts;
+	u64 tx_dim_bytes;
 };
 
 struct mana_recv_buf_oob {
@@ -573,6 +598,15 @@ struct mana_port_context {
 	u8 cqe_coalescing_enable;
 	u32 cqe_coalescing_timeout_ns;
 
+	/* Interrupt moderation settings */
+	u16 intr_modr_rx_usec;
+	u16 intr_modr_rx_comp;
+	u16 intr_modr_tx_usec;
+	u16 intr_modr_tx_comp;
+
+	bool rx_dim_enabled;
+	bool tx_dim_enabled;
+
 	struct mana_ethtool_stats eth_stats;
 
 	struct mana_ethtool_phy_stats phy_stats;
@@ -598,6 +632,8 @@ int mana_alloc_queues(struct net_device *ndev);
 int mana_attach(struct net_device *ndev);
 int mana_detach(struct net_device *ndev, bool from_close);
 
+int mana_dim_change(struct mana_cq *cq, bool enable);
+
 int mana_probe(struct gdma_dev *gd, bool resuming);
 void mana_remove(struct gdma_dev *gd, bool suspending);
 
@@ -633,6 +669,9 @@ struct mana_obj_spec {
 	u32 queue_size;
 	u32 attached_eq;
 	u32 modr_ctx_id;
+	u8 req_cq_moderation;
+	u16 cq_moderation_comp;
+	u16 cq_moderation_usec;
 };
 
 enum mana_command_code {
@@ -764,6 +803,15 @@ struct mana_create_wqobj_req {
 	u32 cq_size;
 	u32 cq_moderation_ctx_id;
 	u32 cq_parent_qid;
+
+	/* V2 */
+	u8 allow_rqwqe_chain;
+
+	/* V3 */
+	u8 req_cq_moderation;
+	u16 cq_moderation_comp;
+	u16 cq_moderation_usec;
+	u8 reserved2[2];
 }; /* HW DATA */
 
 struct mana_create_wqobj_resp {
@@ -771,6 +819,12 @@ struct mana_create_wqobj_resp {
 	u32 wq_id;
 	u32 cq_id;
 	mana_handle_t wq_obj;
+
+	/* V2 */
+	u16 cq_moderation_comp;
+	u16 cq_moderation_usec;
+	u8 cq_moderation_enabled;
+	u8 reserved1[3];
 }; /* HW DATA */
 
 /* Destroy WQ Object */
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH net-next v3 0/6] pds_core: Add PLDM firmware update and host backed memory support
From: Jakub Kicinski @ 2026-06-13 20:58 UTC (permalink / raw)
  To: Jacob Keller
  Cc: Rao, Nikhil, netdev, Brett Creeley, Andrew Lunn, David S . Miller,
	Eric Dumazet, Paolo Abeni, Eric Joyner
In-Reply-To: <1264de6d-a669-4afa-ad08-594d956e101a@intel.com>

On Thu, 11 Jun 2026 11:53:13 -0700 Jacob Keller wrote:
> On 6/11/2026 10:15 AM, Rao, Nikhil wrote:
> >> The preference is to use generic names when possible/feasible. I think
> >> at least some of your name choices could align with the generic ones.
> >>
> >> Could you explain why fw.mainfw was selected and fw.mgmt was deemed not
> >> suitable?  
> > 
> > This component handles both control and data path, so fw.mgmt didn't
> > feel right since devlink-info.rst explicitly excludes data path from
> > that definition. We went with fw.mainfw to indicate it's the primary
> > firmware component
> 
> It might make sense to extend or add a new definition in this case.
> Technically you could also report both fw.mgmt and fw.app together, but
> I think that would be more confusing.
> 
> Perhaps Jakub has a suggestion on the name or policy here. The
> maintainer preference has generally been to use or extend standardized
> names first unless the name or component is clearly unique to the device.

If it covers both datapath and mgmt then shouldn't it be just "fw" ?
Right now driver reports something "running"-only as "fw", looks off

^ permalink raw reply

* Re: [PATCH v5 2/6] landlock: Add UDP send+connect access control
From: Mickaël Salaün @ 2026-06-13 20:55 UTC (permalink / raw)
  To: Matthieu Buffet
  Cc: Günther Noack, linux-security-module, Mikhail Ivanov,
	konstantin.meskhidze, Tingmao Wang, netdev
In-Reply-To: <20260611162107.49278-3-matthieu@buffet.re>

A few issues were identified by Sashiko:
https://sashiko.dev/#/patchset/20260611162107.49278-1-matthieu%40buffet.re

I squashed this patch:

diff --git a/security/landlock/net.c b/security/landlock/net.c
index 9273cdbbf844..b12568666a9e 100644
--- a/security/landlock/net.c
+++ b/security/landlock/net.c
@@ -261,10 +261,17 @@ static int current_check_access_socket(struct socket *const sock,
 
 static int current_check_autobind_udp_socket(struct socket *const sock)
 {
+	const struct access_masks bind_udp = {
+		.net = LANDLOCK_ACCESS_NET_BIND_UDP,
+	};
 	struct sockaddr_storage port0 = {};
 	unsigned short num;
 	bool slow;
 
+	/* Quick return for non-Landlocked tasks. */
+	if (!landlock_get_applicable_subject(current_cred(), bind_udp, NULL))
+		return 0;
+
 	/*
 	 * On UDP sockets, if a local port has not already been bound, calling
 	 * connect() or sending a first datagram has the side effect of
@@ -287,8 +294,7 @@ static int current_check_autobind_udp_socket(struct socket *const sock)
 	port0.ss_family = READ_ONCE(sock->sk->sk_family);
 
 	return current_check_access_socket(sock, (struct sockaddr *)&port0,
-					   sizeof(port0),
-					   LANDLOCK_ACCESS_NET_BIND_UDP, false);
+					   sizeof(port0), bind_udp.net, false);
 }
 
 static int hook_socket_bind(struct socket *const sock,
@@ -328,7 +334,9 @@ static int hook_socket_connect(struct socket *const sock,
 	 * connect()ing to an AF_UNSPEC address does not trigger an autobind and
 	 * should never be restricted.
 	 */
-	if (ret == 0 && sk_is_udp(sock->sk) && address->sa_family != AF_UNSPEC)
+	if (ret == 0 && sk_is_udp(sock->sk) &&
+	    addrlen >= offsetofend(typeof(*address), sa_family) &&
+	    address->sa_family != AF_UNSPEC)
 		ret = current_check_autobind_udp_socket(sock);
 
 	return ret;


We might want to factor out some code, but that should be good for now.


On Thu, Jun 11, 2026 at 06:21:02PM +0200, Matthieu Buffet wrote:
> Add support for a second fine-grained UDP access right.
> LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP controls the ability to set the
> remote port of a socket (via connect()) and to specify an explicit
> destination when sending a datagram, to override any remote peer set on
> a UDP socket (e.g. in sendto() or sendmsg()).
> It will be useful for applications that send datagrams, and for some
> servers too (those creating per-client sockets, which want to receive
> traffic only from a specific address).
> 
> Similarly as for bind(), this access control is performed when
> configuring sockets, not in hot code paths.
> 
> Add detection of when autobind is about to be required, and deny the
> operation if the process would not be allowed to call bind(0)
> explicitly. Autobind can only be performed in udp_lib_get_port() from
> code paths already controlled by LSM hooks: when connect()ing,
> sending a first datagram, and in some splice() EOF edge case which,
> afaiu, can only happen after a remote peer has been set. This invariant
> needs to be preserved to keep bind policies actually enforced.
> 
> Signed-off-by: Matthieu Buffet <matthieu@buffet.re>
> ---
>  include/uapi/linux/landlock.h               |  23 ++++
>  security/landlock/audit.c                   |   2 +
>  security/landlock/limits.h                  |   2 +-
>  security/landlock/net.c                     | 137 +++++++++++++++++---
>  tools/testing/selftests/landlock/net_test.c |   5 +-
>  5 files changed, 151 insertions(+), 18 deletions(-)
> 
> diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h
> index 045b251ff1b4..b147223efc97 100644
> --- a/include/uapi/linux/landlock.h
> +++ b/include/uapi/linux/landlock.h
> @@ -378,11 +378,34 @@ struct landlock_net_port_attr {
>   *
>   * - %LANDLOCK_ACCESS_NET_BIND_UDP: Bind UDP sockets to the given local
>   *   port. Support added in Landlock ABI version 10.
> + * - %LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP: Set the remote port of UDP
> + *   sockets to the given port, or send datagrams to the given remote port
> + *   ignoring any destination pre-set on a socket. Support added in
> + *   Landlock ABI version 10.
> + *
> + * .. note:: Setting a remote address or sending a first datagram
> + *   auto-binds UDP sockets to an ephemeral local source port if not
> + *   already bound. To allow this if both %LANDLOCK_ACCESS_NET_BIND_UDP
> + *   and %LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP are handled, you need to
> + *   either:
> + *
> + *   - use a socket already bound to a port before the ruleset started
> + *     being enforced;
> + *   - or grant %LANDLOCK_ACCESS_NET_BIND_UDP on port 0, meaning "any
> + *     port in the ephemeral port range";
> + *   - or grant %LANDLOCK_ACCESS_NET_BIND_UDP on a specific port, and
> + *     call :manpage:`bind(2)` on that port before trying to
> + *     :manpage:`connect(2)` or send datagrams.
> + *
> + * .. note:: Sending datagrams to an ``AF_UNSPEC`` destination address
> + *   family is not supported for IPv6 UDP sockets: you will need to use a
> + *   ``NULL`` address instead.
>   */
>  /* clang-format off */
>  #define LANDLOCK_ACCESS_NET_BIND_TCP			(1ULL << 0)
>  #define LANDLOCK_ACCESS_NET_CONNECT_TCP			(1ULL << 1)
>  #define LANDLOCK_ACCESS_NET_BIND_UDP			(1ULL << 2)
> +#define LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP		(1ULL << 3)
>  /* clang-format on */
>  
>  /**
> diff --git a/security/landlock/audit.c b/security/landlock/audit.c
> index e676ebffeebe..851647197a01 100644
> --- a/security/landlock/audit.c
> +++ b/security/landlock/audit.c
> @@ -46,6 +46,8 @@ static const char *const net_access_strings[] = {
>  	[BIT_INDEX(LANDLOCK_ACCESS_NET_BIND_TCP)] = "net.bind_tcp",
>  	[BIT_INDEX(LANDLOCK_ACCESS_NET_CONNECT_TCP)] = "net.connect_tcp",
>  	[BIT_INDEX(LANDLOCK_ACCESS_NET_BIND_UDP)] = "net.bind_udp",
> +	[BIT_INDEX(LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP)] =
> +		"net.connect_send_udp",
>  };
>  
>  static_assert(ARRAY_SIZE(net_access_strings) == LANDLOCK_NUM_ACCESS_NET);
> diff --git a/security/landlock/limits.h b/security/landlock/limits.h
> index c0f30a4591b8..a4d908b240a2 100644
> --- a/security/landlock/limits.h
> +++ b/security/landlock/limits.h
> @@ -23,7 +23,7 @@
>  #define LANDLOCK_MASK_ACCESS_FS		((LANDLOCK_LAST_ACCESS_FS << 1) - 1)
>  #define LANDLOCK_NUM_ACCESS_FS		__const_hweight64(LANDLOCK_MASK_ACCESS_FS)
>  
> -#define LANDLOCK_LAST_ACCESS_NET	LANDLOCK_ACCESS_NET_BIND_UDP
> +#define LANDLOCK_LAST_ACCESS_NET	LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP
>  #define LANDLOCK_MASK_ACCESS_NET	((LANDLOCK_LAST_ACCESS_NET << 1) - 1)
>  #define LANDLOCK_NUM_ACCESS_NET		__const_hweight64(LANDLOCK_MASK_ACCESS_NET)
>  
> diff --git a/security/landlock/net.c b/security/landlock/net.c
> index 8da40614c452..0e697403eca9 100644
> --- a/security/landlock/net.c
> +++ b/security/landlock/net.c
> @@ -44,7 +44,8 @@ int landlock_append_net_rule(struct landlock_ruleset *const ruleset,
>  static int current_check_access_socket(struct socket *const sock,
>  				       struct sockaddr *const address,
>  				       const int addrlen,
> -				       access_mask_t access_request)
> +				       access_mask_t access_request,
> +				       bool connecting)
>  {
>  	unsigned short sock_family;
>  	__be16 port;
> @@ -75,19 +76,51 @@ static int current_check_access_socket(struct socket *const sock,
>  
>  	switch (address->sa_family) {
>  	case AF_UNSPEC:
> -		if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) {
> +		if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP ||
> +		    (access_request == LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP &&
> +		     connecting)) {
>  			/*
>  			 * Connecting to an address with AF_UNSPEC dissolves
> -			 * the TCP association, which have the same effect as
> -			 * closing the connection while retaining the socket
> -			 * object (i.e., the file descriptor).  As for dropping
> -			 * privileges, closing connections is always allowed.
> -			 *
> -			 * For a TCP access control system, this request is
> -			 * legitimate. Let the network stack handle potential
> +			 * the remote association while retaining the socket
> +			 * object (i.e., the file descriptor). For TCP, it has
> +			 * the same effect as closing the connection. For UDP,
> +			 * it removes any preset remote address. As for
> +			 * dropping privileges, these actions are always
> +			 * allowed.
> +			 * Let the network stack handle potential
>  			 * inconsistencies and return -EINVAL if needed.
>  			 */
>  			return 0;
> +		} else if (access_request ==
> +			   LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP) {
> +			if (sock_family == AF_INET6) {
> +				/*
> +				 * We cannot allow sending UDP datagrams to an
> +				 * explicit AF_UNSPEC address on IPv6 sockets,
> +				 * even if AF_UNSPEC is treated as "no address"
> +				 * on such sockets (so it should always be allowed).
> +				 * That's because the socket's family can change under
> +				 * our feet (if another thread calls setsockopt(IPV6_ADDRFORM))
> +				 * to IPv4, which would then treat AF_UNSPEC as
> +				 * AF_INET.
> +				 */
> +				audit_net.family = AF_UNSPEC;
> +				audit_net.sk = sock->sk;
> +				landlock_init_layer_masks(
> +					subject->domain, access_request,
> +					&layer_masks, LANDLOCK_KEY_NET_PORT);
> +				landlock_log_denial(
> +					subject,
> +					&(struct landlock_request){
> +						.type = LANDLOCK_REQUEST_NET_ACCESS,
> +						.audit.type =
> +							LSM_AUDIT_DATA_NET,
> +						.audit.u.net = &audit_net,
> +						.access = access_request,
> +						.layer_masks = &layer_masks,
> +					});
> +				return -EACCES;
> +			}
>  		} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP ||
>  			   access_request == LANDLOCK_ACCESS_NET_BIND_UDP) {
>  			/*
> @@ -130,7 +163,11 @@ static int current_check_access_socket(struct socket *const sock,
>  		} else {
>  			WARN_ON_ONCE(1);
>  		}
> -		/* Only for bind(AF_UNSPEC+INADDR_ANY) on IPv4 socket. */
> +		/*
> +		 * AF_UNSPEC is treated as AF_INET only in
> +		 * bind(AF_UNSPEC+INADDR_ANY) on IPv4 sockets and
> +		 * when sending to AF_UNSPEC addresses on IPv4 sockets.
> +		 */
>  		fallthrough;
>  	case AF_INET: {
>  		const struct sockaddr_in *addr4;
> @@ -141,7 +178,8 @@ static int current_check_access_socket(struct socket *const sock,
>  		addr4 = (struct sockaddr_in *)address;
>  		port = addr4->sin_port;
>  
> -		if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) {
> +		if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP ||
> +		    access_request == LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP) {
>  			audit_net.dport = port;
>  			audit_net.v4info.daddr = addr4->sin_addr.s_addr;
>  		} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP ||
> @@ -164,7 +202,8 @@ static int current_check_access_socket(struct socket *const sock,
>  		addr6 = (struct sockaddr_in6 *)address;
>  		port = addr6->sin6_port;
>  
> -		if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) {
> +		if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP ||
> +		    access_request == LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP) {
>  			audit_net.dport = port;
>  			audit_net.v6info.daddr = addr6->sin6_addr;
>  		} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP ||
> @@ -221,6 +260,38 @@ static int current_check_access_socket(struct socket *const sock,
>  	return -EACCES;
>  }
>  
> +static int current_check_autobind_udp_socket(struct socket *const sock)
> +{
> +	struct sockaddr_storage port0 = {};
> +	unsigned short num;
> +	bool slow;
> +
> +	/*
> +	 * On UDP sockets, if a local port has not already been bound,
> +	 * calling connect() or sending a first datagram has the side
> +	 * effect of autobinding an ephemeral port: we also have to check
> +	 * that the process would have had the right to bind(0) explicitly.
> +	 * Hold the socket lock around the inet_num read to exclude
> +	 * udp_lib_get_port()'s transient inet_num = snum write that is
> +	 * reverted to 0 on a failing reuseport bind.
> +	 */
> +	slow = lock_sock_fast(sock->sk);
> +	num = inet_sk(sock->sk)->inet_num;
> +	unlock_sock_fast(sock->sk, slow);
> +	if (num != 0)
> +		return 0;
> +
> +	/*
> +	 * Construct a struct sockaddr* with port 0 to pretend the
> +	 * process tried to bind() on that address.
> +	 */
> +	port0.ss_family = READ_ONCE(sock->sk->sk_family);
> +
> +	return current_check_access_socket(sock, (struct sockaddr *)&port0,
> +					   sizeof(port0),
> +					   LANDLOCK_ACCESS_NET_BIND_UDP, false);
> +}
> +
>  static int hook_socket_bind(struct socket *const sock,
>  			    struct sockaddr *const address, const int addrlen)
>  {
> @@ -234,7 +305,7 @@ static int hook_socket_bind(struct socket *const sock,
>  		return 0;
>  
>  	return current_check_access_socket(sock, address, addrlen,
> -					   access_request);
> +					   access_request, false);
>  }
>  
>  static int hook_socket_connect(struct socket *const sock,
> @@ -242,19 +313,55 @@ static int hook_socket_connect(struct socket *const sock,
>  			       const int addrlen)
>  {
>  	access_mask_t access_request;
> +	int ret = 0;
>  
>  	if (sk_is_tcp(sock->sk))
>  		access_request = LANDLOCK_ACCESS_NET_CONNECT_TCP;
> +	else if (sk_is_udp(sock->sk))
> +		access_request = LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP;
>  	else
>  		return 0;
>  
> -	return current_check_access_socket(sock, address, addrlen,
> -					   access_request);
> +	ret = current_check_access_socket(sock, address, addrlen,
> +					  access_request, true);
> +
> +	/*
> +	 * connect()ing to an AF_UNSPEC address does not trigger an
> +	 * autobind and should never be restricted.
> +	 */
> +	if (ret == 0 && sk_is_udp(sock->sk) && address->sa_family != AF_UNSPEC)
> +		ret = current_check_autobind_udp_socket(sock);
> +
> +	return ret;
> +}
> +
> +static int hook_socket_sendmsg(struct socket *const sock,
> +			       struct msghdr *const msg, const int size)
> +{
> +	struct sockaddr *const address = msg->msg_name;
> +	const int addrlen = msg->msg_namelen;
> +	access_mask_t access_request;
> +	int ret = 0;
> +
> +	if (sk_is_udp(sock->sk))
> +		access_request = LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP;
> +	else
> +		return 0;
> +
> +	if (address != NULL)
> +		ret = current_check_access_socket(sock, address, addrlen,
> +						  access_request, false);
> +
> +	if (ret == 0)
> +		ret = current_check_autobind_udp_socket(sock);
> +
> +	return ret;
>  }
>  
>  static struct security_hook_list landlock_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(socket_bind, hook_socket_bind),
>  	LSM_HOOK_INIT(socket_connect, hook_socket_connect),
> +	LSM_HOOK_INIT(socket_sendmsg, hook_socket_sendmsg),
>  };
>  
>  __init void landlock_add_net_hooks(void)
> diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c
> index ec392d971ea3..016c7277e370 100644
> --- a/tools/testing/selftests/landlock/net_test.c
> +++ b/tools/testing/selftests/landlock/net_test.c
> @@ -1326,12 +1326,13 @@ FIXTURE_TEARDOWN(mini)
>  
>  /* clang-format off */
>  
> -#define ACCESS_LAST LANDLOCK_ACCESS_NET_BIND_UDP
> +#define ACCESS_LAST LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP
>  
>  #define ACCESS_ALL ( \
>  	LANDLOCK_ACCESS_NET_BIND_TCP | \
>  	LANDLOCK_ACCESS_NET_CONNECT_TCP | \
> -	LANDLOCK_ACCESS_NET_BIND_UDP)
> +	LANDLOCK_ACCESS_NET_BIND_UDP | \
> +	LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP)
>  
>  /* clang-format on */
>  
> -- 
> 2.47.3
> 
> 

^ permalink raw reply related

* RE: [EXTERNAL] Re: [PATCH net-next v3] net: mana: Add Interrupt Moderation support
From: Haiyang Zhang @ 2026-06-13 20:48 UTC (permalink / raw)
  To: Simon Horman
  Cc: linux-hyperv@vger.kernel.org, netdev@vger.kernel.org,
	KY Srinivasan, wei.liu@kernel.org, Dexuan Cui, Long Li,
	andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, Konstantin Taranov,
	shradhagupta@linux.microsoft.com, ernis@linux.microsoft.com,
	dipayanroy@linux.microsoft.com, gargaditya@linux.microsoft.com,
	kees@kernel.org, leitao@debian.org, linux-kernel@vger.kernel.org,
	linux-rdma@vger.kernel.org, Paul Rosswurm
In-Reply-To: <20260613082014.715350-1-horms@kernel.org>



> -----Original Message-----
> From: Simon Horman <horms@kernel.org>
> Sent: Saturday, June 13, 2026 4:20 AM
> To: haiyangz@linux.microsoft.com
> Cc: Simon Horman <horms@kernel.org>; linux-hyperv@vger.kernel.org;
> netdev@vger.kernel.org; KY Srinivasan <kys@microsoft.com>; Haiyang Zhang
> <haiyangz@microsoft.com>; wei.liu@kernel.org; Dexuan Cui
> <DECUI@microsoft.com>; Long Li <longli@microsoft.com>;
> andrew+netdev@lunn.ch; davem@davemloft.net; edumazet@google.com;
> kuba@kernel.org; pabeni@redhat.com; Konstantin Taranov
> <kotaranov@microsoft.com>; shradhagupta@linux.microsoft.com;
> ernis@linux.microsoft.com; dipayanroy@linux.microsoft.com;
> gargaditya@linux.microsoft.com; kees@kernel.org; leitao@debian.org; linux-
> kernel@vger.kernel.org; linux-rdma@vger.kernel.org; Paul Rosswurm
> <paulros@microsoft.com>
> Subject: [EXTERNAL] Re: [PATCH net-next v3] net: mana: Add Interrupt
> Moderation support
> 
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> Full review at:
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsashiko.
> dev%2F&data=05%7C02%7Chaiyangz%40microsoft.com%7Ccbca53cce3d24759006708dec
> 924a556%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C639169356403391033%7C
> Unknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJX
> aW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=D2ZPGJ5XznEkcL
> uH3Cxtze0FYOL3xxDIY%2Bg2DP508Q8%3D&reserved=0
> ---
> Date:   Thu Jun 11 19:02:22 2026 +0000
> 
>     net: mana: Add Interrupt Moderation support
> 
>     This commit adds Static and Dynamic Interrupt Moderation (DIM) support
> for
>     Rx and Tx. It updates the queue creation procedure, adds functions to
>     collect stats for DIM, and provides ethtool handler support to get/set
>     the moderation settings.
> 
> > diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c
> b/drivers/net/ethernet/microsoft/mana/mana_en.c
> > index 26aef21c6c2c8..d92e022d8533c 100644
> > --- a/drivers/net/ethernet/microsoft/mana/mana_en.c
> > +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
> > @@ -1579,6 +1579,9 @@ int mana_create_wq_obj(struct mana_port_context
> *apc,
> >
> >  	mana_gd_init_req_hdr(&req.hdr, MANA_CREATE_WQ_OBJ,
> >  			     sizeof(req), sizeof(resp));
> > +
> > +	req.hdr.req.msg_version = GDMA_MESSAGE_V3;
> > +	req.hdr.resp.msg_version = GDMA_MESSAGE_V2;
> >  	req.vport = vport;
> >  	req.wq_type = wq_type;
> >  	req.wq_gdma_region = wq_spec->gdma_region;
> > @@ -1587,6 +1590,9 @@ int mana_create_wq_obj(struct mana_port_context
> *apc,
> >  	req.cq_size = cq_spec->queue_size;
> >  	req.cq_moderation_ctx_id = cq_spec->modr_ctx_id;
> >  	req.cq_parent_qid = cq_spec->attached_eq;
> > +	req.req_cq_moderation = cq_spec->req_cq_moderation;
> > +	req.cq_moderation_comp = cq_spec->cq_moderation_comp;
> > +	req.cq_moderation_usec = cq_spec->cq_moderation_usec;
> 
> [Severity: High]
> Does this break queue creation on older Azure host firmwares?
> 
> The code unconditionally bumps the WQ object creation request to use
> GDMA_MESSAGE_V3 and passes the req_cq_moderation flag. If the firmware
> does
> not support GDMA_PF_CAP_FLAG_1_DYN_INTERRUPT_MODERATION, could the
> firmware
> reject the queue creation request and break device initialization
> entirely?

Our firmware is forward compatible with newer message versions, so the 
old firmware still properly handles this message, just the new feature 
fields are ignored, and queue creation will be successful.
And if the DIM capability bit is zero from FW, driver will keep the DIM
feature to be off and unchangeable.

> 
> [ ... ]
> 
> > +static void mana_update_tx_dim(struct mana_cq *cq)
> > +{
> > +	struct mana_port_context *apc = netdev_priv(cq->txq->ndev);
> > +	struct dim_sample dim_sample = {};
> > +	struct mana_txq *txq = cq->txq;
> > +
> > +	if (!apc->tx_dim_enabled)
> > +		return;
> > +
> > +	dim_update_sample(READ_ONCE(cq->dim_event_ctr), txq->stats.packets,
> > +			  txq->stats.bytes, &dim_sample);
> > +	net_dim(&cq->dim, &dim_sample);
> > +}
> 
> [Severity: High]
> Does this measure the CPU enqueue rate rather than the hardware completion
> rate?
> 
> It appears that txq->stats.packets is incremented in mana_start_xmit()
> upon enqueue, not during completion in mana_poll_tx_cq(). Dynamic
> interrupt
> moderation relies on measuring the actual hardware completion rate to
> function correctly.
> 
> Additionally, is it safe to read txq->stats.packets here without the
> u64_stats_fetch_begin() retry loop? Reading a 64-bit statistic locklessly
> without the synchronization primitives could result in torn reads on 32-
> bit
> systems.
In the next patch version, I added counters to cq, and track the HW comp rate,
And the reader is in the same NAPI thread to prevent any torn reads.

> 
> [ ... ]
> 
> > @@ -2324,7 +2434,13 @@ static int mana_cq_handler(void *context, struct
> gdma_queue *gdma_queue)
> >  	if (w < cq->budget) {
> >  		mana_gd_ring_cq(gdma_queue, SET_ARM_BIT);
> >  		cq->work_done_since_doorbell = 0;
> > -		napi_complete_done(&cq->napi, w);
> > +
> > +		if (napi_complete_done(&cq->napi, w)) {
> > +			if (cq->type == MANA_CQ_TYPE_RX)
> > +				mana_update_rx_dim(cq);
> > +			else
> > +				mana_update_tx_dim(cq);
> > +		}
> 
> [Severity: High]
> Is it safe to call mana_update_rx_dim() and mana_update_tx_dim() after
> napi_complete_done()?
> 
> Since napi_complete_done() ends the NAPI polling cycle and relinquishes
> mutual exclusion, and the hardware interrupt was already re-armed by
> mana_gd_ring_cq() right before this, couldn't a new packet trigger an
> interrupt immediately? This could allow NAPI to be scheduled on another
> CPU
> concurrently while this CPU is still running the DIM update, potentially
> corrupting the non-thread-safe net_dim() state machine.

Thanks, I moved the dim update before the napi_complete_done() to avoid
concurrently running it.

> 
> [ ... ]
> 
> > @@ -2562,6 +2685,9 @@ static int mana_create_txq(struct
> mana_port_context *apc,
> >  		napi_enable_locked(&cq->napi);
> >  		txq->napi_initialized = true;
> >
> > +		INIT_WORK(&cq->dim.work, mana_tx_dim_work);
> > +		cq->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
> 
> [Severity: High]
> Could this allow NAPI to schedule an uninitialized work_struct?
> 
> napi_enable_locked() is called right before INIT_WORK(). Once NAPI is
> enabled, it can be scheduled to run immediately (for example, via
> netpoll).
> If NAPI executes before INIT_WORK completes, mana_update_tx_dim() would
> pass the uninitialized cq->dim to net_dim(), which could cause a kernel
> panic when it attempts to call schedule_work().
> 
> This pattern also occurs in mana_create_rxq().

I have updated the init order in the new version.

> 
> > diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
> b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
> > index 94e658d07a27e..67a2b282ff4da 100644
> > --- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
> > +++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
> 
> [ ... ]
> 
> > @@ -440,18 +474,123 @@ static int mana_set_coalesce(struct net_device
> *ndev,
> > +		if (enable_rx_dim)
> > +			apc->rx_dim_enabled = true;
> > +		if (enable_tx_dim)
> > +			apc->tx_dim_enabled = true;
> 
> [Severity: High]
> Could the lack of memory barriers here expose uninitialized DIM structures
> to NAPI?
> 
> The driver initializes DIM via mana_dim_change() and then sets
> apc->rx_dim_enabled to true. Without an smp_store_release() here and a
> corresponding smp_load_acquire() in mana_update_rx_dim(), weakly-ordered
> CPUs like ARM64 might reorder the stores. Concurrently, NAPI polling might
> observe the flag as true before the initialization is fully visible in
> memory,
> potentially invoking net_dim() on garbage memory.

I added smp_store_release() & smp_load_acquire() to fix it in the next version.

And, I will submit the next version soon.

Thanks,
- Haiyang


^ permalink raw reply

* Re: [PATCH 01/18] xfrm: cleanup error path in xfrm_add_policy()
From: patchwork-bot+netdevbpf @ 2026-06-13 20:40 UTC (permalink / raw)
  To: Steffen Klassert; +Cc: davem, kuba, herbert, netdev
In-Reply-To: <20260612074725.1760473-2-steffen.klassert@secunet.com>

Hello:

This series was applied to netdev/net-next.git (main)
by Steffen Klassert <steffen.klassert@secunet.com>:

On Fri, 12 Jun 2026 09:46:17 +0200 you wrote:
> From: Deepanshu Kartikey <kartikey406@gmail.com>
> 
> Replace the open-coded manual cleanup in the error path of
> xfrm_add_policy() with xfrm_policy_destroy(), which already
> handles all the necessary cleanup internally. This is consistent
> with how xfrm_policy_construct() handles its own error paths.
> 
> [...]

Here is the summary with links:
  - [01/18] xfrm: cleanup error path in xfrm_add_policy()
    https://git.kernel.org/netdev/net-next/c/a77d172177f3
  - [02/18] xfrm: Reject excessive values for XFRMA_TFCPAD
    https://git.kernel.org/netdev/net-next/c/41c4d3b26f5e
  - [03/18] xfrm: remove redundant assignments
    https://git.kernel.org/netdev/net-next/c/440bf355d32e
  - [04/18] xfrm: add extack to xfrm_init_state
    https://git.kernel.org/netdev/net-next/c/231a1744dc43
  - [05/18] xfrm: allow migration from UDP encapsulated to non-encapsulated ESP
    https://git.kernel.org/netdev/net-next/c/b8addb8884f2
  - [06/18] xfrm: fix NAT-related field inheritance in SA migration
    https://git.kernel.org/netdev/net-next/c/364e165e0b63
  - [07/18] xfrm: rename reqid in xfrm_migrate
    https://git.kernel.org/netdev/net-next/c/e2e92714d081
  - [08/18] xfrm: split xfrm_state_migrate into create and install functions
    https://git.kernel.org/netdev/net-next/c/8de53883a4bf
  - [09/18] xfrm: check family before comparing addresses in migrate
    https://git.kernel.org/netdev/net-next/c/b2cb192b95e5
  - [10/18] xfrm: add state synchronization after migration
    https://git.kernel.org/netdev/net-next/c/bac7a60e2678
  - [11/18] xfrm: add error messages to state migration
    https://git.kernel.org/netdev/net-next/c/15e5d32de6bf
  - [12/18] xfrm: move encap and xuo into struct xfrm_migrate
    https://git.kernel.org/netdev/net-next/c/1d97daee3038
  - [13/18] xfrm: refactor XFRMA_MTIMER_THRESH validation into a helper
    https://git.kernel.org/netdev/net-next/c/92550d30c69b
  - [14/18] xfrm: extract address family and selector validation helpers
    https://git.kernel.org/netdev/net-next/c/38d400e5d0fd
  - [15/18] xfrm: make xfrm_dev_state_add xuo parameter const
    https://git.kernel.org/netdev/net-next/c/8eed5ba25734
  - [16/18] xfrm: add XFRM_MSG_MIGRATE_STATE for single SA migration
    https://git.kernel.org/netdev/net-next/c/a9d155ea9b44
  - [17/18] xfrm: restrict netlink attributes for XFRM_MSG_MIGRATE_STATE
    https://git.kernel.org/netdev/net-next/c/c4460171d78a
  - [18/18] xfrm: add documentation for XFRM_MSG_MIGRATE_STATE
    https://git.kernel.org/netdev/net-next/c/c13c0cc6f52e

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH v14 net-next 00/13] dpll/ice: Add generic DPLL type and full TX reference clock control for E825
From: patchwork-bot+netdevbpf @ 2026-06-13 20:40 UTC (permalink / raw)
  To: Nitka, Grzegorz
  Cc: netdev, linux-kernel, intel-wired-lan, poros, richardcochran,
	andrew+netdev, przemyslaw.kitszel, anthony.l.nguyen,
	Prathosh.Satish, ivecera, jiri, arkadiusz.kubalewski,
	vadim.fedorenko, donald.hunter, horms, pabeni, kuba, davem,
	edumazet
In-Reply-To: <20260607183045.1213735-1-grzegorz.nitka@intel.com>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Sun,  7 Jun 2026 20:30:32 +0200 you wrote:
> NOTE: This series is intentionally submitted on net-next (not
> intel-wired-lan) as early feedback of DPLL subsystem changes is
> welcomed. In the past possible approaches were discussed in [1].
> 
> This series adds TX reference clock support for E825 devices and exposes
> TX clock selection and synchronization status via the Linux DPLL
> subsystem.
> 
> [...]

Here is the summary with links:
  - [v14,net-next,01/13] dpll: add generic DPLL type
    https://git.kernel.org/netdev/net-next/c/9375487c0c78
  - [v14,net-next,02/13] dpll: allow registering FW-identified pin with a different DPLL
    https://git.kernel.org/netdev/net-next/c/c191b319f208
  - [v14,net-next,03/13] dpll: fix stale iteration in dpll_pin_on_pin_unregister()
    https://git.kernel.org/netdev/net-next/c/32239d600236
  - [v14,net-next,04/13] dpll: send delete notification before unregister in on-pin rollback
    https://git.kernel.org/netdev/net-next/c/e83b403eb142
  - [v14,net-next,05/13] dpll: emit per-dpll delete notifications in dpll_pin_on_pin_unregister()
    https://git.kernel.org/netdev/net-next/c/df0ba51ccf87
  - [v14,net-next,06/13] dpll: guard sync-pair removal on full pin unregister
    https://git.kernel.org/netdev/net-next/c/0a5c720a7d57
  - [v14,net-next,07/13] dpll: balance create/delete notifications in __dpll_pin_(un)register
    https://git.kernel.org/netdev/net-next/c/1a2292101c0d
  - [v14,net-next,08/13] dpll: extend pin notifier with notification source ID
    https://git.kernel.org/netdev/net-next/c/0bf47f722fa9
  - [v14,net-next,09/13] dpll: allow fwnode pins to attempt state change without capability bit
    https://git.kernel.org/netdev/net-next/c/521b6d5de08d
  - [v14,net-next,10/13] ice: introduce TXC DPLL device and TX ref clock pin framework for E825
    https://git.kernel.org/netdev/net-next/c/5db36ee62849
  - [v14,net-next,11/13] ice: implement CPI support for E825C
    https://git.kernel.org/netdev/net-next/c/fff4ed70ca9b
  - [v14,net-next,12/13] ice: add Tx reference clock index handling to AN restart command
    https://git.kernel.org/netdev/net-next/c/4128bda8fc1d
  - [v14,net-next,13/13] ice: implement E825 TX ref clock control and TXC hardware sync status
    https://git.kernel.org/netdev/net-next/c/e075d7768386

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH net-next v6 3/5] net: dsa: tag_ks8995: Add the KS8995 tag handling
From: Jakub Kicinski @ 2026-06-13 20:38 UTC (permalink / raw)
  To: Linus Walleij
  Cc: woojung.huh, UNGLinuxDriver, andrew, olteanv, davem, edumazet,
	pabeni, robh, krzk+dt, conor+dt, marex, horms, linux, netdev,
	devicetree, nb
In-Reply-To: <CAD++jLnuBv97nUW-EdZXiLmgsUSiVLgkB0R=gKB0zYtr8JN7xg@mail.gmail.com>

On Sat, 13 Jun 2026 18:56:03 +0200 Linus Walleij wrote:
> Which is what I do.
> 
> So yeah. skb_free() will be free:ed twice. The code in tag_8021q.c will
> also do that. But what do you expect ->xmit() to return on error if
> not NULL?
> 
> When user.c does this:
> 
>     /* Transmit function may have to reallocate the original SKB,
>      * in which case it must have freed it. Only free it here on error.
>      */
>     nskb = p->xmit(skb, dev);
>     if (!nskb) {
>         kfree_skb(skb);
>         return NETDEV_TX_OK;
>     }
> 
>     return dsa_enqueue_skb(nskb, dev);
> 
> The only way to get clean out of this branch if you run
> into an error in ->xmit() is to return NULL!

Yes, maybe DSA experts remember the background here, and can guide us
But from a fresh look this and ->rcv have very odd semantics.

  nskb = func(skb);

should assume skb is either freed or returned. Freeing the input param
on failure of func() is a rather strange pattern.

I vote we drop these kfree_skb()s (both xmit and rcv) and fix up any
driver that depended on them (if any)?

^ permalink raw reply

* Re: [PATCH net-next 4/4] net: dsa: realtek: rtl8366rb: Switch to generic learning enablement
From: Luiz Angelo Daros de Luca @ 2026-06-13 20:28 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Alvin Šipraga, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
In-Reply-To: <20260612-rtl8366rb-improvements-v1-4-9232286fc20c@kernel.org>

Em sex., 12 de jun. de 2026 às 11:23, Linus Walleij
<linusw@kernel.org> escreveu:
>
> Instead of just writing the learning disablement register in setup
> and a custom handling of BR_LEARNING, implement the generic RTL83xx
> .port_set_learning() callback for setting learning on a port, and
> call this in the per-port loop in .setup().
>
> Instead of the custom rtl83366rb_port_bridge_flags() function for
> setting learning mode on each port, use the RTL83xx generic
> rtl83xx_port_bridge_flags() callback.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
>  drivers/net/dsa/realtek/rtl8366rb.c | 43 +++++++++++++++----------------------
>  1 file changed, 17 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
> index 155bf0010d5f..d2fa8ff6a5d0 100644
> --- a/drivers/net/dsa/realtek/rtl8366rb.c
> +++ b/drivers/net/dsa/realtek/rtl8366rb.c
> @@ -854,6 +854,16 @@ rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
>         }
>  }
>
> +static int rtl8366rb_port_set_learning(struct realtek_priv *priv, int port,
> +                                      bool enable)
> +{
> +       /* Notice inverted semantics in this register: setting a bit disables
> +        * learning instead of enabling it.
> +        */
> +       return regmap_update_bits(priv->map, RTL8366RB_PORT_LEARNDIS_CTRL,
> +                                 BIT(port), enable ? 0 : BIT(port));
> +}
> +
>  static int rtl8366rb_setup(struct dsa_switch *ds)
>  {
>         struct realtek_priv *priv = ds->priv;
> @@ -945,6 +955,11 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
>                 if (ret)
>                         return ret;
>
> +               /* Disable learning */
> +               ret = rtl8366rb_port_set_learning(priv, dp->index, false);
> +               if (ret)
> +                       return ret;
> +
>                 /* Collect CPU ports. If we support cascade switches, it should
>                  * also include the upstream DSA ports.
>                  */
> @@ -1037,12 +1052,6 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
>                         rb->max_mtu[i] = ETH_DATA_LEN;
>         }
>
> -       /* Disable learning for all ports */
> -       ret = regmap_write(priv->map, RTL8366RB_PORT_LEARNDIS_CTRL,
> -                          RTL8366RB_PORT_ALL);
> -       if (ret)
> -               return ret;
> -
>         /* Enable auto ageing for all ports */
>         ret = regmap_write(priv->map, RTL8366RB_SECURITY_CTRL, 0);
>         if (ret)
> @@ -1341,25 +1350,6 @@ rtl8366rb_port_pre_bridge_flags(struct dsa_switch *ds, int port,
>         return 0;
>  }
>
> -static int
> -rtl8366rb_port_bridge_flags(struct dsa_switch *ds, int port,
> -                           struct switchdev_brport_flags flags,
> -                           struct netlink_ext_ack *extack)
> -{
> -       struct realtek_priv *priv = ds->priv;
> -       int ret;
> -
> -       if (flags.mask & BR_LEARNING) {
> -               ret = regmap_update_bits(priv->map, RTL8366RB_PORT_LEARNDIS_CTRL,
> -                                        BIT(port),
> -                                        (flags.val & BR_LEARNING) ? 0 : BIT(port));
> -               if (ret)
> -                       return ret;
> -       }
> -
> -       return 0;
> -}
> -
>  static void
>  rtl8366rb_port_fast_age(struct dsa_switch *ds, int port)
>  {
> @@ -1810,7 +1800,7 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops = {
>         .port_enable = rtl8366rb_port_enable,
>         .port_disable = rtl8366rb_port_disable,
>         .port_pre_bridge_flags = rtl8366rb_port_pre_bridge_flags,
> -       .port_bridge_flags = rtl8366rb_port_bridge_flags,
> +       .port_bridge_flags = rtl83xx_port_bridge_flags,
>         .port_stp_state_set = rtl8366rb_port_stp_state_set,
>         .port_fast_age = rtl8366rb_port_fast_age,
>         .port_change_mtu = rtl8366rb_change_mtu,
> @@ -1833,6 +1823,7 @@ static const struct realtek_ops rtl8366rb_ops = {
>         .enable_vlan4k  = rtl8366rb_enable_vlan4k,
>         .port_add_isolation = rtl8366rb_port_add_isolation,
>         .port_remove_isolation = rtl8366rb_port_remove_isolation,
> +       .port_set_learning = rtl8366rb_port_set_learning,

The bridge flags code is fine as it does not touch CPU port but the
.port_set_learning will also be used by bridge join/leave. As I
mentioned in the last patch comment, disabling CPU learning requires
fdb_add/remove. Maybe we should both check if port_set_learning and
fdb is available before disabling CPU learning.

>         .phy_read       = rtl8366rb_phy_read,
>         .phy_write      = rtl8366rb_phy_write,
>  };
>
> --
> 2.54.0
>

Regards,

Luiz

^ permalink raw reply

* Re: [PATCH net-next 1/4] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers
From: Luiz Angelo Daros de Luca @ 2026-06-13 20:28 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Alvin Šipraga, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
In-Reply-To: <20260612-rtl8366rb-improvements-v1-1-9232286fc20c@kernel.org>

Hi Linus,

> The RTL8366RB is using its own sub-standard port isolation code.
>
> Implement the required isolation helpers, use these directly in
> the port setup callback, and switch over to the standard port
> isolation code.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>

> -       .port_bridge_join = rtl8366rb_port_bridge_join,
> -       .port_bridge_leave = rtl8366rb_port_bridge_leave,
> +       .port_bridge_join = rtl83xx_port_bridge_join,
> +       .port_bridge_leave = rtl83xx_port_bridge_leave,

Maybe you wrote this patch based on a previous submission I sent. The
merged code requires both port_set_learning and
port_{add,remove}_isolation. Even if the next patch implements
port_set_learning, it will break bisectability.
You'll need to change rtl83xx.c to make port_set_learning optional in
order to keep the old behavior for rtl8366rb.

If learning remains enabled on the CPU port (as the rtl8366rb driver
works today), the host's MAC entry might eventually expire due to
aging. If that happens, traffic destined to the CPU will momentarily
flood to user ports. It will still work as it does today, but not in
the recommended DSA way.

On the other hand, if you do disable learning on the CPU port, the
driver must implement FDB callbacks so the kernel can statically teach
the switch where the host MAC is. Otherwise, the switch will treat all
host-bound traffic as unknown unicast, flooding it to all user ports
in the same bridge continuously. The worst part is that traffic will
work, but that flooding would be a regression.

My suggestion is to change rtl83xx_port_bridge_{join,leave} to check
for the operation's existence before calling it, preserving the
current state.

>         .port_vlan_filtering = rtl8366rb_vlan_filtering,
>         .port_vlan_add = rtl8366_vlan_add,
>         .port_vlan_del = rtl8366_vlan_del,
> @@ -1830,6 +1792,8 @@ static const struct realtek_ops rtl8366rb_ops = {
>         .is_vlan_valid  = rtl8366rb_is_vlan_valid,
>         .enable_vlan    = rtl8366rb_enable_vlan,
>         .enable_vlan4k  = rtl8366rb_enable_vlan4k,
> +       .port_add_isolation = rtl8366rb_port_add_isolation,
> +       .port_remove_isolation = rtl8366rb_port_remove_isolation,

Regards,

Luiz

^ permalink raw reply

* Re: [PATCH net-next 3/4] net: dsa: realtek: rtl8366rb: Disable STP learning on all ports in setup
From: Luiz Angelo Daros de Luca @ 2026-06-13 20:27 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Alvin Šipraga, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
In-Reply-To: <20260612-rtl8366rb-improvements-v1-3-9232286fc20c@kernel.org>

> +static void
> +rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
> +{
> +       struct realtek_priv *priv = ds->priv;
> +       u32 val;
> +       int i;
> +
> +       switch (state) {
> +       case BR_STATE_DISABLED:
> +               val = RTL8366RB_STP_STATE_DISABLED;
> +               break;
> +       case BR_STATE_BLOCKING:
> +       case BR_STATE_LISTENING:
> +               val = RTL8366RB_STP_STATE_BLOCKING;
> +               break;
> +       case BR_STATE_LEARNING:
> +               val = RTL8366RB_STP_STATE_LEARNING;
> +               break;
> +       case BR_STATE_FORWARDING:
> +               val = RTL8366RB_STP_STATE_FORWARDING;
> +               break;
> +       default:
> +               dev_err(priv->dev, "unknown bridge state requested\n");
> +               return;
> +       }
> +
> +       /* Set the same status for the port on all the FIDs */
> +       for (i = 0; i < RTL8366RB_NUM_FIDS; i++) {
> +               regmap_update_bits(priv->map, RTL8366RB_STP_STATE_BASE + i,
> +                                  RTL8366RB_STP_STATE_MASK(port),
> +                                  RTL8366RB_STP_STATE(port, val));
> +       }

Hum... I might need to check rtl8365mb as well. There we disable only
MSTP/FID 0.

Reviewed-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>

^ permalink raw reply

* Re: [PATCH v14 net-next 03/13] dpll: fix stale iteration in dpll_pin_on_pin_unregister()
From: Jakub Kicinski @ 2026-06-13 20:27 UTC (permalink / raw)
  To: Nitka, Grzegorz
  Cc: Paolo Abeni, netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	intel-wired-lan@lists.osuosl.org, Oros, Petr,
	richardcochran@gmail.com, andrew+netdev@lunn.ch,
	Kitszel, Przemyslaw, Nguyen, Anthony L,
	Prathosh.Satish@microchip.com, Vecera, Ivan, jiri@resnulli.us,
	Kubalewski, Arkadiusz, vadim.fedorenko@linux.dev,
	donald.hunter@gmail.com, horms@kernel.org, davem@davemloft.net,
	edumazet@google.com
In-Reply-To: <IA1PR11MB6219B836E61D44198B0FB5AF921B2@IA1PR11MB6219.namprd11.prod.outlook.com>

On Thu, 11 Jun 2026 18:36:14 +0000 Nitka, Grzegorz wrote:
> For v14 patchset, I got only comments from Arek and Paolo.
> In my opinion, after rethinking, Arek's concerns are not valid (explained in
> the responses). Maybe I could squash some changes, but the final code would
> remain the same as for v14.
> 
> Paolo raised 'Fixes' tags which I added and critical divide-by-zero panic
> Regarding 'Fixes' tag, It might be my fault or misunderstanding.
> I can remove them if we want and re-send the series.
> Regarding div-by-zero - see my comments about AI concern list below.
> 
> Also, what was raised by AI, I unintentionally changed WARN_ON to WARN_ON_ONCE
> in patch 2. I'd restore it to WARN_ON.

Alright, let me apply this.

But please investigate the situation with the notifications.
Maybe there are two create notifications because we add more info
to the second one? If not we should drop the duplicates.. YNL can
monitor the notifications during tests if you need a repro.

You can follow up with the fixes during the merge window.

^ permalink raw reply

* Re: [PATCH net-next 2/4] net: dsa: realtek: rtl8366rb: Use DSA port iterators
From: Luiz Angelo Daros de Luca @ 2026-06-13 20:22 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Alvin Šipraga, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
In-Reply-To: <20260612-rtl8366rb-improvements-v1-2-9232286fc20c@kernel.org>

Em sex., 12 de jun. de 2026 às 11:23, Linus Walleij
<linusw@kernel.org> escreveu:
>
> Instead of custom loops for intializing the ports (including the
> CPU port) use the DSA helpers dsa_switch_for_each_port() and
> dsa_switch_for_each_cpu_port() following the pattern in RTL8365MB by
> accumulatong masks for the upstream and downstream ports.
>
> This gives us similar enough code to the RTL8365MB that we
> can start using more generic rtl83xx helpers.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>

Reviewed-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>

^ permalink raw reply

* Re: [PATCH 0/18] pull request (net-next): ipsec-next 2026-06-12
From: Jakub Kicinski @ 2026-06-13 20:15 UTC (permalink / raw)
  To: Steffen Klassert, Antony Antony; +Cc: David Miller, Herbert Xu, netdev
In-Reply-To: <20260612074725.1760473-1-steffen.klassert@secunet.com>

On Fri, 12 Jun 2026 09:46:16 +0200 Steffen Klassert wrote:
> 3) Add a new netlink message XFRM_MSG_MIGRATE_STATE that
>    allows migrating individual IPsec SAs independently of
>    their policies. The existing XFRM_MSG_MIGRATE is tightly coupled
>    to policy+SA migration, lacks SPI for unique SA identification,
>    and cannot express reqid changes or migrate Transport mode
>    selectors. The new interface identifies the SA via SPI and mark,
>    supports reqid changes, address family changes, encap removal,
>    and uses an atomic create+install flow under x->lock to prevent
>    SN/IV reuse during AEAD SA migration.
>    From Antony Antony.

Hi! There are some Sashiko comments here, please follow up:

https://sashiko.dev/#/patchset/20260612074725.1760473-8-steffen.klassert@secunet.com

^ permalink raw reply

* Re: [PATCH net v3] virtio-net: fix len check in receive_big()
From: Xiang Mei @ 2026-06-13 20:15 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: jasowang, xuanzhuo, eperezma, andrew+netdev, davem, edumazet,
	kuba, pabeni, netdev, virtualization, linux-kernel,
	minhquangbui99, bestswngs
In-Reply-To: <20260611014519-mutt-send-email-mst@kernel.org>

On Wed, Jun 10, 2026 at 10:56 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Wed, Jun 10, 2026 at 07:46:16PM -0700, Xiang Mei wrote:
> > receive_big() bounds the device-announced length by
> > (big_packets_num_skbfrags + 1) * PAGE_SIZE.  That is still too loose:
> > add_recvbuf_big() sets sg[1] to start at offset
> > sizeof(struct padded_vnet_hdr) into the first page, so the chain
> > actually carries hdr_len + (PAGE_SIZE - sizeof(padded_vnet_hdr)) +
> > big_packets_num_skbfrags * PAGE_SIZE bytes -- 20 bytes less than the
> > check allows for the common hdr_len == 12 case.
> >
> > A malicious virtio backend can announce a len in that gap.  page_to_skb()
> > then walks one frag past the page chain, storing a NULL page->private
> > into skb_shinfo()->frags[MAX_SKB_FRAGS], which is both an out-of-bounds
> > write past the static frag array and a NULL frag handed up the rx path.
> >
> > Bound len by the size add_recvbuf_big() actually advertised.
> >
> > Fixes: 0c716703965f ("virtio-net: fix received length check in big packets")
> > Reported-by: Weiming Shi <bestswngs@gmail.com>
> > Signed-off-by: Xiang Mei <xmei5@asu.edu>
> > Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>
> Thanks for the patch! Something small to improve:
>
> > ---
> > v3: revoke 2/2 and add Xuan Zhuo's Reviewed-by tag
> >
> >  drivers/net/virtio_net.c | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index f4adcfee7a80..afe73eda1491 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -1999,15 +1999,17 @@ static struct sk_buff *receive_big(struct net_device *dev,
> >                                  struct virtnet_rq_stats *stats)
> >  {
> >       struct page *page = buf;
> > +     unsigned long max_len;
>
> Assignment can happen here?
>
> >       struct sk_buff *skb;
> >
> >       /* Make sure that len does not exceed the size allocated in
> >        * add_recvbuf_big.
> >        */
> > -     if (unlikely(len > (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE)) {
> > +     max_len = vi->hdr_len + (PAGE_SIZE - sizeof(struct padded_vnet_hdr)) +
> > +               vi->big_packets_num_skbfrags * PAGE_SIZE;
>
> Took me a while to figure out what is going on, but I finally
> understand:
>
>
> Reducing
> (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE
>
> (what we allocated)
>
> by sizeof(struct padded_vnet_hdr) - vi->hdr_len
>
>
> right?
>
> So clearer as:
>
>
>         unsigned long max_len = (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE -
>         sizeof(struct padded_vnet_hdr) + vi->hdr_len;
>
Right, that's the same value. Yours reads better!

I'll fold this into the next respin. One thing I'd like to settle
first: David suggested storing this in a vi field computed once at the
probe (it's a per-device constant) and just comparing len against it
on the datapath, instead of re-deriving it in receive_big() each time.
I'll wait for his take on that and send a single v4 that covers both.

Xiang

>
>
>
> > +     if (unlikely(len > max_len)) {
> >               pr_debug("%s: rx error: len %u exceeds allocated size %lu\n",
> > -                      dev->name, len,
> > -                      (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE);
> > +                      dev->name, len, max_len);
> >               goto err;
> >       }
> >
> > --
> > 2.43.0
>

^ permalink raw reply

* [PATCH net-next 9/9] atm: remove orphaned uAPI for deleted drivers, protocols and SVCs
From: Jakub Kicinski @ 2026-06-13 20:10 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, 3chas3, mitch,
	linux-atm-general, dwmw2, Jakub Kicinski
In-Reply-To: <20260613201032.77274-1-kuba@kernel.org>

ATM removals have left a number of uAPI headers and ioctl
definitions with no in-kernel implementation behind them:

 - device headers for adapters deleted with the legacy PCI/SBUS drivers:
   atm_eni.h, atm_he.h, atm_idt77105.h, atm_nicstar.h, atm_zatm.h and
   the atmtcp pair atm_tcp.h / <linux/atm_tcp.h>
 - protocol headers for the removed CLIP, LANE and MPOA stacks:
   atmarp.h, atmclip.h, atmlec.h, atmmpc.h
 - atmsvc.h and the SVC / p2mp / local-address ioctls in atmdev.h
   (ATM_{GET,RST,ADD,DEL}ADDR, ATM_{ADD,DEL,GET}LECSADDR,
   ATM_{ADD,DROP}PARTY) left behind by the SVC and address-registry
   removals

None of these are referenced by any remaining in-tree code.
Let's try to delete all this. Chances are nobody cares about
these headers any more. I'm keeping this separate from the
kernel side code changes for ease of revert, in case I am
proven wrong...

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 include/linux/atm_tcp.h           |  24 ------
 include/uapi/linux/atm_eni.h      |  24 ------
 include/uapi/linux/atm_he.h       |  21 -----
 include/uapi/linux/atm_idt77105.h |  29 -------
 include/uapi/linux/atm_nicstar.h  |  54 -------------
 include/uapi/linux/atm_tcp.h      |  62 ---------------
 include/uapi/linux/atm_zatm.h     |  47 -----------
 include/uapi/linux/atmarp.h       |  42 ----------
 include/uapi/linux/atmclip.h      |  22 ------
 include/uapi/linux/atmdev.h       |  18 -----
 include/uapi/linux/atmlec.h       |  92 ----------------------
 include/uapi/linux/atmmpc.h       | 127 ------------------------------
 include/uapi/linux/atmsvc.h       |  56 -------------
 net/atm/ioctl.c                   |   1 -
 14 files changed, 619 deletions(-)
 delete mode 100644 include/linux/atm_tcp.h
 delete mode 100644 include/uapi/linux/atm_eni.h
 delete mode 100644 include/uapi/linux/atm_he.h
 delete mode 100644 include/uapi/linux/atm_idt77105.h
 delete mode 100644 include/uapi/linux/atm_nicstar.h
 delete mode 100644 include/uapi/linux/atm_tcp.h
 delete mode 100644 include/uapi/linux/atm_zatm.h
 delete mode 100644 include/uapi/linux/atmarp.h
 delete mode 100644 include/uapi/linux/atmclip.h
 delete mode 100644 include/uapi/linux/atmlec.h
 delete mode 100644 include/uapi/linux/atmmpc.h
 delete mode 100644 include/uapi/linux/atmsvc.h

diff --git a/include/linux/atm_tcp.h b/include/linux/atm_tcp.h
deleted file mode 100644
index 2558439d849b..000000000000
--- a/include/linux/atm_tcp.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* atm_tcp.h - Driver-specific declarations of the ATMTCP driver (for use by
-	       driver-specific utilities) */
-
-/* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-#ifndef LINUX_ATM_TCP_H
-#define LINUX_ATM_TCP_H
-
-#include <uapi/linux/atm_tcp.h>
-
-struct atm_vcc;
-struct module;
-
-struct atm_tcp_ops {
-	int (*attach)(struct atm_vcc *vcc,int itf);
-	int (*create_persistent)(int itf);
-	int (*remove_persistent)(int itf);
-	struct module *owner;
-};
-
-extern struct atm_tcp_ops atm_tcp_ops;
-
-#endif
diff --git a/include/uapi/linux/atm_eni.h b/include/uapi/linux/atm_eni.h
deleted file mode 100644
index cf5bfd1a2691..000000000000
--- a/include/uapi/linux/atm_eni.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* atm_eni.h - Driver-specific declarations of the ENI driver (for use by
-	       driver-specific utilities) */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#ifndef LINUX_ATM_ENI_H
-#define LINUX_ATM_ENI_H
-
-#include <linux/atmioc.h>
-
-
-struct eni_multipliers {
-	int tx,rx;	/* values are in percent and must be > 100 */
-};
-
-
-#define ENI_MEMDUMP     _IOW('a',ATMIOC_SARPRV,struct atmif_sioc)
-                                                /* printk memory map */
-#define ENI_SETMULT	_IOW('a',ATMIOC_SARPRV+7,struct atmif_sioc)
-						/* set buffer multipliers */
-
-#endif
diff --git a/include/uapi/linux/atm_he.h b/include/uapi/linux/atm_he.h
deleted file mode 100644
index 9f4b43293988..000000000000
--- a/include/uapi/linux/atm_he.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* atm_he.h */
-
-#ifndef LINUX_ATM_HE_H
-#define LINUX_ATM_HE_H
-
-#include <linux/atmioc.h>
-
-#define HE_GET_REG	_IOW('a', ATMIOC_SARPRV, struct atmif_sioc)
-
-#define HE_REGTYPE_PCI	1
-#define HE_REGTYPE_RCM	2
-#define HE_REGTYPE_TCM	3
-#define HE_REGTYPE_MBOX	4
-
-struct he_ioctl_reg {
-	unsigned addr, val;
-	char type;
-};
-
-#endif /* LINUX_ATM_HE_H */
diff --git a/include/uapi/linux/atm_idt77105.h b/include/uapi/linux/atm_idt77105.h
deleted file mode 100644
index f0fd6912a14b..000000000000
--- a/include/uapi/linux/atm_idt77105.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* atm_idt77105.h - Driver-specific declarations of the IDT77105 driver (for
- * use by driver-specific utilities) */
-
-/* Written 1999 by Greg Banks <gnb@linuxfan.com>. Copied from atm_suni.h. */
-
-
-#ifndef LINUX_ATM_IDT77105_H
-#define LINUX_ATM_IDT77105_H
-
-#include <linux/types.h>
-#include <linux/atmioc.h>
-#include <linux/atmdev.h>
-
-/*
- * Structure for IDT77105_GETSTAT and IDT77105_GETSTATZ ioctls.
- * Pointed to by `arg' in atmif_sioc.
- */
-struct idt77105_stats {
-        __u32 symbol_errors;  /* wire symbol errors */
-        __u32 tx_cells;       /* cells transmitted */
-        __u32 rx_cells;       /* cells received */
-        __u32 rx_hec_errors;  /* Header Error Check errors on receive */
-};
-
-#define IDT77105_GETSTAT	_IOW('a',ATMIOC_PHYPRV+2,struct atmif_sioc)	/* get stats */
-#define IDT77105_GETSTATZ	_IOW('a',ATMIOC_PHYPRV+3,struct atmif_sioc)	/* get stats and zero */
-
-#endif
diff --git a/include/uapi/linux/atm_nicstar.h b/include/uapi/linux/atm_nicstar.h
deleted file mode 100644
index 880d368b5b9a..000000000000
--- a/include/uapi/linux/atm_nicstar.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/******************************************************************************
- *
- * atm_nicstar.h
- *
- * Driver-specific declarations for use by NICSTAR driver specific utils.
- *
- * Author: Rui Prior
- *
- * (C) INESC 1998
- *
- ******************************************************************************/
-
-
-#ifndef LINUX_ATM_NICSTAR_H
-#define LINUX_ATM_NICSTAR_H
-
-/* Note: non-kernel programs including this file must also include
- * sys/types.h for struct timeval
- */
-
-#include <linux/atmapi.h>
-#include <linux/atmioc.h>
-
-#define NS_GETPSTAT	_IOWR('a',ATMIOC_SARPRV+1,struct atmif_sioc)
-						/* get pool statistics */
-#define NS_SETBUFLEV	_IOW('a',ATMIOC_SARPRV+2,struct atmif_sioc)
-						/* set buffer level markers */
-#define NS_ADJBUFLEV	_IO('a',ATMIOC_SARPRV+3)
-						/* adjust buffer level */
-
-typedef struct buf_nr
-{
-   unsigned min;
-   unsigned init;
-   unsigned max;
-}buf_nr;
-
-
-typedef struct pool_levels
-{
-   int buftype;
-   int count;		/* (At least for now) only used in NS_GETPSTAT */
-   buf_nr level;
-} pool_levels;
-
-/* type must be one of the following: */
-#define NS_BUFTYPE_SMALL 1
-#define NS_BUFTYPE_LARGE 2
-#define NS_BUFTYPE_HUGE 3
-#define NS_BUFTYPE_IOVEC 4
-
-
-#endif /* LINUX_ATM_NICSTAR_H */
diff --git a/include/uapi/linux/atm_tcp.h b/include/uapi/linux/atm_tcp.h
deleted file mode 100644
index 7309e1bc8867..000000000000
--- a/include/uapi/linux/atm_tcp.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* atm_tcp.h - Driver-specific declarations of the ATMTCP driver (for use by
-	       driver-specific utilities) */
-
-/* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#ifndef _UAPILINUX_ATM_TCP_H
-#define _UAPILINUX_ATM_TCP_H
-
-#include <linux/atmapi.h>
-#include <linux/atm.h>
-#include <linux/atmioc.h>
-#include <linux/types.h>
-
-
-/*
- * All values in struct atmtcp_hdr are in network byte order
- */
-
-struct atmtcp_hdr {
-	__u16	vpi;
-	__u16	vci;
-	__u32	length;		/* ... of data part */
-};
-
-/*
- * All values in struct atmtcp_command are in host byte order
- */
-
-#define ATMTCP_HDR_MAGIC	(~0)	/* this length indicates a command */
-#define ATMTCP_CTRL_OPEN	1	/* request/reply */
-#define ATMTCP_CTRL_CLOSE	2	/* request/reply */
-
-struct atmtcp_control {
-	struct atmtcp_hdr hdr;	/* must be first */
-	int type;		/* message type; both directions */
-	atm_kptr_t vcc;		/* both directions */
-	struct sockaddr_atmpvc addr; /* suggested value from kernel */
-	struct atm_qos	qos;	/* both directions */
-	int result;		/* to kernel only */
-} __ATM_API_ALIGN;
-
-/*
- * Field usage:
- * Messge type	dir.	hdr.v?i	type	addr	qos	vcc	result
- * -----------  ----	------- ----	----	---	---	------
- * OPEN		K->D	Y	Y	Y	Y	Y	0
- * OPEN		D->K	-	Y	Y	Y	Y	Y
- * CLOSE	K->D	-	-	Y	-	Y	0
- * CLOSE	D->K	-	-	-	-	Y	Y
- */
-
-#define SIOCSIFATMTCP	_IO('a',ATMIOC_ITF)	/* set ATMTCP mode */
-#define ATMTCP_CREATE	_IO('a',ATMIOC_ITF+14)	/* create persistent ATMTCP
-						   interface */
-#define ATMTCP_REMOVE	_IO('a',ATMIOC_ITF+15)	/* destroy persistent ATMTCP
-						   interface */
-
-
-
-#endif /* _UAPILINUX_ATM_TCP_H */
diff --git a/include/uapi/linux/atm_zatm.h b/include/uapi/linux/atm_zatm.h
deleted file mode 100644
index 5135027b93c1..000000000000
--- a/include/uapi/linux/atm_zatm.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* atm_zatm.h - Driver-specific declarations of the ZATM driver (for use by
-		driver-specific utilities) */
-
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#ifndef LINUX_ATM_ZATM_H
-#define LINUX_ATM_ZATM_H
-
-/*
- * Note: non-kernel programs including this file must also include
- * sys/types.h for struct timeval
- */
-
-#include <linux/atmapi.h>
-#include <linux/atmioc.h>
-
-#define ZATM_GETPOOL	_IOW('a',ATMIOC_SARPRV+1,struct atmif_sioc)
-						/* get pool statistics */
-#define ZATM_GETPOOLZ	_IOW('a',ATMIOC_SARPRV+2,struct atmif_sioc)
-						/* get statistics and zero */
-#define ZATM_SETPOOL	_IOW('a',ATMIOC_SARPRV+3,struct atmif_sioc)
-						/* set pool parameters */
-
-struct zatm_pool_info {
-	int ref_count;			/* free buffer pool usage counters */
-	int low_water,high_water;	/* refill parameters */
-	int rqa_count,rqu_count;	/* queue condition counters */
-	int offset,next_off;		/* alignment optimizations: offset */
-	int next_cnt,next_thres;	/* repetition counter and threshold */
-};
-
-struct zatm_pool_req {
-	int pool_num;			/* pool number */
-	struct zatm_pool_info info;	/* actual information */
-};
-
-#define ZATM_OAM_POOL		0	/* free buffer pool for OAM cells */
-#define ZATM_AAL0_POOL		1	/* free buffer pool for AAL0 cells */
-#define ZATM_AAL5_POOL_BASE	2	/* first AAL5 free buffer pool */
-#define ZATM_LAST_POOL	ZATM_AAL5_POOL_BASE+10 /* max. 64 kB */
-
-#define ZATM_TIMER_HISTORY_SIZE	16	/* number of timer adjustments to
-					   record; must be 2^n */
-
-#endif
diff --git a/include/uapi/linux/atmarp.h b/include/uapi/linux/atmarp.h
deleted file mode 100644
index 8e44d121fde1..000000000000
--- a/include/uapi/linux/atmarp.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* atmarp.h - ATM ARP protocol and kernel-demon interface definitions */
- 
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
- 
-
-#ifndef _LINUX_ATMARP_H
-#define _LINUX_ATMARP_H
-
-#include <linux/types.h>
-#include <linux/atmapi.h>
-#include <linux/atmioc.h>
-
-
-#define ATMARP_RETRY_DELAY 30		/* request next resolution or forget
-					   NAK after 30 sec - should go into
-					   atmclip.h */
-#define ATMARP_MAX_UNRES_PACKETS 5	/* queue that many packets while
-					   waiting for the resolver */
-
-
-#define ATMARPD_CTRL	_IO('a',ATMIOC_CLIP+1)	/* become atmarpd ctrl sock */
-#define ATMARP_MKIP	_IO('a',ATMIOC_CLIP+2)	/* attach socket to IP */
-#define ATMARP_SETENTRY	_IO('a',ATMIOC_CLIP+3)	/* fill or hide ARP entry */
-#define ATMARP_ENCAP	_IO('a',ATMIOC_CLIP+5)	/* change encapsulation */
-
-
-enum atmarp_ctrl_type {
-	act_invalid,		/* catch uninitialized structures */
-	act_need,		/* need address resolution */
-	act_up,			/* interface is coming up */
-	act_down,		/* interface is going down */
-	act_change		/* interface configuration has changed */
-};
-
-struct atmarp_ctrl {
-	enum atmarp_ctrl_type	type;	/* message type */
-	int			itf_num;/* interface number (if present) */
-	__be32			ip;	/* IP address (act_need only) */
-};
-
-#endif
diff --git a/include/uapi/linux/atmclip.h b/include/uapi/linux/atmclip.h
deleted file mode 100644
index c818bb82b4e6..000000000000
--- a/include/uapi/linux/atmclip.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* atmclip.h - Classical IP over ATM */
- 
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
- 
-
-#ifndef LINUX_ATMCLIP_H
-#define LINUX_ATMCLIP_H
-
-#include <linux/sockios.h>
-#include <linux/atmioc.h>
-
-
-#define RFC1483LLC_LEN	8		/* LLC+OUI+PID = 8 */
-#define RFC1626_MTU	9180		/* RFC1626 default MTU */
-
-#define CLIP_DEFAULT_IDLETIMER 1200	/* 20 minutes, see RFC1755 */
-#define CLIP_CHECK_INTERVAL	 10	/* check every ten seconds */
-
-#define	SIOCMKCLIP	_IO('a',ATMIOC_CLIP)	/* create IP interface */
-
-#endif
diff --git a/include/uapi/linux/atmdev.h b/include/uapi/linux/atmdev.h
index 20b0215084fc..a94e7b8360ee 100644
--- a/include/uapi/linux/atmdev.h
+++ b/include/uapi/linux/atmdev.h
@@ -60,14 +60,6 @@ struct atm_dev_stats {
 					/* get interface type name */
 #define ATM_GETESI	_IOW('a',ATMIOC_ITF+5,struct atmif_sioc)
 					/* get interface ESI */
-#define ATM_GETADDR	_IOW('a',ATMIOC_ITF+6,struct atmif_sioc)
-					/* get itf's local ATM addr. list */
-#define ATM_RSTADDR	_IOW('a',ATMIOC_ITF+7,struct atmif_sioc)
-					/* reset itf's ATM address list */
-#define ATM_ADDADDR	_IOW('a',ATMIOC_ITF+8,struct atmif_sioc)
-					/* add a local ATM address */
-#define ATM_DELADDR	_IOW('a',ATMIOC_ITF+9,struct atmif_sioc)
-					/* remove a local ATM address */
 #define ATM_GETCIRANGE	_IOW('a',ATMIOC_ITF+10,struct atmif_sioc)
 					/* get connection identifier range */
 #define ATM_SETCIRANGE	_IOW('a',ATMIOC_ITF+11,struct atmif_sioc)
@@ -76,12 +68,6 @@ struct atm_dev_stats {
 					/* set interface ESI */
 #define ATM_SETESIF	_IOW('a',ATMIOC_ITF+13,struct atmif_sioc)
 					/* force interface ESI */
-#define ATM_ADDLECSADDR	_IOW('a', ATMIOC_ITF+14, struct atmif_sioc)
-					/* register a LECS address */
-#define ATM_DELLECSADDR	_IOW('a', ATMIOC_ITF+15, struct atmif_sioc)
-					/* unregister a LECS address */
-#define ATM_GETLECSADDR	_IOW('a', ATMIOC_ITF+16, struct atmif_sioc)
-					/* retrieve LECS address(es) */
 
 #define ATM_GETSTAT	_IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc)
 					/* get AAL layer statistics */
@@ -99,10 +85,6 @@ struct atm_dev_stats {
 					/* set backend handler */
 #define ATM_NEWBACKENDIF _IOW('a',ATMIOC_SPECIAL+3,atm_backend_t)
 					/* use backend to make new if */
-#define ATM_ADDPARTY  	_IOW('a', ATMIOC_SPECIAL+4,struct atm_iobuf)
- 					/* add party to p2mp call */
-#define ATM_DROPPARTY 	_IOW('a', ATMIOC_SPECIAL+5,int)
-					/* drop party from p2mp call */
 
 /*
  * These are backend handkers that can be set via the ATM_SETBACKEND call
diff --git a/include/uapi/linux/atmlec.h b/include/uapi/linux/atmlec.h
deleted file mode 100644
index c68346bb40e6..000000000000
--- a/include/uapi/linux/atmlec.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * ATM Lan Emulation Daemon driver interface
- *
- * Marko Kiiskila <mkiiskila@yahoo.com>
- */
-
-#ifndef _ATMLEC_H_
-#define _ATMLEC_H_
-
-#include <linux/atmapi.h>
-#include <linux/atmioc.h>
-#include <linux/atm.h>
-#include <linux/if_ether.h>
-#include <linux/types.h>
-
-/* ATM lec daemon control socket */
-#define ATMLEC_CTRL	_IO('a', ATMIOC_LANE)
-#define ATMLEC_DATA	_IO('a', ATMIOC_LANE+1)
-#define ATMLEC_MCAST	_IO('a', ATMIOC_LANE+2)
-
-/* Maximum number of LEC interfaces (tweakable) */
-#define MAX_LEC_ITF 48
-
-typedef enum {
-	l_set_mac_addr,
-	l_del_mac_addr,
-	l_svc_setup,
-	l_addr_delete,
-	l_topology_change,
-	l_flush_complete,
-	l_arp_update,
-	l_narp_req,		/* LANE2 mandates the use of this */
-	l_config,
-	l_flush_tran_id,
-	l_set_lecid,
-	l_arp_xmt,
-	l_rdesc_arp_xmt,
-	l_associate_req,
-	l_should_bridge		/* should we bridge this MAC? */
-} atmlec_msg_type;
-
-#define ATMLEC_MSG_TYPE_MAX l_should_bridge
-
-struct atmlec_config_msg {
-	unsigned int maximum_unknown_frame_count;
-	unsigned int max_unknown_frame_time;
-	unsigned short max_retry_count;
-	unsigned int aging_time;
-	unsigned int forward_delay_time;
-	unsigned int arp_response_time;
-	unsigned int flush_timeout;
-	unsigned int path_switching_delay;
-	unsigned int lane_version;	/* LANE2: 1 for LANEv1, 2 for LANEv2 */
-	int mtu;
-	int is_proxy;
-};
-
-struct atmlec_msg {
-	atmlec_msg_type type;
-	int sizeoftlvs;		/* LANE2: if != 0, tlvs follow */
-	union {
-		struct {
-			unsigned char mac_addr[ETH_ALEN];
-			unsigned char atm_addr[ATM_ESA_LEN];
-			unsigned int flag;	/*
-						 * Topology_change flag,
-						 * remoteflag, permanent flag,
-						 * lecid, transaction id
-						 */
-			unsigned int targetless_le_arp;	/* LANE2 */
-			unsigned int no_source_le_narp;	/* LANE2 */
-		} normal;
-		struct atmlec_config_msg config;
-		struct {
-			__u16 lec_id;				/* requestor lec_id  */
-			__u32 tran_id;				/* transaction id    */
-			unsigned char mac_addr[ETH_ALEN];	/* dst mac addr      */
-			unsigned char atm_addr[ATM_ESA_LEN];	/* reqestor ATM addr */
-		} proxy;	/*
-				 * For mapping LE_ARP requests to responses. Filled by
-				 * zeppelin, returned by kernel. Used only when proxying
-				 */
-	} content;
-} __ATM_API_ALIGN;
-
-struct atmlec_ioc {
-	int dev_num;
-	unsigned char atm_addr[ATM_ESA_LEN];
-	unsigned char receive;	/* 1= receive vcc, 0 = send vcc */
-};
-#endif /* _ATMLEC_H_ */
diff --git a/include/uapi/linux/atmmpc.h b/include/uapi/linux/atmmpc.h
deleted file mode 100644
index cc17f4304839..000000000000
--- a/include/uapi/linux/atmmpc.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _ATMMPC_H_
-#define _ATMMPC_H_
-
-#include <linux/atmapi.h>
-#include <linux/atmioc.h>
-#include <linux/atm.h>
-#include <linux/types.h>
-
-#define ATMMPC_CTRL _IO('a', ATMIOC_MPOA)
-#define ATMMPC_DATA _IO('a', ATMIOC_MPOA+1)
-
-#define MPC_SOCKET_INGRESS 1
-#define MPC_SOCKET_EGRESS  2
-
-struct atmmpc_ioc {
-        int dev_num;
-        __be32 ipaddr;              /* the IP address of the shortcut    */
-        int type;                     /* ingress or egress                 */
-};
-
-typedef struct in_ctrl_info {
-        __u8   Last_NHRP_CIE_code;
-        __u8   Last_Q2931_cause_value;
-        __u8   eg_MPC_ATM_addr[ATM_ESA_LEN];
-        __be32  tag;
-        __be32  in_dst_ip;      /* IP address this ingress MPC sends packets to */
-        __u16  holding_time;
-        __u32  request_id;
-} in_ctrl_info;
-
-typedef struct eg_ctrl_info {
-        __u8   DLL_header[256];
-        __u8   DH_length;
-        __be32  cache_id;
-        __be32  tag;
-        __be32  mps_ip;
-        __be32  eg_dst_ip;      /* IP address to which ingress MPC sends packets */
-        __u8   in_MPC_data_ATM_addr[ATM_ESA_LEN];
-        __u16  holding_time;
-} eg_ctrl_info;
-
-struct mpc_parameters {
-        __u16 mpc_p1;   /* Shortcut-Setup Frame Count    */
-        __u16 mpc_p2;   /* Shortcut-Setup Frame Time     */
-        __u8 mpc_p3[8]; /* Flow-detection Protocols      */
-        __u16 mpc_p4;   /* MPC Initial Retry Time        */
-        __u16 mpc_p5;   /* MPC Retry Time Maximum        */
-        __u16 mpc_p6;   /* Hold Down Time                */
-} ;
-
-struct k_message {
-        __u16 type;
-        __be32 ip_mask;
-        __u8  MPS_ctrl[ATM_ESA_LEN];
-        union {
-                in_ctrl_info in_info;
-                eg_ctrl_info eg_info;
-                struct mpc_parameters params;
-        } content;
-        struct atm_qos qos;       
-} __ATM_API_ALIGN;
-
-struct llc_snap_hdr {
-	/* RFC 1483 LLC/SNAP encapsulation for routed IP PDUs */
-        __u8  dsap;    /* Destination Service Access Point (0xAA)     */
-        __u8  ssap;    /* Source Service Access Point      (0xAA)     */
-        __u8  ui;      /* Unnumbered Information           (0x03)     */
-        __u8  org[3];  /* Organizational identification    (0x000000) */
-        __u8  type[2]; /* Ether type (for IP)              (0x0800)   */
-};
-
-/* TLVs this MPC recognizes */
-#define TLV_MPOA_DEVICE_TYPE         0x00a03e2a  
-
-/* MPOA device types in MPOA Device Type TLV */
-#define NON_MPOA    0
-#define MPS         1
-#define MPC         2
-#define MPS_AND_MPC 3
-
-
-/* MPC parameter defaults */
-
-#define MPC_P1 10  /* Shortcut-Setup Frame Count  */ 
-#define MPC_P2 1   /* Shortcut-Setup Frame Time   */
-#define MPC_P3 0   /* Flow-detection Protocols    */
-#define MPC_P4 5   /* MPC Initial Retry Time      */
-#define MPC_P5 40  /* MPC Retry Time Maximum      */
-#define MPC_P6 160 /* Hold Down Time              */
-#define HOLDING_TIME_DEFAULT 1200 /* same as MPS-p7 */
-
-/* MPC constants */
-
-#define MPC_C1 2   /* Retry Time Multiplier       */
-#define MPC_C2 60  /* Initial Keep-Alive Lifetime */
-
-/* Message types - to MPOA daemon */
-
-#define SND_MPOA_RES_RQST    201
-#define SET_MPS_CTRL_ADDR    202
-#define SND_MPOA_RES_RTRY    203 /* Different type in a retry due to req id         */
-#define STOP_KEEP_ALIVE_SM   204
-#define EGRESS_ENTRY_REMOVED 205
-#define SND_EGRESS_PURGE     206
-#define DIE                  207 /* tell the daemon to exit()                       */
-#define DATA_PLANE_PURGE     208 /* Data plane purge because of egress cache hit miss or dead MPS */
-#define OPEN_INGRESS_SVC     209
-
-/* Message types - from MPOA daemon */
-
-#define MPOA_TRIGGER_RCVD     101
-#define MPOA_RES_REPLY_RCVD   102
-#define INGRESS_PURGE_RCVD    103
-#define EGRESS_PURGE_RCVD     104
-#define MPS_DEATH             105
-#define CACHE_IMPOS_RCVD      106
-#define SET_MPC_CTRL_ADDR     107 /* Our MPC's control ATM address   */
-#define SET_MPS_MAC_ADDR      108
-#define CLEAN_UP_AND_EXIT     109
-#define SET_MPC_PARAMS        110 /* MPC configuration parameters    */
-
-/* Message types - bidirectional */       
-
-#define RELOAD                301 /* kill -HUP the daemon for reload */
-
-#endif /* _ATMMPC_H_ */
diff --git a/include/uapi/linux/atmsvc.h b/include/uapi/linux/atmsvc.h
deleted file mode 100644
index 137b5f853449..000000000000
--- a/include/uapi/linux/atmsvc.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* atmsvc.h - ATM signaling kernel-demon interface definitions */
- 
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
- 
-
-#ifndef _LINUX_ATMSVC_H
-#define _LINUX_ATMSVC_H
-
-#include <linux/atmapi.h>
-#include <linux/atm.h>
-#include <linux/atmioc.h>
-
-
-#define ATMSIGD_CTRL _IO('a',ATMIOC_SPECIAL)
-				/* become ATM signaling demon control socket */
-
-enum atmsvc_msg_type { as_catch_null, as_bind, as_connect, as_accept, as_reject,
-		       as_listen, as_okay, as_error, as_indicate, as_close,
-		       as_itf_notify, as_modify, as_identify, as_terminate,
-		       as_addparty, as_dropparty };
-
-struct atmsvc_msg {
-	enum atmsvc_msg_type type;
-	atm_kptr_t vcc;
-	atm_kptr_t listen_vcc;		/* indicate */
-	int reply;			/* for okay and close:		   */
-					/*   < 0: error before active	   */
-					/*        (sigd has discarded ctx) */
-					/*   ==0: success		   */
-				        /*   > 0: error when active (still */
-					/*        need to close)	   */
-	struct sockaddr_atmpvc pvc;	/* indicate, okay (connect) */
-	struct sockaddr_atmsvc local;	/* local SVC address */
-	struct atm_qos qos;		/* QOS parameters */
-	struct atm_sap sap;		/* SAP */
-	unsigned int session;		/* for p2pm */
-	struct sockaddr_atmsvc svc;	/* SVC address */
-} __ATM_API_ALIGN;
-
-/*
- * Message contents: see ftp://icaftp.epfl.ch/pub/linux/atm/docs/isp-*.tar.gz
- */
-
-/*
- * Some policy stuff for atmsigd and for net/atm/svc.c. Both have to agree on
- * what PCR is used to request bandwidth from the device driver. net/atm/svc.c
- * tries to do better than that, but only if there's no routing decision (i.e.
- * if signaling only uses one ATM interface).
- */
-
-#define SELECT_TOP_PCR(tp) ((tp).pcr ? (tp).pcr : \
-  (tp).max_pcr && (tp).max_pcr != ATM_MAX_PCR ? (tp).max_pcr : \
-  (tp).min_pcr ? (tp).min_pcr : ATM_MAX_PCR)
-
-#endif
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index 11f6d236f5d6..194587fc15e8 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -11,7 +11,6 @@
 #include <linux/net.h>		/* struct socket, struct proto_ops */
 #include <linux/atm.h>		/* ATM stuff */
 #include <linux/atmdev.h>
-#include <linux/atmarp.h>	/* manifest constants */
 #include <linux/capability.h>
 #include <linux/mutex.h>
 #include <asm/ioctls.h>
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next 8/9] atm: remove unused ATM PHY operations
From: Jakub Kicinski @ 2026-06-13 20:10 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, 3chas3, mitch,
	linux-atm-general, dwmw2, Jakub Kicinski
In-Reply-To: <20260613201032.77274-1-kuba@kernel.org>

The PHY operations are vestiges of the SAR/framer split used by the
removed PCI/SBUS ATM adapters:

 - atmdev_ops::phy_put / ::phy_get (register accessors) are never called
   by the core and solos-pci only listed them as NULL
 - struct atmphy_ops and atm_dev::phy have no users at all - nothing
   assigns or dereferences them

Remove all of them. atm_dev::phy_data is kept: solos-pci repurposes it
to stash its per-port channel index.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 include/linux/atmdev.h  | 12 ------------
 drivers/atm/solos-pci.c |  2 --
 2 files changed, 14 deletions(-)

diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 96ce36e02247..fe21d2f547b5 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -107,8 +107,6 @@ static inline struct sock *sk_atm(struct atm_vcc *vcc)
 
 struct atm_dev {
 	const struct atmdev_ops *ops;	/* device operations; NULL if unused */
-	const struct atmphy_ops *phy;	/* PHY operations, may be undefined */
-					/* (NULL) */
 	const char	*type;		/* device type name */
 	int		number;		/* device index */
 	void		*dev_data;	/* per-device data */
@@ -138,20 +136,10 @@ struct atmdev_ops { /* only send is required */
 			    void __user *arg);
 #endif
 	int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
-	void (*phy_put)(struct atm_dev *dev,unsigned char value,
-	    unsigned long addr);
-	unsigned char (*phy_get)(struct atm_dev *dev,unsigned long addr);
 	int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page);
 	struct module *owner;
 };
 
-struct atmphy_ops {
-	int (*start)(struct atm_dev *dev);
-	int (*ioctl)(struct atm_dev *dev,unsigned int cmd,void __user *arg);
-	void (*interrupt)(struct atm_dev *dev);
-	int (*stop)(struct atm_dev *dev);
-};
-
 struct atm_skb_data {
 	struct atm_vcc	*vcc;		/* ATM VCC */
 	unsigned long	atm_options;	/* ATM layer options */
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 9c246b956c30..fc0e91a1029e 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -1180,8 +1180,6 @@ static const struct atmdev_ops fpga_ops = {
 	.close =	pclose,
 	.ioctl =	NULL,
 	.send =		psend,
-	.phy_put =	NULL,
-	.phy_get =	NULL,
 	.proc_read =	NULL,
 	.owner =	THIS_MODULE
 };
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next 7/9] atm: remove the unused pre_send and send_bh device operations
From: Jakub Kicinski @ 2026-06-13 20:10 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, 3chas3, mitch,
	linux-atm-general, dwmw2, Jakub Kicinski
In-Reply-To: <20260613201032.77274-1-kuba@kernel.org>

atmdev_ops::pre_send (a TX pre-processing hook) and ::send_bh (a
bottom-half capable send variant) have no implementation behind them:
no remaining ATM driver sets either, so vcc_sendmsg() always skipped
pre_send and the raw AAL0/AAL5 paths always fell back to ->send().
The drivers that used these hooks were removed with the legacy ATM
adapters.

Drop both operations and the dead branches that tested for them.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 include/linux/atmdev.h | 2 --
 net/atm/common.c       | 6 ------
 net/atm/raw.c          | 7 +------
 3 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 218c05f2ec54..96ce36e02247 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -137,9 +137,7 @@ struct atmdev_ops { /* only send is required */
 	int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd,
 			    void __user *arg);
 #endif
-	int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb);
 	int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
-	int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb);
 	void (*phy_put)(struct atm_dev *dev,unsigned char value,
 	    unsigned long addr);
 	unsigned char (*phy_get)(struct atm_dev *dev,unsigned long addr);
diff --git a/net/atm/common.c b/net/atm/common.c
index 44a0179d4586..654cbe3c855e 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -626,12 +626,6 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
 	if (eff != size)
 		memset(skb->data + size, 0, eff-size);
 
-	if (vcc->dev->ops->pre_send) {
-		error = vcc->dev->ops->pre_send(vcc, skb);
-		if (error)
-			goto free_skb;
-	}
-
 	error = vcc->dev->ops->send(vcc, skb);
 	error = error ? error : size;
 out:
diff --git a/net/atm/raw.c b/net/atm/raw.c
index 1d6ac7b0c4e5..87d136c7554b 100644
--- a/net/atm/raw.c
+++ b/net/atm/raw.c
@@ -54,8 +54,6 @@ static int atm_send_aal0(struct atm_vcc *vcc, struct sk_buff *skb)
 		kfree_skb(skb);
 		return -EADDRNOTAVAIL;
 	}
-	if (vcc->dev->ops->send_bh)
-		return vcc->dev->ops->send_bh(vcc, skb);
 	return vcc->dev->ops->send(vcc, skb);
 }
 
@@ -71,10 +69,7 @@ int atm_init_aal5(struct atm_vcc *vcc)
 {
 	vcc->push = atm_push_raw;
 	vcc->pop = atm_pop_raw;
-	if (vcc->dev->ops->send_bh)
-		vcc->send = vcc->dev->ops->send_bh;
-	else
-		vcc->send = vcc->dev->ops->send;
+	vcc->send = vcc->dev->ops->send;
 	return 0;
 }
 EXPORT_SYMBOL(atm_init_aal5);
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next 6/9] atm: remove the unused change_qos device operation
From: Jakub Kicinski @ 2026-06-13 20:10 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, 3chas3, mitch,
	linux-atm-general, dwmw2, Jakub Kicinski
In-Reply-To: <20260613201032.77274-1-kuba@kernel.org>

atmdev_ops::change_qos() was the hook for renegotiating the traffic
parameters of an already-connected VCC, driven from SO_ATMQOS on a
connected socket (and previously from the SVC as_modify path, now gone).
None of the ATM drivers left in tree implement it - solos-pci only listed
change_qos = NULL - so atm_change_qos() always returned -EOPNOTSUPP.

Drop the operation and return -EOPNOTSUPP directly.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 include/linux/atmdev.h  |  1 -
 drivers/atm/solos-pci.c |  1 -
 net/atm/common.c        | 25 ++-----------------------
 3 files changed, 2 insertions(+), 25 deletions(-)

diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 59477676063c..218c05f2ec54 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -143,7 +143,6 @@ struct atmdev_ops { /* only send is required */
 	void (*phy_put)(struct atm_dev *dev,unsigned char value,
 	    unsigned long addr);
 	unsigned char (*phy_get)(struct atm_dev *dev,unsigned long addr);
-	int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos,int flags);
 	int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page);
 	struct module *owner;
 };
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 4ad170a858ee..9c246b956c30 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -1182,7 +1182,6 @@ static const struct atmdev_ops fpga_ops = {
 	.send =		psend,
 	.phy_put =	NULL,
 	.phy_get =	NULL,
-	.change_qos =	NULL,
 	.proc_read =	NULL,
 	.owner =	THIS_MODULE
 };
diff --git a/net/atm/common.c b/net/atm/common.c
index 650814d0a56c..44a0179d4586 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -673,28 +673,6 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
 	return mask;
 }
 
-static int atm_change_qos(struct atm_vcc *vcc, struct atm_qos *qos)
-{
-	int error;
-
-	/*
-	 * Don't let the QoS change the already connected AAL type nor the
-	 * traffic class.
-	 */
-	if (qos->aal != vcc->qos.aal ||
-	    qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class ||
-	    qos->txtp.traffic_class != vcc->qos.txtp.traffic_class)
-		return -EINVAL;
-	error = adjust_tp(&qos->txtp, qos->aal);
-	if (!error)
-		error = adjust_tp(&qos->rxtp, qos->aal);
-	if (error)
-		return error;
-	if (!vcc->dev->ops->change_qos)
-		return -EOPNOTSUPP;
-	return vcc->dev->ops->change_qos(vcc, qos, ATM_MF_SET);
-}
-
 static int check_tp(const struct atm_trafprm *tp)
 {
 	/* @@@ Should be merged with adjust_tp */
@@ -753,8 +731,9 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
 		error = check_qos(&qos);
 		if (error)
 			return error;
+		/* QoS cannot be renegotiated on an already connected VCC. */
 		if (sock->state == SS_CONNECTED)
-			return atm_change_qos(vcc, &qos);
+			return -EOPNOTSUPP;
 		if (sock->state != SS_UNCONNECTED)
 			return -EBADFD;
 		vcc->qos = qos;
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next 5/9] atm: remove SVC socket support and the signaling daemon interface
From: Jakub Kicinski @ 2026-06-13 20:10 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, 3chas3, mitch,
	linux-atm-general, dwmw2, Jakub Kicinski
In-Reply-To: <20260613201032.77274-1-kuba@kernel.org>

ATM switched virtual circuits (SVCs) are set up and torn down by a
user-space signaling daemon (atmsigd) which the kernel talks to over
a dedicated "sigd" socket: the kernel marshals Q.2931-style requests
(as_connect, as_listen, as_accept, as_close, ...) to the daemon and
applies the results to PF_ATMSVC sockets. This is the machinery behind
classical SVC use and was the foundation for LANE / MPOA, all of which
have been removed.

DSL deployments do not use any of this. PPPoATM and BR2684 run over
permanent virtual circuits (PF_ATMPVC) with a statically configured
VPI/VCI; no atmsigd, no Q.2931. Neither remaining ATM driver
(solos-pci, the USB DSL modems) is reachable through the SVC path.

Remove the SVC socket family and the signaling interface:

 - delete net/atm/svc.c, net/atm/signaling.c and signaling.h
 - drop atmsvc_init()/atmsvc_exit() and the PF_ATMSVC registration and
   module alias
 - drop the ATMSIGD_CTRL ioctl (sigd_attach) and the /proc/net/atm/svc
   file
 - fold the SVC branch out of atm_change_qos(); all sockets are PVCs now

The obsolete ATM_SETSC ioctl stub is left in place (it already just
warns and returns 0), as is the struct atm_vcc SVC bookkeeping shared
with the queueing layer.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 net/atm/Makefile       |   2 +-
 include/linux/atmdev.h |  38 +--
 net/atm/common.h       |   5 -
 net/atm/signaling.h    |  31 --
 net/atm/br2684.c       |   3 +-
 net/atm/common.c       |  35 +--
 net/atm/ioctl.c        |  32 --
 net/atm/pppoatm.c      |   3 +-
 net/atm/proc.c         |  56 ----
 net/atm/resources.c    |   1 -
 net/atm/signaling.c    | 297 ------------------
 net/atm/svc.c          | 694 -----------------------------------------
 12 files changed, 12 insertions(+), 1185 deletions(-)
 delete mode 100644 net/atm/signaling.h
 delete mode 100644 net/atm/signaling.c
 delete mode 100644 net/atm/svc.c

diff --git a/net/atm/Makefile b/net/atm/Makefile
index 5ed48d50df35..0a14ea7d4683 100644
--- a/net/atm/Makefile
+++ b/net/atm/Makefile
@@ -3,7 +3,7 @@
 # Makefile for the ATM Protocol Families.
 #
 
-atm-y		:= pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o
+atm-y		:= pvc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o
 
 obj-$(CONFIG_ATM) += atm.o
 obj-$(CONFIG_ATM_BR2684) += br2684.o
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 7abbd23fada6..59477676063c 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -51,33 +51,11 @@ enum {
 				   driver, cleared by anybody. */
 	ATM_VF_PARTIAL,		/* resources are bound to PVC (partial PVC
 				   setup), controlled by socket layer */
-	ATM_VF_REGIS,		/* registered with demon, controlled by SVC
-				   socket layer */
-	ATM_VF_BOUND,		/* local SAP is set, controlled by SVC socket
-				   layer */
-	ATM_VF_RELEASED,	/* demon has indicated/requested release,
-				   controlled by SVC socket layer */
 	ATM_VF_HASQOS,		/* QOS parameters have been set */
-	ATM_VF_LISTEN,		/* socket is used for listening */
-	ATM_VF_META,		/* SVC socket isn't used for normal data
-				   traffic and doesn't depend on signaling
-				   to be available */
-	ATM_VF_SESSION,		/* VCC is p2mp session control descriptor */
-	ATM_VF_HASSAP,		/* SAP has been set */
-	ATM_VF_CLOSE,		/* asynchronous close - treat like VF_RELEASED*/
-	ATM_VF_WAITING,		/* waiting for reply from sigd */
-	ATM_VF_IS_CLIP,		/* in use by CLIP protocol */
+	ATM_VF_CLOSE,		/* asynchronous close - VC is being torn down */
 };
 
 
-#define ATM_VF2VS(flags) \
-    (test_bit(ATM_VF_READY,&(flags)) ? ATM_VS_CONNECTED : \
-     test_bit(ATM_VF_RELEASED,&(flags)) ? ATM_VS_CLOSING : \
-     test_bit(ATM_VF_LISTEN,&(flags)) ? ATM_VS_LISTEN : \
-     test_bit(ATM_VF_REGIS,&(flags)) ? ATM_VS_INUSE : \
-     test_bit(ATM_VF_BOUND,&(flags)) ? ATM_VS_BOUND : ATM_VS_IDLE)
-
-
 enum {
 	ATM_DF_REMOVED,		/* device was removed from atm_devs list */
 };
@@ -100,7 +78,6 @@ struct atm_vcc {
 	unsigned long	atm_options;	/* ATM layer options */
 	struct atm_dev	*dev;		/* device back pointer */
 	struct atm_qos	qos;		/* QOS */
-	struct atm_sap	sap;		/* SAP */
 	void (*release_cb)(struct atm_vcc *vcc); /* release_sock callback */
 	void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
 	void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
@@ -109,16 +86,8 @@ struct atm_vcc {
 	void		*proto_data;	/* per-protocol data */
 	struct k_atm_aal_stats *stats;	/* pointer to AAL stats group */
 	struct module *owner;		/* owner of ->push function */
-	/* SVC part --- may move later ------------------------------------- */
-	short		itf;		/* interface number */
-	struct sockaddr_atmsvc local;
-	struct sockaddr_atmsvc remote;
-	/* Multipoint part ------------------------------------------------- */
-	struct atm_vcc	*session;	/* session VCC descriptor */
-	/* Other stuff ----------------------------------------------------- */
-	void		*user_back;	/* user backlink - not touched by */
-					/* native ATM stack. Currently used */
-					/* by CLIP and sch_atm. */
+	void		*user_back;	/* user backlink - not touched by the */
+					/* native ATM stack, used by sch_atm */
 };
 
 static inline struct atm_vcc *atm_sk(struct sock *sk)
@@ -151,7 +120,6 @@ struct atm_dev {
 	char		signal;		/* signal status (ATM_PHY_SIG_*) */
 	int		link_rate;	/* link rate (default: OC3) */
 	refcount_t	refcnt;		/* reference count */
-	spinlock_t	lock;		/* protect internal members */
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *proc_entry; /* proc entry */
 	char *proc_name;		/* proc entry name */
diff --git a/net/atm/common.h b/net/atm/common.h
index ae4502abf028..11cb51dd7dbb 100644
--- a/net/atm/common.h
+++ b/net/atm/common.h
@@ -28,8 +28,6 @@ void vcc_process_recv_queue(struct atm_vcc *vcc);
 
 int atmpvc_init(void);
 void atmpvc_exit(void);
-int atmsvc_init(void);
-void atmsvc_exit(void);
 int atm_sysfs_init(void);
 void atm_sysfs_exit(void);
 
@@ -48,9 +46,6 @@ static inline void atm_proc_exit(void)
 }
 #endif /* CONFIG_PROC_FS */
 
-/* SVC */
-int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
-
 void atm_dev_release_vccs(struct atm_dev *dev);
 
 #endif
diff --git a/net/atm/signaling.h b/net/atm/signaling.h
deleted file mode 100644
index 2df8220f7ab5..000000000000
--- a/net/atm/signaling.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* net/atm/signaling.h - ATM signaling */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#ifndef NET_ATM_SIGNALING_H
-#define NET_ATM_SIGNALING_H
-
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/atmsvc.h>
-
-
-extern struct atm_vcc *sigd; /* needed in svc_release */
-
-
-/*
- * sigd_enq is a wrapper for sigd_enq2, covering the more common cases, and
- * avoiding huge lists of null values.
- */
-
-void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
-    struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
-    const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply);
-void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
-    struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
-    const struct sockaddr_atmsvc *svc);
-int sigd_attach(struct atm_vcc *vcc);
-
-#endif
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 6580d67c3456..05712c28386a 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -311,8 +311,7 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
 
 	bh_lock_sock(sk_atm(atmvcc));
 
-	if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) ||
-	    test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
+	if (test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
 	    !test_bit(ATM_VF_READY, &atmvcc->flags)) {
 		dev->stats.tx_dropped++;
 		dev_kfree_skb(skb);
diff --git a/net/atm/common.c b/net/atm/common.c
index 7d5b7c39b80b..650814d0a56c 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -30,7 +30,6 @@
 #include "resources.h"		/* atm_find_dev */
 #include "common.h"		/* prototypes */
 #include "protocols.h"		/* atm_init_<transport> */
-#include "signaling.h"		/* for WAITING and sigd_attach */
 
 struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
 EXPORT_SYMBOL(vcc_hash);
@@ -154,8 +153,6 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family, i
 
 	vcc = atm_sk(sk);
 	vcc->dev = NULL;
-	memset(&vcc->local, 0, sizeof(struct sockaddr_atmsvc));
-	memset(&vcc->remote, 0, sizeof(struct sockaddr_atmsvc));
 	vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
 	refcount_set(&sk->sk_wmem_alloc, SK_WMEM_ALLOC_BIAS);
 	atomic_set(&sk->sk_rmem_alloc, 0);
@@ -216,7 +213,6 @@ void vcc_release_async(struct atm_vcc *vcc, int reply)
 	set_bit(ATM_VF_CLOSE, &vcc->flags);
 	sk->sk_shutdown |= RCV_SHUTDOWN;
 	sk->sk_err = -reply;
-	clear_bit(ATM_VF_WAITING, &vcc->flags);
 	sk->sk_state_change(sk);
 }
 EXPORT_SYMBOL(vcc_release_async);
@@ -527,8 +523,7 @@ int vcc_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
 		return -EOPNOTSUPP;
 
 	vcc = ATM_SD(sock);
-	if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
-	    test_bit(ATM_VF_CLOSE, &vcc->flags) ||
+	if (test_bit(ATM_VF_CLOSE, &vcc->flags) ||
 	    !test_bit(ATM_VF_READY, &vcc->flags))
 		return 0;
 
@@ -575,8 +570,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
 		goto out;
 	}
 	vcc = ATM_SD(sock);
-	if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
-	    test_bit(ATM_VF_CLOSE, &vcc->flags) ||
+	if (test_bit(ATM_VF_CLOSE, &vcc->flags) ||
 	    !test_bit(ATM_VF_READY, &vcc->flags)) {
 		error = -EPIPE;
 		send_sig(SIGPIPE, current, 0);
@@ -604,8 +598,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
 			error = -ERESTARTSYS;
 			break;
 		}
-		if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
-		    test_bit(ATM_VF_CLOSE, &vcc->flags) ||
+		if (test_bit(ATM_VF_CLOSE, &vcc->flags) ||
 		    !test_bit(ATM_VF_READY, &vcc->flags)) {
 			error = -EPIPE;
 			send_sig(SIGPIPE, current, 0);
@@ -665,8 +658,7 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
 	if (sk->sk_err)
 		mask = EPOLLERR;
 
-	if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
-	    test_bit(ATM_VF_CLOSE, &vcc->flags))
+	if (test_bit(ATM_VF_CLOSE, &vcc->flags))
 		mask |= EPOLLHUP;
 
 	/* readable? */
@@ -674,10 +666,6 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
 		mask |= EPOLLIN | EPOLLRDNORM;
 
 	/* writable? */
-	if (sock->state == SS_CONNECTING &&
-	    test_bit(ATM_VF_WAITING, &vcc->flags))
-		return mask;
-
 	if (vcc->qos.txtp.traffic_class != ATM_NONE &&
 	    vcc_writable(sk))
 		mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
@@ -704,9 +692,7 @@ static int atm_change_qos(struct atm_vcc *vcc, struct atm_qos *qos)
 		return error;
 	if (!vcc->dev->ops->change_qos)
 		return -EOPNOTSUPP;
-	if (sk_atm(vcc)->sk_family == AF_ATMPVC)
-		return vcc->dev->ops->change_qos(vcc, qos, ATM_MF_SET);
-	return svc_change_qos(vcc, qos);
+	return vcc->dev->ops->change_qos(vcc, qos, ATM_MF_SET);
 }
 
 static int check_tp(const struct atm_trafprm *tp)
@@ -854,15 +840,10 @@ static int __init atm_init(void)
 		pr_err("atmpvc_init() failed with %d\n", error);
 		goto out_unregister_vcc_proto;
 	}
-	error = atmsvc_init();
-	if (error < 0) {
-		pr_err("atmsvc_init() failed with %d\n", error);
-		goto out_atmpvc_exit;
-	}
 	error = atm_proc_init();
 	if (error < 0) {
 		pr_err("atm_proc_init() failed with %d\n", error);
-		goto out_atmsvc_exit;
+		goto out_atmpvc_exit;
 	}
 	error = atm_sysfs_init();
 	if (error < 0) {
@@ -873,8 +854,6 @@ static int __init atm_init(void)
 	return error;
 out_atmproc_exit:
 	atm_proc_exit();
-out_atmsvc_exit:
-	atmsvc_exit();
 out_atmpvc_exit:
 	atmpvc_exit();
 out_unregister_vcc_proto:
@@ -886,7 +865,6 @@ static void __exit atm_exit(void)
 {
 	atm_proc_exit();
 	atm_sysfs_exit();
-	atmsvc_exit();
 	atmpvc_exit();
 	proto_unregister(&vcc_proto);
 }
@@ -898,4 +876,3 @@ module_exit(atm_exit);
 MODULE_DESCRIPTION("Asynchronous Transfer Mode (ATM) networking core");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NETPROTO(PF_ATMPVC);
-MODULE_ALIAS_NETPROTO(PF_ATMSVC);
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index 97f20cd051ed..11f6d236f5d6 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -13,13 +13,11 @@
 #include <linux/atmdev.h>
 #include <linux/atmarp.h>	/* manifest constants */
 #include <linux/capability.h>
-#include <linux/atmsvc.h>
 #include <linux/mutex.h>
 #include <asm/ioctls.h>
 #include <net/compat.h>
 
 #include "resources.h"
-#include "signaling.h"		/* for WAITING and sigd_attach */
 #include "common.h"
 
 
@@ -86,36 +84,6 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
 				     current->comm, task_pid_nr(current));
 		error = 0;
 		goto done;
-	case ATMSIGD_CTRL:
-		if (!capable(CAP_NET_ADMIN)) {
-			error = -EPERM;
-			goto done;
-		}
-		/*
-		 * The user/kernel protocol for exchanging signalling
-		 * info uses kernel pointers as opaque references,
-		 * so the holder of the file descriptor can scribble
-		 * on the kernel... so we should make sure that we
-		 * have the same privileges that /proc/kcore needs
-		 */
-		if (!capable(CAP_SYS_RAWIO)) {
-			error = -EPERM;
-			goto done;
-		}
-#ifdef CONFIG_COMPAT
-		/* WTF? I don't even want to _think_ about making this
-		   work for 32-bit userspace. TBH I don't really want
-		   to think about it at all. dwmw2. */
-		if (compat) {
-			net_warn_ratelimited("32-bit task cannot be atmsigd\n");
-			error = -EINVAL;
-			goto done;
-		}
-#endif
-		error = sigd_attach(vcc);
-		if (!error)
-			sock->state = SS_CONNECTED;
-		goto done;
 	case ATM_SETBACKEND:
 	case ATM_NEWBACKENDIF:
 	{
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index e3c422dc533a..6da52d12df68 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -308,8 +308,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
 		test_and_set_bit(BLOCKED, &pvcc->blocked);
 		goto nospace;
 	}
-	if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
-	    test_bit(ATM_VF_CLOSE, &vcc->flags) ||
+	if (test_bit(ATM_VF_CLOSE, &vcc->flags) ||
 	    !test_bit(ATM_VF_READY, &vcc->flags)) {
 		bh_unlock_sock(sk_atm(vcc));
 		kfree_skb(skb);
diff --git a/net/atm/proc.c b/net/atm/proc.c
index b650da764a23..8f20b49b9c02 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -29,7 +29,6 @@
 #include <linux/atomic.h>
 #include "resources.h"
 #include "common.h" /* atm_proc_init prototype */
-#include "signaling.h" /* to get sigd - ugly too */
 
 static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
 				 size_t count, loff_t *pos);
@@ -156,13 +155,6 @@ static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
 	seq_putc(seq, '\n');
 }
 
-static const char *vcc_state(struct atm_vcc *vcc)
-{
-	static const char *const map[] = { ATM_VS2TXT_MAP };
-
-	return map[ATM_VF2VS(vcc->flags)];
-}
-
 static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
 {
 	struct sock *sk = sk_atm(vcc);
@@ -177,9 +169,6 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
 	case AF_ATMPVC:
 		seq_printf(seq, "PVC");
 		break;
-	case AF_ATMSVC:
-		seq_printf(seq, "SVC");
-		break;
 	default:
 		seq_printf(seq, "%3d", sk->sk_family);
 	}
@@ -190,26 +179,6 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
 		   refcount_read(&sk->sk_refcnt));
 }
 
-static void svc_info(struct seq_file *seq, struct atm_vcc *vcc)
-{
-	if (!vcc->dev)
-		seq_printf(seq, sizeof(void *) == 4 ?
-			   "N/A@%pK%10s" : "N/A@%pK%2s", vcc, "");
-	else
-		seq_printf(seq, "%3d %3d %5d         ",
-			   vcc->dev->number, vcc->vpi, vcc->vci);
-	seq_printf(seq, "%-10s ", vcc_state(vcc));
-	seq_printf(seq, "%s%s", vcc->remote.sas_addr.pub,
-	    *vcc->remote.sas_addr.pub && *vcc->remote.sas_addr.prv ? "+" : "");
-	if (*vcc->remote.sas_addr.prv) {
-		int i;
-
-		for (i = 0; i < ATM_ESA_LEN; i++)
-			seq_printf(seq, "%02x", vcc->remote.sas_addr.prv[i]);
-	}
-	seq_putc(seq, '\n');
-}
-
 static int atm_dev_seq_show(struct seq_file *seq, void *v)
 {
 	static char atm_dev_banner[] =
@@ -278,29 +247,6 @@ static const struct seq_operations vcc_seq_ops = {
 	.show	= vcc_seq_show,
 };
 
-static int svc_seq_show(struct seq_file *seq, void *v)
-{
-	static const char atm_svc_banner[] =
-		"Itf VPI VCI           State      Remote\n";
-
-	if (v == SEQ_START_TOKEN)
-		seq_puts(seq, atm_svc_banner);
-	else {
-		struct vcc_state *state = seq->private;
-		struct atm_vcc *vcc = atm_sk(state->sk);
-
-		svc_info(seq, vcc);
-	}
-	return 0;
-}
-
-static const struct seq_operations svc_seq_ops = {
-	.start	= vcc_seq_start,
-	.next	= vcc_seq_next,
-	.stop	= vcc_seq_stop,
-	.show	= svc_seq_show,
-};
-
 static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
 				 size_t count, loff_t *pos)
 {
@@ -376,8 +322,6 @@ int __init atm_proc_init(void)
 	proc_create_seq("devices", 0444, atm_proc_root, &atm_dev_seq_ops);
 	proc_create_seq_private("pvc", 0444, atm_proc_root, &pvc_seq_ops,
 			sizeof(struct vcc_state), (void *)(uintptr_t)PF_ATMPVC);
-	proc_create_seq_private("svc", 0444, atm_proc_root, &svc_seq_ops,
-			sizeof(struct vcc_state), (void *)(uintptr_t)PF_ATMSVC);
 	proc_create_seq_private("vc", 0444, atm_proc_root, &vcc_seq_ops,
 			sizeof(struct vcc_state), NULL);
 	return 0;
diff --git a/net/atm/resources.c b/net/atm/resources.c
index a08f65aacf75..3fa4b0df63a8 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -40,7 +40,6 @@ static struct atm_dev *__alloc_atm_dev(const char *type)
 	dev->type = type;
 	dev->signal = ATM_PHY_SIG_UNKNOWN;
 	dev->link_rate = ATM_OC3_PCR;
-	spin_lock_init(&dev->lock);
 
 	return dev;
 }
diff --git a/net/atm/signaling.c b/net/atm/signaling.c
deleted file mode 100644
index b991d937205a..000000000000
--- a/net/atm/signaling.c
+++ /dev/null
@@ -1,297 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* net/atm/signaling.c - ATM signaling */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-#include <linux/errno.h>	/* error codes */
-#include <linux/kernel.h>	/* printk */
-#include <linux/skbuff.h>
-#include <linux/wait.h>
-#include <linux/sched.h>	/* jiffies and HZ */
-#include <linux/atm.h>		/* ATM stuff */
-#include <linux/atmsap.h>
-#include <linux/atmsvc.h>
-#include <linux/atmdev.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-
-#include "resources.h"
-#include "signaling.h"
-
-struct atm_vcc *sigd = NULL;
-
-/*
- * find_get_vcc - validate and get a reference to a vcc pointer
- * @vcc: the vcc pointer to validate
- *
- * This function validates that @vcc points to a registered VCC in vcc_hash.
- * If found, it increments the socket reference count and returns the vcc.
- * The caller must call sock_put(sk_atm(vcc)) when done.
- *
- * Returns the vcc pointer if valid, NULL otherwise.
- */
-static struct atm_vcc *find_get_vcc(struct atm_vcc *vcc)
-{
-	int i;
-
-	read_lock(&vcc_sklist_lock);
-	for (i = 0; i < VCC_HTABLE_SIZE; i++) {
-		struct sock *s;
-
-		sk_for_each(s, &vcc_hash[i]) {
-			if (atm_sk(s) == vcc) {
-				sock_hold(s);
-				read_unlock(&vcc_sklist_lock);
-				return vcc;
-			}
-		}
-	}
-	read_unlock(&vcc_sklist_lock);
-	return NULL;
-}
-
-static void sigd_put_skb(struct sk_buff *skb)
-{
-	if (!sigd) {
-		pr_debug("atmsvc: no signaling daemon\n");
-		kfree_skb(skb);
-		return;
-	}
-	atm_force_charge(sigd, skb->truesize);
-	skb_queue_tail(&sk_atm(sigd)->sk_receive_queue, skb);
-	sk_atm(sigd)->sk_data_ready(sk_atm(sigd));
-}
-
-static void modify_qos(struct atm_vcc *vcc, struct atmsvc_msg *msg)
-{
-	struct sk_buff *skb;
-
-	if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
-	    !test_bit(ATM_VF_READY, &vcc->flags))
-		return;
-	msg->type = as_error;
-	if (!vcc->dev->ops->change_qos)
-		msg->reply = -EOPNOTSUPP;
-	else {
-		/* should lock VCC */
-		msg->reply = vcc->dev->ops->change_qos(vcc, &msg->qos,
-						       msg->reply);
-		if (!msg->reply)
-			msg->type = as_okay;
-	}
-	/*
-	 * Should probably just turn around the old skb. But then, the buffer
-	 * space accounting needs to follow the change too. Maybe later.
-	 */
-	while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL)))
-		schedule();
-	*(struct atmsvc_msg *)skb_put(skb, sizeof(struct atmsvc_msg)) = *msg;
-	sigd_put_skb(skb);
-}
-
-static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb)
-{
-	struct atmsvc_msg *msg;
-	struct atm_vcc *session_vcc;
-	struct sock *sk;
-
-	msg = (struct atmsvc_msg *) skb->data;
-	WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
-
-	vcc = find_get_vcc(*(struct atm_vcc **)&msg->vcc);
-	if (!vcc) {
-		pr_debug("invalid vcc pointer in msg\n");
-		dev_kfree_skb(skb);
-		return -EINVAL;
-	}
-
-	pr_debug("%d (0x%lx)\n", (int)msg->type, (unsigned long)vcc);
-	sk = sk_atm(vcc);
-
-	switch (msg->type) {
-	case as_okay:
-		sk->sk_err = -msg->reply;
-		clear_bit(ATM_VF_WAITING, &vcc->flags);
-		if (!*vcc->local.sas_addr.prv && !*vcc->local.sas_addr.pub) {
-			vcc->local.sas_family = AF_ATMSVC;
-			memcpy(vcc->local.sas_addr.prv,
-			       msg->local.sas_addr.prv, ATM_ESA_LEN);
-			memcpy(vcc->local.sas_addr.pub,
-			       msg->local.sas_addr.pub, ATM_E164_LEN + 1);
-		}
-		session_vcc = vcc->session ? vcc->session : vcc;
-		if (session_vcc->vpi || session_vcc->vci)
-			break;
-		session_vcc->itf = msg->pvc.sap_addr.itf;
-		session_vcc->vpi = msg->pvc.sap_addr.vpi;
-		session_vcc->vci = msg->pvc.sap_addr.vci;
-		if (session_vcc->vpi || session_vcc->vci)
-			session_vcc->qos = msg->qos;
-		break;
-	case as_error:
-		clear_bit(ATM_VF_REGIS, &vcc->flags);
-		clear_bit(ATM_VF_READY, &vcc->flags);
-		sk->sk_err = -msg->reply;
-		clear_bit(ATM_VF_WAITING, &vcc->flags);
-		break;
-	case as_indicate:
-		/* Release the reference from msg->vcc, we'll use msg->listen_vcc instead */
-		sock_put(sk);
-
-		vcc = find_get_vcc(*(struct atm_vcc **)&msg->listen_vcc);
-		if (!vcc) {
-			pr_debug("invalid listen_vcc pointer in msg\n");
-			dev_kfree_skb(skb);
-			return -EINVAL;
-		}
-
-		sk = sk_atm(vcc);
-		pr_debug("as_indicate!!!\n");
-		lock_sock(sk);
-		if (sk_acceptq_is_full(sk)) {
-			sigd_enq(NULL, as_reject, vcc, NULL, NULL);
-			dev_kfree_skb(skb);
-			goto as_indicate_complete;
-		}
-		sk_acceptq_added(sk);
-		skb_queue_tail(&sk->sk_receive_queue, skb);
-		pr_debug("waking sk_sleep(sk) 0x%p\n", sk_sleep(sk));
-		sk->sk_state_change(sk);
-as_indicate_complete:
-		release_sock(sk);
-		/* Paired with find_get_vcc(msg->listen_vcc) above */
-		sock_put(sk);
-		return 0;
-	case as_close:
-		set_bit(ATM_VF_RELEASED, &vcc->flags);
-		vcc_release_async(vcc, msg->reply);
-		goto out;
-	case as_modify:
-		modify_qos(vcc, msg);
-		break;
-	case as_addparty:
-	case as_dropparty:
-		WRITE_ONCE(sk->sk_err_soft, -msg->reply);
-					/* < 0 failure, otherwise ep_ref */
-		clear_bit(ATM_VF_WAITING, &vcc->flags);
-		break;
-	default:
-		pr_alert("bad message type %d\n", (int)msg->type);
-		dev_kfree_skb(skb);
-		/* Paired with find_get_vcc(msg->vcc) above */
-		sock_put(sk);
-		return -EINVAL;
-	}
-	sk->sk_state_change(sk);
-out:
-	dev_kfree_skb(skb);
-	/* Paired with find_get_vcc(msg->vcc) above */
-	sock_put(sk);
-	return 0;
-}
-
-void sigd_enq2(struct atm_vcc *vcc, enum atmsvc_msg_type type,
-	       struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc,
-	       const struct sockaddr_atmsvc *svc, const struct atm_qos *qos,
-	       int reply)
-{
-	struct sk_buff *skb;
-	struct atmsvc_msg *msg;
-	static unsigned int session = 0;
-
-	pr_debug("%d (0x%p)\n", (int)type, vcc);
-	while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL)))
-		schedule();
-	msg = skb_put_zero(skb, sizeof(struct atmsvc_msg));
-	msg->type = type;
-	*(struct atm_vcc **) &msg->vcc = vcc;
-	*(struct atm_vcc **) &msg->listen_vcc = listen_vcc;
-	msg->reply = reply;
-	if (qos)
-		msg->qos = *qos;
-	if (vcc)
-		msg->sap = vcc->sap;
-	if (svc)
-		msg->svc = *svc;
-	if (vcc)
-		msg->local = vcc->local;
-	if (pvc)
-		msg->pvc = *pvc;
-	if (vcc) {
-		if (type == as_connect && test_bit(ATM_VF_SESSION, &vcc->flags))
-			msg->session = ++session;
-			/* every new pmp connect gets the next session number */
-	}
-	sigd_put_skb(skb);
-	if (vcc)
-		set_bit(ATM_VF_REGIS, &vcc->flags);
-}
-
-void sigd_enq(struct atm_vcc *vcc, enum atmsvc_msg_type type,
-	      struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc,
-	      const struct sockaddr_atmsvc *svc)
-{
-	sigd_enq2(vcc, type, listen_vcc, pvc, svc, vcc ? &vcc->qos : NULL, 0);
-	/* other ISP applications may use "reply" */
-}
-
-static void purge_vcc(struct atm_vcc *vcc)
-{
-	if (sk_atm(vcc)->sk_family == PF_ATMSVC &&
-	    !test_bit(ATM_VF_META, &vcc->flags)) {
-		set_bit(ATM_VF_RELEASED, &vcc->flags);
-		clear_bit(ATM_VF_REGIS, &vcc->flags);
-		vcc_release_async(vcc, -EUNATCH);
-	}
-}
-
-static void sigd_close(struct atm_vcc *vcc)
-{
-	struct sock *s;
-	int i;
-
-	pr_debug("\n");
-	sigd = NULL;
-	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
-		pr_err("closing with requests pending\n");
-	skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
-
-	read_lock(&vcc_sklist_lock);
-	for (i = 0; i < VCC_HTABLE_SIZE; ++i) {
-		struct hlist_head *head = &vcc_hash[i];
-
-		sk_for_each(s, head) {
-			vcc = atm_sk(s);
-
-			purge_vcc(vcc);
-		}
-	}
-	read_unlock(&vcc_sklist_lock);
-}
-
-static const struct atmdev_ops sigd_dev_ops = {
-	.close = sigd_close,
-	.send =	sigd_send
-};
-
-static struct atm_dev sigd_dev = {
-	.ops =		&sigd_dev_ops,
-	.type =		"sig",
-	.number =	999,
-	.lock =		__SPIN_LOCK_UNLOCKED(sigd_dev.lock)
-};
-
-int sigd_attach(struct atm_vcc *vcc)
-{
-	if (sigd)
-		return -EADDRINUSE;
-	pr_debug("\n");
-	sigd = vcc;
-	vcc->dev = &sigd_dev;
-	vcc_insert_socket(sk_atm(vcc));
-	set_bit(ATM_VF_META, &vcc->flags);
-	set_bit(ATM_VF_READY, &vcc->flags);
-	return 0;
-}
diff --git a/net/atm/svc.c b/net/atm/svc.c
deleted file mode 100644
index 270e95154a2b..000000000000
--- a/net/atm/svc.c
+++ /dev/null
@@ -1,694 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* net/atm/svc.c - ATM SVC sockets */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
-
-#include <linux/string.h>
-#include <linux/net.h>		/* struct socket, struct proto_ops */
-#include <linux/errno.h>	/* error codes */
-#include <linux/kernel.h>	/* printk */
-#include <linux/skbuff.h>
-#include <linux/wait.h>
-#include <linux/sched/signal.h>
-#include <linux/fcntl.h>	/* O_NONBLOCK */
-#include <linux/init.h>
-#include <linux/atm.h>		/* ATM stuff */
-#include <linux/atmsap.h>
-#include <linux/atmsvc.h>
-#include <linux/atmdev.h>
-#include <linux/bitops.h>
-#include <net/sock.h>		/* for sock_no_* */
-#include <linux/uaccess.h>
-#include <linux/uio.h>
-#include <linux/export.h>
-
-#include "resources.h"
-#include "common.h"		/* common for PVCs and SVCs */
-#include "signaling.h"
-
-#ifdef CONFIG_COMPAT
-/* It actually takes struct sockaddr_atmsvc, not struct atm_iobuf */
-#define COMPAT_ATM_ADDPARTY _IOW('a', ATMIOC_SPECIAL + 4, struct compat_atm_iobuf)
-#endif
-
-static int svc_create(struct net *net, struct socket *sock, int protocol,
-		      int kern);
-
-/*
- * Note: since all this is still nicely synchronized with the signaling demon,
- *       there's no need to protect sleep loops with clis. If signaling is
- *       moved into the kernel, that would change.
- */
-
-
-static int svc_shutdown(struct socket *sock, int how)
-{
-	return 0;
-}
-
-static void svc_disconnect(struct atm_vcc *vcc)
-{
-	DEFINE_WAIT(wait);
-	struct sk_buff *skb;
-	struct sock *sk = sk_atm(vcc);
-
-	pr_debug("%p\n", vcc);
-	if (test_bit(ATM_VF_REGIS, &vcc->flags)) {
-		sigd_enq(vcc, as_close, NULL, NULL, NULL);
-		for (;;) {
-			prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
-			if (test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd)
-				break;
-			schedule();
-		}
-		finish_wait(sk_sleep(sk), &wait);
-	}
-	/* beware - socket is still in use by atmsigd until the last
-	   as_indicate has been answered */
-	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
-		atm_return(vcc, skb->truesize);
-		pr_debug("LISTEN REL\n");
-		sigd_enq2(NULL, as_reject, vcc, NULL, NULL, &vcc->qos, 0);
-		dev_kfree_skb(skb);
-	}
-	clear_bit(ATM_VF_REGIS, &vcc->flags);
-	/* ... may retry later */
-}
-
-static int svc_release(struct socket *sock)
-{
-	struct sock *sk = sock->sk;
-	struct atm_vcc *vcc;
-
-	if (sk) {
-		vcc = ATM_SD(sock);
-		pr_debug("%p\n", vcc);
-		clear_bit(ATM_VF_READY, &vcc->flags);
-		/*
-		 * VCC pointer is used as a reference,
-		 * so we must not free it (thereby subjecting it to re-use)
-		 * before all pending connections are closed
-		 */
-		svc_disconnect(vcc);
-		vcc_release(sock);
-	}
-	return 0;
-}
-
-static int svc_bind(struct socket *sock, struct sockaddr_unsized *sockaddr,
-		    int sockaddr_len)
-{
-	DEFINE_WAIT(wait);
-	struct sock *sk = sock->sk;
-	struct sockaddr_atmsvc *addr;
-	struct atm_vcc *vcc;
-	int error;
-
-	if (sockaddr_len != sizeof(struct sockaddr_atmsvc))
-		return -EINVAL;
-	lock_sock(sk);
-	if (sock->state == SS_CONNECTED) {
-		error = -EISCONN;
-		goto out;
-	}
-	if (sock->state != SS_UNCONNECTED) {
-		error = -EINVAL;
-		goto out;
-	}
-	vcc = ATM_SD(sock);
-	addr = (struct sockaddr_atmsvc *) sockaddr;
-	if (addr->sas_family != AF_ATMSVC) {
-		error = -EAFNOSUPPORT;
-		goto out;
-	}
-	clear_bit(ATM_VF_BOUND, &vcc->flags);
-	    /* failing rebind will kill old binding */
-	/* @@@ check memory (de)allocation on rebind */
-	if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
-		error = -EBADFD;
-		goto out;
-	}
-	vcc->local = *addr;
-	set_bit(ATM_VF_WAITING, &vcc->flags);
-	sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local);
-	for (;;) {
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
-		if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
-			break;
-		schedule();
-	}
-	finish_wait(sk_sleep(sk), &wait);
-	clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */
-	if (!sigd) {
-		error = -EUNATCH;
-		goto out;
-	}
-	if (!sk->sk_err)
-		set_bit(ATM_VF_BOUND, &vcc->flags);
-	error = -sk->sk_err;
-out:
-	release_sock(sk);
-	return error;
-}
-
-static int svc_connect(struct socket *sock, struct sockaddr_unsized *sockaddr,
-		       int sockaddr_len, int flags)
-{
-	DEFINE_WAIT(wait);
-	struct sock *sk = sock->sk;
-	struct sockaddr_atmsvc *addr;
-	struct atm_vcc *vcc = ATM_SD(sock);
-	int error;
-
-	pr_debug("%p\n", vcc);
-	lock_sock(sk);
-	if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) {
-		error = -EINVAL;
-		goto out;
-	}
-
-	switch (sock->state) {
-	default:
-		error = -EINVAL;
-		goto out;
-	case SS_CONNECTED:
-		error = -EISCONN;
-		goto out;
-	case SS_CONNECTING:
-		if (test_bit(ATM_VF_WAITING, &vcc->flags)) {
-			error = -EALREADY;
-			goto out;
-		}
-		sock->state = SS_UNCONNECTED;
-		if (sk->sk_err) {
-			error = -sk->sk_err;
-			goto out;
-		}
-		break;
-	case SS_UNCONNECTED:
-		addr = (struct sockaddr_atmsvc *) sockaddr;
-		if (addr->sas_family != AF_ATMSVC) {
-			error = -EAFNOSUPPORT;
-			goto out;
-		}
-		if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
-			error = -EBADFD;
-			goto out;
-		}
-		if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS ||
-		    vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) {
-			error = -EINVAL;
-			goto out;
-		}
-		if (!vcc->qos.txtp.traffic_class &&
-		    !vcc->qos.rxtp.traffic_class) {
-			error = -EINVAL;
-			goto out;
-		}
-		vcc->remote = *addr;
-		set_bit(ATM_VF_WAITING, &vcc->flags);
-		sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote);
-		if (flags & O_NONBLOCK) {
-			sock->state = SS_CONNECTING;
-			error = -EINPROGRESS;
-			goto out;
-		}
-		error = 0;
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
-		while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
-			schedule();
-			if (!signal_pending(current)) {
-				prepare_to_wait(sk_sleep(sk), &wait,
-						TASK_INTERRUPTIBLE);
-				continue;
-			}
-			pr_debug("*ABORT*\n");
-			/*
-			 * This is tricky:
-			 *   Kernel ---close--> Demon
-			 *   Kernel <--close--- Demon
-			 * or
-			 *   Kernel ---close--> Demon
-			 *   Kernel <--error--- Demon
-			 * or
-			 *   Kernel ---close--> Demon
-			 *   Kernel <--okay---- Demon
-			 *   Kernel <--close--- Demon
-			 */
-			sigd_enq(vcc, as_close, NULL, NULL, NULL);
-			while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
-				prepare_to_wait(sk_sleep(sk), &wait,
-						TASK_INTERRUPTIBLE);
-				schedule();
-			}
-			if (!sk->sk_err)
-				while (!test_bit(ATM_VF_RELEASED, &vcc->flags) &&
-				       sigd) {
-					prepare_to_wait(sk_sleep(sk), &wait,
-							TASK_INTERRUPTIBLE);
-					schedule();
-				}
-			clear_bit(ATM_VF_REGIS, &vcc->flags);
-			clear_bit(ATM_VF_RELEASED, &vcc->flags);
-			clear_bit(ATM_VF_CLOSE, &vcc->flags);
-			    /* we're gone now but may connect later */
-			error = -EINTR;
-			break;
-		}
-		finish_wait(sk_sleep(sk), &wait);
-		if (error)
-			goto out;
-		if (!sigd) {
-			error = -EUNATCH;
-			goto out;
-		}
-		if (sk->sk_err) {
-			error = -sk->sk_err;
-			goto out;
-		}
-	}
-
-	vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp);
-	vcc->qos.txtp.pcr = 0;
-	vcc->qos.txtp.min_pcr = 0;
-
-	error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci);
-	if (!error)
-		sock->state = SS_CONNECTED;
-	else
-		(void)svc_disconnect(vcc);
-out:
-	release_sock(sk);
-	return error;
-}
-
-static int svc_listen(struct socket *sock, int backlog)
-{
-	DEFINE_WAIT(wait);
-	struct sock *sk = sock->sk;
-	struct atm_vcc *vcc = ATM_SD(sock);
-	int error;
-
-	pr_debug("%p\n", vcc);
-	lock_sock(sk);
-	/* let server handle listen on unbound sockets */
-	if (test_bit(ATM_VF_SESSION, &vcc->flags)) {
-		error = -EINVAL;
-		goto out;
-	}
-	if (test_bit(ATM_VF_LISTEN, &vcc->flags)) {
-		error = -EADDRINUSE;
-		goto out;
-	}
-	set_bit(ATM_VF_WAITING, &vcc->flags);
-	sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local);
-	for (;;) {
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
-		if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
-			break;
-		schedule();
-	}
-	finish_wait(sk_sleep(sk), &wait);
-	if (!sigd) {
-		error = -EUNATCH;
-		goto out;
-	}
-	set_bit(ATM_VF_LISTEN, &vcc->flags);
-	vcc_insert_socket(sk);
-	sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
-	error = -sk->sk_err;
-out:
-	release_sock(sk);
-	return error;
-}
-
-static int svc_accept(struct socket *sock, struct socket *newsock,
-		      struct proto_accept_arg *arg)
-{
-	struct sock *sk = sock->sk;
-	struct sk_buff *skb;
-	struct atmsvc_msg *msg;
-	struct atm_vcc *old_vcc = ATM_SD(sock);
-	struct atm_vcc *new_vcc;
-	int error;
-
-	lock_sock(sk);
-
-	error = svc_create(sock_net(sk), newsock, 0, arg->kern);
-	if (error)
-		goto out;
-
-	new_vcc = ATM_SD(newsock);
-
-	pr_debug("%p -> %p\n", old_vcc, new_vcc);
-	while (1) {
-		DEFINE_WAIT(wait);
-
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
-		while (!(skb = skb_dequeue(&sk->sk_receive_queue)) &&
-		       sigd) {
-			if (test_bit(ATM_VF_RELEASED, &old_vcc->flags))
-				break;
-			if (test_bit(ATM_VF_CLOSE, &old_vcc->flags)) {
-				error = -sk->sk_err;
-				break;
-			}
-			if (arg->flags & O_NONBLOCK) {
-				error = -EAGAIN;
-				break;
-			}
-			release_sock(sk);
-			schedule();
-			lock_sock(sk);
-			if (signal_pending(current)) {
-				error = -ERESTARTSYS;
-				break;
-			}
-			prepare_to_wait(sk_sleep(sk), &wait,
-					TASK_INTERRUPTIBLE);
-		}
-		finish_wait(sk_sleep(sk), &wait);
-		if (error)
-			goto out;
-		if (!skb) {
-			error = -EUNATCH;
-			goto out;
-		}
-		msg = (struct atmsvc_msg *)skb->data;
-		new_vcc->qos = msg->qos;
-		set_bit(ATM_VF_HASQOS, &new_vcc->flags);
-		new_vcc->remote = msg->svc;
-		new_vcc->local = msg->local;
-		new_vcc->sap = msg->sap;
-		error = vcc_connect(newsock, msg->pvc.sap_addr.itf,
-				    msg->pvc.sap_addr.vpi,
-				    msg->pvc.sap_addr.vci);
-		dev_kfree_skb(skb);
-		sk_acceptq_removed(sk);
-		if (error) {
-			sigd_enq2(NULL, as_reject, old_vcc, NULL, NULL,
-				  &old_vcc->qos, error);
-			error = error == -EAGAIN ? -EBUSY : error;
-			goto out;
-		}
-		/* wait should be short, so we ignore the non-blocking flag */
-		set_bit(ATM_VF_WAITING, &new_vcc->flags);
-		sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL);
-		for (;;) {
-			prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait,
-					TASK_UNINTERRUPTIBLE);
-			if (!test_bit(ATM_VF_WAITING, &new_vcc->flags) || !sigd)
-				break;
-			release_sock(sk);
-			schedule();
-			lock_sock(sk);
-		}
-		finish_wait(sk_sleep(sk_atm(new_vcc)), &wait);
-		if (!sigd) {
-			error = -EUNATCH;
-			goto out;
-		}
-		if (!sk_atm(new_vcc)->sk_err)
-			break;
-		if (sk_atm(new_vcc)->sk_err != ERESTARTSYS) {
-			error = -sk_atm(new_vcc)->sk_err;
-			goto out;
-		}
-	}
-	newsock->state = SS_CONNECTED;
-out:
-	release_sock(sk);
-	return error;
-}
-
-static int svc_getname(struct socket *sock, struct sockaddr *sockaddr,
-		       int peer)
-{
-	struct sockaddr_atmsvc *addr;
-
-	addr = (struct sockaddr_atmsvc *) sockaddr;
-	memcpy(addr, peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local,
-	       sizeof(struct sockaddr_atmsvc));
-	return sizeof(struct sockaddr_atmsvc);
-}
-
-int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos)
-{
-	struct sock *sk = sk_atm(vcc);
-	DEFINE_WAIT(wait);
-
-	set_bit(ATM_VF_WAITING, &vcc->flags);
-	sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0);
-	for (;;) {
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
-		if (!test_bit(ATM_VF_WAITING, &vcc->flags) ||
-		    test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd) {
-			break;
-		}
-		schedule();
-	}
-	finish_wait(sk_sleep(sk), &wait);
-	if (!sigd)
-		return -EUNATCH;
-	return -sk->sk_err;
-}
-
-static int svc_setsockopt(struct socket *sock, int level, int optname,
-			  sockptr_t optval, unsigned int optlen)
-{
-	struct sock *sk = sock->sk;
-	struct atm_vcc *vcc = ATM_SD(sock);
-	int value, error = 0;
-
-	lock_sock(sk);
-	switch (optname) {
-	case SO_ATMSAP:
-		if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) {
-			error = -EINVAL;
-			goto out;
-		}
-		if (copy_from_sockptr(&vcc->sap, optval, optlen)) {
-			error = -EFAULT;
-			goto out;
-		}
-		set_bit(ATM_VF_HASSAP, &vcc->flags);
-		break;
-	case SO_MULTIPOINT:
-		if (level != SOL_ATM || optlen != sizeof(int)) {
-			error = -EINVAL;
-			goto out;
-		}
-		if (copy_from_sockptr(&value, optval, sizeof(int))) {
-			error = -EFAULT;
-			goto out;
-		}
-		if (value == 1)
-			set_bit(ATM_VF_SESSION, &vcc->flags);
-		else if (value == 0)
-			clear_bit(ATM_VF_SESSION, &vcc->flags);
-		else
-			error = -EINVAL;
-		break;
-	default:
-		error = vcc_setsockopt(sock, level, optname, optval, optlen);
-	}
-
-out:
-	release_sock(sk);
-	return error;
-}
-
-static int svc_getsockopt(struct socket *sock, int level, int optname,
-			  sockopt_t *opt)
-{
-	struct sock *sk = sock->sk;
-	int error = 0, len;
-
-	lock_sock(sk);
-	if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP) {
-		error = vcc_getsockopt(sock, level, optname, opt);
-		goto out;
-	}
-	len = opt->optlen;
-	if (len != sizeof(struct atm_sap)) {
-		error = -EINVAL;
-		goto out;
-	}
-	if (copy_to_iter(&ATM_SD(sock)->sap, sizeof(struct atm_sap),
-			 &opt->iter_out) != sizeof(struct atm_sap)) {
-		error = -EFAULT;
-		goto out;
-	}
-out:
-	release_sock(sk);
-	return error;
-}
-
-static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,
-			int sockaddr_len, int flags)
-{
-	DEFINE_WAIT(wait);
-	struct sock *sk = sock->sk;
-	struct atm_vcc *vcc = ATM_SD(sock);
-	int error;
-
-	lock_sock(sk);
-	set_bit(ATM_VF_WAITING, &vcc->flags);
-	sigd_enq(vcc, as_addparty, NULL, NULL,
-		 (struct sockaddr_atmsvc *) sockaddr);
-	if (flags & O_NONBLOCK) {
-		error = -EINPROGRESS;
-		goto out;
-	}
-	pr_debug("added wait queue\n");
-	for (;;) {
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
-		if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
-			break;
-		schedule();
-	}
-	finish_wait(sk_sleep(sk), &wait);
-	error = -xchg(&sk->sk_err_soft, 0);
-out:
-	release_sock(sk);
-	return error;
-}
-
-static int svc_dropparty(struct socket *sock, int ep_ref)
-{
-	DEFINE_WAIT(wait);
-	struct sock *sk = sock->sk;
-	struct atm_vcc *vcc = ATM_SD(sock);
-	int error;
-
-	lock_sock(sk);
-	set_bit(ATM_VF_WAITING, &vcc->flags);
-	sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref);
-	for (;;) {
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
-		if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
-			break;
-		schedule();
-	}
-	finish_wait(sk_sleep(sk), &wait);
-	if (!sigd) {
-		error = -EUNATCH;
-		goto out;
-	}
-	error = -xchg(&sk->sk_err_soft, 0);
-out:
-	release_sock(sk);
-	return error;
-}
-
-static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-	int error, ep_ref;
-	struct sockaddr_atmsvc sa;
-	struct atm_vcc *vcc = ATM_SD(sock);
-
-	switch (cmd) {
-	case ATM_ADDPARTY:
-		if (!test_bit(ATM_VF_SESSION, &vcc->flags))
-			return -EINVAL;
-		if (copy_from_user(&sa, (void __user *) arg, sizeof(sa)))
-			return -EFAULT;
-		error = svc_addparty(sock, (struct sockaddr *)&sa, sizeof(sa),
-				     0);
-		break;
-	case ATM_DROPPARTY:
-		if (!test_bit(ATM_VF_SESSION, &vcc->flags))
-			return -EINVAL;
-		if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int)))
-			return -EFAULT;
-		error = svc_dropparty(sock, ep_ref);
-		break;
-	default:
-		error = vcc_ioctl(sock, cmd, arg);
-	}
-
-	return error;
-}
-
-#ifdef CONFIG_COMPAT
-static int svc_compat_ioctl(struct socket *sock, unsigned int cmd,
-			    unsigned long arg)
-{
-	/* The definition of ATM_ADDPARTY uses the size of struct atm_iobuf.
-	   But actually it takes a struct sockaddr_atmsvc, which doesn't need
-	   compat handling. So all we have to do is fix up cmd... */
-	if (cmd == COMPAT_ATM_ADDPARTY)
-		cmd = ATM_ADDPARTY;
-
-	if (cmd == ATM_ADDPARTY || cmd == ATM_DROPPARTY)
-		return svc_ioctl(sock, cmd, arg);
-	else
-		return vcc_compat_ioctl(sock, cmd, arg);
-}
-#endif /* CONFIG_COMPAT */
-
-static const struct proto_ops svc_proto_ops = {
-	.family =	PF_ATMSVC,
-	.owner =	THIS_MODULE,
-
-	.release =	svc_release,
-	.bind =		svc_bind,
-	.connect =	svc_connect,
-	.socketpair =	sock_no_socketpair,
-	.accept =	svc_accept,
-	.getname =	svc_getname,
-	.poll =		vcc_poll,
-	.ioctl =	svc_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl =	svc_compat_ioctl,
-#endif
-	.gettstamp =	sock_gettstamp,
-	.listen =	svc_listen,
-	.shutdown =	svc_shutdown,
-	.setsockopt =	svc_setsockopt,
-	.getsockopt_iter = svc_getsockopt,
-	.sendmsg =	vcc_sendmsg,
-	.recvmsg =	vcc_recvmsg,
-	.mmap =		sock_no_mmap,
-};
-
-
-static int svc_create(struct net *net, struct socket *sock, int protocol,
-		      int kern)
-{
-	int error;
-
-	if (!net_eq(net, &init_net))
-		return -EAFNOSUPPORT;
-
-	sock->ops = &svc_proto_ops;
-	error = vcc_create(net, sock, protocol, AF_ATMSVC, kern);
-	if (error)
-		return error;
-	ATM_SD(sock)->local.sas_family = AF_ATMSVC;
-	ATM_SD(sock)->remote.sas_family = AF_ATMSVC;
-	return 0;
-}
-
-static const struct net_proto_family svc_family_ops = {
-	.family = PF_ATMSVC,
-	.create = svc_create,
-	.owner = THIS_MODULE,
-};
-
-
-/*
- *	Initialize the ATM SVC protocol family
- */
-
-int __init atmsvc_init(void)
-{
-	return sock_register(&svc_family_ops);
-}
-
-void atmsvc_exit(void)
-{
-	sock_unregister(PF_ATMSVC);
-}
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next 4/9] atm: remove the local ATM (NSAP) address registry
From: Jakub Kicinski @ 2026-06-13 20:10 UTC (permalink / raw)
  To: davem
  Cc: netdev, edumazet, pabeni, andrew+netdev, horms, 3chas3, mitch,
	linux-atm-general, dwmw2, Jakub Kicinski
In-Reply-To: <20260613201032.77274-1-kuba@kernel.org>

net/atm/addr.c maintained the per-device lists of local NSAP addresses
(dev->local) and ILMI-learned LECS addresses (dev->lecs). These exist
solely to serve SVC signaling: the lists are populated through the
ATM_{ADD,DEL,RST}ADDR / ATM_{ADD,DEL,GET}LECSADDR ioctls used by the
atmsigd / ILMI daemons, and consumed when registering addresses with the
signaling daemon. The LECS list belonged to LAN Emulation, which has
been removed.

With no SVC users in a DSL-only configuration these lists are always
empty, so drop the registry entirely:

 - remove the ADDR/LECSADDR/RSTADDR ioctls
 - drop the now-always-empty "atmaddress" sysfs attribute
 - remove the dev->local / dev->lecs lists, structs and enums
 - delete net/atm/addr.c and net/atm/addr.h

The device ESI ("MAC" address) and its ATM_{G,S}ETESI ioctls and
"address" sysfs attribute are retained - the USB DSL modems populate
the ESI.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 net/atm/Makefile       |   2 +-
 include/linux/atmdev.h |   9 ---
 net/atm/addr.h         |  21 ------
 net/atm/addr.c         | 162 -----------------------------------------
 net/atm/atm_sysfs.c    |  25 -------
 net/atm/common.c       |   1 -
 net/atm/ioctl.c        |  12 ---
 net/atm/resources.c    |  48 ------------
 net/atm/svc.c          |   1 -
 9 files changed, 1 insertion(+), 280 deletions(-)
 delete mode 100644 net/atm/addr.h
 delete mode 100644 net/atm/addr.c

diff --git a/net/atm/Makefile b/net/atm/Makefile
index 484a1b1552cc..5ed48d50df35 100644
--- a/net/atm/Makefile
+++ b/net/atm/Makefile
@@ -3,7 +3,7 @@
 # Makefile for the ATM Protocol Families.
 #
 
-atm-y		:= addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o
+atm-y		:= pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o
 
 obj-$(CONFIG_ATM) += atm.o
 obj-$(CONFIG_ATM_BR2684) += br2684.o
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 71c5bf6950e3..7abbd23fada6 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -136,13 +136,6 @@ static inline struct sock *sk_atm(struct atm_vcc *vcc)
 	return (struct sock *)vcc;
 }
 
-struct atm_dev_addr {
-	struct sockaddr_atmsvc addr;	/* ATM address */
-	struct list_head entry;		/* next address */
-};
-
-enum atm_addr_type_t { ATM_ADDR_LOCAL, ATM_ADDR_LECS };
-
 struct atm_dev {
 	const struct atmdev_ops *ops;	/* device operations; NULL if unused */
 	const struct atmphy_ops *phy;	/* PHY operations, may be undefined */
@@ -152,8 +145,6 @@ struct atm_dev {
 	void		*dev_data;	/* per-device data */
 	void		*phy_data;	/* private PHY data */
 	unsigned long	flags;		/* device flags (ATM_DF_*) */
-	struct list_head local;		/* local ATM addresses */
-	struct list_head lecs;		/* LECS ATM addresses learned via ILMI */
 	unsigned char	esi[ESI_LEN];	/* ESI ("MAC" addr) */
 	struct atm_cirange ci_range;	/* VPI/VCI range */
 	struct k_atm_dev_stats stats;	/* statistics */
diff --git a/net/atm/addr.h b/net/atm/addr.h
deleted file mode 100644
index da3f848411a0..000000000000
--- a/net/atm/addr.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* net/atm/addr.h - Local ATM address registry */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#ifndef NET_ATM_ADDR_H
-#define NET_ATM_ADDR_H
-
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-
-void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t type);
-int atm_add_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
-		 enum atm_addr_type_t type);
-int atm_del_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
-		 enum atm_addr_type_t type);
-int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user *buf,
-		 size_t size, enum atm_addr_type_t type);
-
-#endif
diff --git a/net/atm/addr.c b/net/atm/addr.c
deleted file mode 100644
index 938f360ae230..000000000000
--- a/net/atm/addr.c
+++ /dev/null
@@ -1,162 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* net/atm/addr.c - Local ATM address registry */
-
-/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
-#include <linux/atm.h>
-#include <linux/atmdev.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include "signaling.h"
-#include "addr.h"
-
-static int check_addr(const struct sockaddr_atmsvc *addr)
-{
-	int i;
-
-	if (addr->sas_family != AF_ATMSVC)
-		return -EAFNOSUPPORT;
-	if (!*addr->sas_addr.pub)
-		return *addr->sas_addr.prv ? 0 : -EINVAL;
-	for (i = 1; i < ATM_E164_LEN + 1; i++)	/* make sure it's \0-terminated */
-		if (!addr->sas_addr.pub[i])
-			return 0;
-	return -EINVAL;
-}
-
-static int identical(const struct sockaddr_atmsvc *a, const struct sockaddr_atmsvc *b)
-{
-	if (*a->sas_addr.prv)
-		if (memcmp(a->sas_addr.prv, b->sas_addr.prv, ATM_ESA_LEN))
-			return 0;
-	if (!*a->sas_addr.pub)
-		return !*b->sas_addr.pub;
-	if (!*b->sas_addr.pub)
-		return 0;
-	return !strcmp(a->sas_addr.pub, b->sas_addr.pub);
-}
-
-static void notify_sigd(const struct atm_dev *dev)
-{
-	struct sockaddr_atmpvc pvc;
-
-	pvc.sap_addr.itf = dev->number;
-	sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL);
-}
-
-void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype)
-{
-	unsigned long flags;
-	struct atm_dev_addr *this, *p;
-	struct list_head *head;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	if (atype == ATM_ADDR_LECS)
-		head = &dev->lecs;
-	else
-		head = &dev->local;
-	list_for_each_entry_safe(this, p, head, entry) {
-		list_del(&this->entry);
-		kfree(this);
-	}
-	spin_unlock_irqrestore(&dev->lock, flags);
-	if (head == &dev->local)
-		notify_sigd(dev);
-}
-
-int atm_add_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
-		 enum atm_addr_type_t atype)
-{
-	unsigned long flags;
-	struct atm_dev_addr *this;
-	struct list_head *head;
-	int error;
-
-	error = check_addr(addr);
-	if (error)
-		return error;
-	spin_lock_irqsave(&dev->lock, flags);
-	if (atype == ATM_ADDR_LECS)
-		head = &dev->lecs;
-	else
-		head = &dev->local;
-	list_for_each_entry(this, head, entry) {
-		if (identical(&this->addr, addr)) {
-			spin_unlock_irqrestore(&dev->lock, flags);
-			return -EEXIST;
-		}
-	}
-	this = kmalloc_obj(struct atm_dev_addr, GFP_ATOMIC);
-	if (!this) {
-		spin_unlock_irqrestore(&dev->lock, flags);
-		return -ENOMEM;
-	}
-	this->addr = *addr;
-	list_add(&this->entry, head);
-	spin_unlock_irqrestore(&dev->lock, flags);
-	if (head == &dev->local)
-		notify_sigd(dev);
-	return 0;
-}
-
-int atm_del_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
-		 enum atm_addr_type_t atype)
-{
-	unsigned long flags;
-	struct atm_dev_addr *this;
-	struct list_head *head;
-	int error;
-
-	error = check_addr(addr);
-	if (error)
-		return error;
-	spin_lock_irqsave(&dev->lock, flags);
-	if (atype == ATM_ADDR_LECS)
-		head = &dev->lecs;
-	else
-		head = &dev->local;
-	list_for_each_entry(this, head, entry) {
-		if (identical(&this->addr, addr)) {
-			list_del(&this->entry);
-			spin_unlock_irqrestore(&dev->lock, flags);
-			kfree(this);
-			if (head == &dev->local)
-				notify_sigd(dev);
-			return 0;
-		}
-	}
-	spin_unlock_irqrestore(&dev->lock, flags);
-	return -ENOENT;
-}
-
-int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf,
-		 size_t size, enum atm_addr_type_t atype)
-{
-	unsigned long flags;
-	struct atm_dev_addr *this;
-	struct list_head *head;
-	int total = 0, error;
-	struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	if (atype == ATM_ADDR_LECS)
-		head = &dev->lecs;
-	else
-		head = &dev->local;
-	list_for_each_entry(this, head, entry)
-	    total += sizeof(struct sockaddr_atmsvc);
-	tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
-	if (!tmp_buf) {
-		spin_unlock_irqrestore(&dev->lock, flags);
-		return -ENOMEM;
-	}
-	list_for_each_entry(this, head, entry)
-	    memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc));
-	spin_unlock_irqrestore(&dev->lock, flags);
-	error = total > size ? -E2BIG : total;
-	if (copy_to_user(buf, tmp_buf, total < size ? total : size))
-		error = -EFAULT;
-	kfree(tmp_buf);
-	return error;
-}
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
index 54e7fb1a4ee5..0676a9c333ff 100644
--- a/net/atm/atm_sysfs.c
+++ b/net/atm/atm_sysfs.c
@@ -27,29 +27,6 @@ static ssize_t address_show(struct device *cdev,
 	return scnprintf(buf, PAGE_SIZE, "%pM\n", adev->esi);
 }
 
-static ssize_t atmaddress_show(struct device *cdev,
-			       struct device_attribute *attr, char *buf)
-{
-	unsigned long flags;
-	struct atm_dev *adev = to_atm_dev(cdev);
-	struct atm_dev_addr *aaddr;
-	int count = 0;
-
-	spin_lock_irqsave(&adev->lock, flags);
-	list_for_each_entry(aaddr, &adev->local, entry) {
-		count += scnprintf(buf + count, PAGE_SIZE - count,
-				   "%1phN.%2phN.%10phN.%6phN.%1phN\n",
-				   &aaddr->addr.sas_addr.prv[0],
-				   &aaddr->addr.sas_addr.prv[1],
-				   &aaddr->addr.sas_addr.prv[3],
-				   &aaddr->addr.sas_addr.prv[13],
-				   &aaddr->addr.sas_addr.prv[19]);
-	}
-	spin_unlock_irqrestore(&adev->lock, flags);
-
-	return count;
-}
-
 static ssize_t atmindex_show(struct device *cdev,
 			     struct device_attribute *attr, char *buf)
 {
@@ -91,14 +68,12 @@ static ssize_t link_rate_show(struct device *cdev,
 }
 
 static DEVICE_ATTR_RO(address);
-static DEVICE_ATTR_RO(atmaddress);
 static DEVICE_ATTR_RO(atmindex);
 static DEVICE_ATTR_RO(carrier);
 static DEVICE_ATTR_RO(type);
 static DEVICE_ATTR_RO(link_rate);
 
 static struct device_attribute *atm_attrs[] = {
-	&dev_attr_atmaddress,
 	&dev_attr_address,
 	&dev_attr_atmindex,
 	&dev_attr_carrier,
diff --git a/net/atm/common.c b/net/atm/common.c
index c6e87fc9bbfc..7d5b7c39b80b 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -30,7 +30,6 @@
 #include "resources.h"		/* atm_find_dev */
 #include "common.h"		/* prototypes */
 #include "protocols.h"		/* atm_init_<transport> */
-#include "addr.h"		/* address registry */
 #include "signaling.h"		/* for WAITING and sigd_attach */
 
 struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index 4f2d185bf2f0..97f20cd051ed 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -220,10 +220,6 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 #define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct compat_atm_iobuf)
 #define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct compat_atmif_sioc)
 #define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct compat_atmif_sioc)
-#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct compat_atmif_sioc)
-#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct compat_atmif_sioc)
-#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct compat_atmif_sioc)
-#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct compat_atmif_sioc)
 #define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct compat_atmif_sioc)
 #define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct compat_atmif_sioc)
 #define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct compat_atmif_sioc)
@@ -242,10 +238,6 @@ static struct {
 	{ ATM_GETNAMES32,    ATM_GETNAMES },
 	{ ATM_GETTYPE32,     ATM_GETTYPE },
 	{ ATM_GETESI32,	     ATM_GETESI },
-	{ ATM_GETADDR32,     ATM_GETADDR },
-	{ ATM_RSTADDR32,     ATM_RSTADDR },
-	{ ATM_ADDADDR32,     ATM_ADDADDR },
-	{ ATM_DELADDR32,     ATM_DELADDR },
 	{ ATM_GETCIRANGE32,  ATM_GETCIRANGE },
 	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
 	{ ATM_SETESI32,	     ATM_SETESI },
@@ -305,10 +297,6 @@ static int do_atm_ioctl(struct socket *sock, unsigned int cmd32,
 	case ATM_GETLINKRATE:
 	case ATM_GETTYPE:
 	case ATM_GETESI:
-	case ATM_GETADDR:
-	case ATM_RSTADDR:
-	case ATM_ADDADDR:
-	case ATM_DELADDR:
 	case ATM_GETCIRANGE:
 	case ATM_SETCIRANGE:
 	case ATM_SETESI:
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 7aac25e917b4..a08f65aacf75 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -25,7 +25,6 @@
 
 #include "common.h"
 #include "resources.h"
-#include "addr.h"
 
 
 LIST_HEAD(atm_devs);
@@ -42,8 +41,6 @@ static struct atm_dev *__alloc_atm_dev(const char *type)
 	dev->signal = ATM_PHY_SIG_UNKNOWN;
 	dev->link_rate = ATM_OC3_PCR;
 	spin_lock_init(&dev->lock);
-	INIT_LIST_HEAD(&dev->local);
-	INIT_LIST_HEAD(&dev->lecs);
 
 	return dev;
 }
@@ -306,51 +303,6 @@ int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len,
 			goto done;
 		}
 		break;
-	case ATM_RSTADDR:
-		if (!capable(CAP_NET_ADMIN)) {
-			error = -EPERM;
-			goto done;
-		}
-		atm_reset_addr(dev, ATM_ADDR_LOCAL);
-		break;
-	case ATM_ADDADDR:
-	case ATM_DELADDR:
-	case ATM_ADDLECSADDR:
-	case ATM_DELLECSADDR:
-	{
-		struct sockaddr_atmsvc addr;
-
-		if (!capable(CAP_NET_ADMIN)) {
-			error = -EPERM;
-			goto done;
-		}
-
-		if (copy_from_user(&addr, buf, sizeof(addr))) {
-			error = -EFAULT;
-			goto done;
-		}
-		if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR)
-			error = atm_add_addr(dev, &addr,
-					     (cmd == ATM_ADDADDR ?
-					      ATM_ADDR_LOCAL : ATM_ADDR_LECS));
-		else
-			error = atm_del_addr(dev, &addr,
-					     (cmd == ATM_DELADDR ?
-					      ATM_ADDR_LOCAL : ATM_ADDR_LECS));
-		goto done;
-	}
-	case ATM_GETADDR:
-	case ATM_GETLECSADDR:
-		error = atm_get_addr(dev, buf, len,
-				     (cmd == ATM_GETADDR ?
-				      ATM_ADDR_LOCAL : ATM_ADDR_LECS));
-		if (error < 0)
-			goto done;
-		size = error;
-		/* may return 0, but later on size == 0 means "don't
-		   write the length" */
-		error = put_user(size, sioc_len) ? -EFAULT : 0;
-		goto done;
 	case ATM_SETLOOP:
 		if (__ATM_LM_XTRMT((int) (unsigned long) buf) &&
 		    __ATM_LM_XTLOC((int) (unsigned long) buf) >
diff --git a/net/atm/svc.c b/net/atm/svc.c
index 7c5559f50a99..270e95154a2b 100644
--- a/net/atm/svc.c
+++ b/net/atm/svc.c
@@ -27,7 +27,6 @@
 #include "resources.h"
 #include "common.h"		/* common for PVCs and SVCs */
 #include "signaling.h"
-#include "addr.h"
 
 #ifdef CONFIG_COMPAT
 /* It actually takes struct sockaddr_atmsvc, not struct atm_iobuf */
-- 
2.54.0


^ permalink raw reply related


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