* [PATCH net-next v2] vsock: avoid timeout for non-blocking accept() with empty backlog
From: Laurence Rowe @ 2026-04-02 20:49 UTC (permalink / raw)
To: Stefano Garzarella
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, virtualization, netdev, Laurence Rowe,
Bobby Eshleman
A common pattern in epoll network servers is to eagerly accept all
pending connections from the non-blocking listening socket after
epoll_wait indicates the socket is ready by calling accept in a loop
until EAGAIN is returned indicating that the backlog is empty.
Scheduling a timeout for a non-blocking accept with an empty backlog
meant AF_VSOCK sockets used by epoll network servers incurred hundreds
of microseconds of additional latency per accept loop compared to
AF_INET or AF_UNIX sockets.
Signed-off-by: Laurence Rowe <laurencerowe@gmail.com>
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
Patch v2 with feedback from Stefano Garzarella and Bobby Eshleman:
- Move prepare_to_wait before release_sock to match previous behaviour.
- Simplify not connected case.
This fixes the observed issue for me:
1. With loopback vsock on the host running Linux v6.19.10 built with
config-6.17.0-19-generic from Ubuntu 24.04 and make olddefconfig.
2. With Firecracker guests with current torvalds/master, v6.19.10, and
amazonlinux/microvm-kernel-6.1.166-24.303.amzn2023 used in Firecracker
CI and examples. (Firecracker guest vsocks are unix sockets on the host
side so this fix works there with just a fixed guest kernel.)
I struggled to build a generic 6.1.166 kernel that worked as a
Firecracker guest but the patch applies (conflict due to change of
`flags` to `arg->flags` in surrounding context) so I believe it should
work for generic v6.1.166 kernel.
Alternatively a minimal version of this fix is to just wrap the
`schedule_timeout` in an `if (timeout != 0)` but that leaves an
unnecessary additional `lock_sock` call.
There are ftrace's and reproduction tools at:
https://github.com/lrowe/linux-vsock-accept-timeout-investigation
---
net/vmw_vsock/af_vsock.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index e4756604d5..b8794ea0f0 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1864,10 +1864,10 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
* created upon connection establishment.
*/
timeout = sock_rcvtimeo(listener, arg->flags & O_NONBLOCK);
- prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
while ((connected = vsock_dequeue_accept(listener)) == NULL &&
- listener->sk_err == 0) {
+ listener->sk_err == 0 && timeout != 0) {
+ prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
release_sock(listener);
timeout = schedule_timeout(timeout);
finish_wait(sk_sleep(listener), &wait);
@@ -1876,17 +1876,14 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
if (signal_pending(current)) {
err = sock_intr_errno(timeout);
goto out;
- } else if (timeout == 0) {
- err = -EAGAIN;
- goto out;
}
-
- prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
}
- finish_wait(sk_sleep(listener), &wait);
- if (listener->sk_err)
+ if (listener->sk_err) {
err = -listener->sk_err;
+ } else if (!connected) {
+ err = -EAGAIN;
+ }
if (connected) {
sk_acceptq_removed(listener);
base-commit: f35340f2d653f1003602878403c901396ab03c17
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 0/6] Deprecate Legacy IP
From: Mauro Carvalho Chehab @ 2026-04-02 20:27 UTC (permalink / raw)
To: David Woodhouse
Cc: Fernando Fernandez Mancera, Saeed Mahameed, Leon Romanovsky,
Tariq Toukan, Mark Bloch, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Nikolay Aleksandrov, Ido Schimmel, Martin KaFai Lau,
Daniel Borkmann, John Fastabend, Stanislav Fomichev,
Alexei Starovoitov, Andrii Nakryiko, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Kuniyuki Iwashima,
Willem de Bruijn, David Ahern, Neal Cardwell, Johannes Berg,
Pablo Neira Ayuso, Florian Westphal, Phil Sutter, Guillaume Nault,
Kees Cook, Alexei Lazar, Gal Pressman, Paul Moore, netdev,
linux-rdma, linux-kernel, oss-drivers, bridge, bpf,
linux-wireless, netfilter-devel, coreteam, torvalds,
jon.maddog.hall
In-Reply-To: <2cb91533e22ed6cb11205dbc56b8aeedbbce0cca.camel@infradead.org>
On Wed, 01 Apr 2026 09:25:08 +0100
David Woodhouse <dwmw2@infradead.org> wrote:
> On Wed, 2026-04-01 at 10:07 +0200, Fernando Fernandez Mancera wrote:
> >
> >
> > Dammit, you've beaten me to it! This was my next step for 7.2.
> >
> > Fully-endorsed-by: Fernando Fernandez Mancera <fmancera@suse.de>
>
> Yeah. The date notwithstanding,
You tricked me on this April fools day...
Very funny!
> I do actually think we should do most
> of this for real.
>
> Maybe we don't get away with the actual deprecation and the warnings on
> use *just* yet, and *maybe* we won't even get away with calling the
> config option CONFIG_LEGACY_IP, although I would genuinely like to see
> us moving consistently towards saying "Legacy IP" instead of "IPv4"
> everywhere.
IPv4 is not legacy yet... Lots of configurations, service providers
and corporations that requires the usage of VPN are IPv4 only still
today. For instance, my paid VPN provider only grants IPv4 addresses
(at least for those not using their proprietary software).
>
> But we *should* clean up the separation of CONFIG_INET and
> CONFIG_IPV[64] and make it possible to build with either protocol
> alone.
That makes sense on my eyes.
Thanks,
Mauro
^ permalink raw reply
* [PATCH net v3 7/7] net/sched: netem: fix slot delay calculation overflow
From: Stephen Hemminger @ 2026-04-02 20:19 UTC (permalink / raw)
To: netdev
Cc: Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Neal Cardwell, Yousuk Seung, open list
In-Reply-To: <20260402202037.176299-1-stephen@networkplumber.org>
get_slot_next() computes a random delay between min_delay and
max_delay using:
get_random_u32() * (max_delay - min_delay) >> 32
This overflows signed 64-bit arithmetic when the delay range exceeds
approximately 2.1 seconds (2^31 nanoseconds), producing a negative
result that effectively disables slot-based pacing. This is a
realistic configuration for WAN emulation (e.g., slot 1s 5s).
Use mul_u64_u32_shr() which handles the widening multiply without
overflow.
Fixes: 0a9fe5c375b5 ("netem: slotting with non-uniform distribution")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index c82f76af41aa..d47e1b0d7942 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -660,9 +660,8 @@ static void get_slot_next(struct netem_sched_data *q, u64 now)
if (!q->slot_dist)
next_delay = q->slot_config.min_delay +
- (get_random_u32() *
- (q->slot_config.max_delay -
- q->slot_config.min_delay) >> 32);
+ mul_u64_u32_shr(q->slot_config.max_delay - q->slot_config.min_delay,
+ get_random_u32(), 32);
else
next_delay = tabledist(q->slot_config.dist_delay,
(s32)(q->slot_config.dist_jitter),
--
2.53.0
^ permalink raw reply related
* [PATCH net v3 6/7] net/sched: netem: check for invalid slot range
From: Stephen Hemminger @ 2026-04-02 20:19 UTC (permalink / raw)
To: netdev
Cc: Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Yousuk Seung, Neal Cardwell, open list
In-Reply-To: <20260402202037.176299-1-stephen@networkplumber.org>
Reject slot configuration where min_delay exceeds max_delay.
The delay range computation in get_slot_next() underflows in
this case, producing bogus results.
Fixes: 0a9fe5c375b5 ("netem: slotting with non-uniform distribution")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index e405bf862163..c82f76af41aa 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -883,6 +883,18 @@ static int get_dist_table(struct disttable **tbl, const struct nlattr *attr)
return 0;
}
+static int validate_slot(const struct nlattr *attr,
+ struct netlink_ext_ack *extack)
+{
+ const struct tc_netem_slot *c = nla_data(attr);
+
+ if (c->min_delay > c->max_delay) {
+ NL_SET_ERR_MSG(extack, "slot min delay greater than max delay");
+ return -EINVAL;
+ }
+ return 0;
+}
+
static void get_slot(struct netem_sched_data *q, const struct nlattr *attr)
{
const struct tc_netem_slot *c = nla_data(attr);
@@ -1096,6 +1108,12 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
goto table_free;
}
+ if (tb[TCA_NETEM_SLOT]) {
+ ret = validate_slot(tb[TCA_NETEM_SLOT], extack);
+ if (ret)
+ goto table_free;
+ }
+
sch_tree_lock(sch);
/* backup q->clg and q->loss_model */
old_clg = q->clg;
--
2.53.0
^ permalink raw reply related
* [PATCH net v3 5/7] net/sched: netem: null-terminate tfifo linear queue tail
From: Stephen Hemminger @ 2026-04-02 20:19 UTC (permalink / raw)
To: netdev
Cc: Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Peter Oskolkov, open list
In-Reply-To: <20260402202037.176299-1-stephen@networkplumber.org>
When tfifo_enqueue() appends a packet to the linear queue tail,
nskb->next is never set to NULL. The list terminates correctly
only by accident if the skb arrived with next already NULL.
Explicitly null-terminate the tail to prevent list corruption.
Fixes: d66280b12bd7 ("net: netem: use a list in addition to rbtree")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index b93f0e886a2b..e405bf862163 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -398,6 +398,7 @@ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
q->t_tail->next = nskb;
else
q->t_head = nskb;
+ nskb->next = NULL;
q->t_tail = nskb;
} else {
struct rb_node **p = &q->t_root.rb_node, *parent = NULL;
--
2.53.0
^ permalink raw reply related
* [PATCH net v3 4/7] net/sched: netem: restructure dequeue to avoid re-entrancy with child qdisc
From: Stephen Hemminger @ 2026-04-02 20:19 UTC (permalink / raw)
To: netdev
Cc: Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
open list
In-Reply-To: <20260402202037.176299-1-stephen@networkplumber.org>
netem_dequeue() enqueues packets into its child qdisc while being
called from the parent's dequeue path. This causes two problems:
- HFSC tracks class active/inactive state on qlen transitions.
A child enqueue during dequeue causes double-insertion into
the eltree (CVE-2025-37890, CVE-2025-38001).
- Non-work-conserving children like TBF may refuse to dequeue
packets just enqueued, causing netem to return NULL despite
having backlog. Parents like DRR then incorrectly deactivate
the class.
Split the dequeue into helpers:
netem_pull_tfifo() - remove head packet from tfifo
netem_slot_account() - update slot pacing counters
netem_dequeue_child() - batch-transfer ready packets to the
child, then dequeue from the child
netem_dequeue_direct()- dequeue from tfifo when no child
When a child qdisc is present, all time-ready packets are moved
into the child before calling its dequeue. This separates the
enqueue and dequeue phases so the parent sees consistent qlen
transitions.
Fixes: 50612537e9ab ("netem: fix classful handling")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 201 +++++++++++++++++++++++++++---------------
1 file changed, 128 insertions(+), 73 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 556f9747f0e7..b93f0e886a2b 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -689,99 +689,154 @@ static struct sk_buff *netem_peek(struct netem_sched_data *q)
return q->t_head;
}
-static void netem_erase_head(struct netem_sched_data *q, struct sk_buff *skb)
+/*
+ * Pop the head packet from the tfifo and prepare it for delivery.
+ * skb->dev shares the rbnode area and must be restored after removal.
+ */
+static struct sk_buff *netem_pull_tfifo(struct netem_sched_data *q,
+ struct Qdisc *sch)
{
- if (skb == q->t_head) {
+ struct sk_buff *skb;
+
+ if (q->t_head) {
+ skb = q->t_head;
q->t_head = skb->next;
if (!q->t_head)
q->t_tail = NULL;
} else {
- rb_erase(&skb->rbnode, &q->t_root);
+ struct rb_node *p = rb_first(&q->t_root);
+
+ if (!p)
+ return NULL;
+ skb = rb_to_skb(p);
+ rb_erase(p, &q->t_root);
}
+
+ q->t_len--;
+ skb->next = NULL;
+ skb->prev = NULL;
+ skb->dev = qdisc_dev(sch);
+
+ return skb;
}
-static struct sk_buff *netem_dequeue(struct Qdisc *sch)
+/* Update slot pacing counters after releasing a packet */
+static void netem_slot_account(struct netem_sched_data *q,
+ const struct sk_buff *skb, u64 now)
+{
+ if (!q->slot.slot_next)
+ return;
+
+ q->slot.packets_left--;
+ q->slot.bytes_left -= qdisc_pkt_len(skb);
+ if (q->slot.packets_left <= 0 || q->slot.bytes_left <= 0)
+ get_slot_next(q, now);
+}
+
+/*
+ * Transfer all time-ready packets from the tfifo into the child qdisc,
+ * then dequeue from the child. Batching the transfers avoids calling
+ * qdisc_enqueue() inside the parent's dequeue path, which confuses
+ * parents that track active/inactive state on qlen transitions (HFSC).
+ */
+static struct sk_buff *netem_dequeue_child(struct Qdisc *sch)
{
struct netem_sched_data *q = qdisc_priv(sch);
+ u64 now = ktime_get_ns();
struct sk_buff *skb;
-tfifo_dequeue:
- skb = __qdisc_dequeue_head(&sch->q);
- if (skb) {
-deliver:
- qdisc_qstats_backlog_dec(sch, skb);
- qdisc_bstats_update(sch, skb);
- return skb;
- }
- skb = netem_peek(q);
- if (skb) {
- u64 time_to_send;
- u64 now = ktime_get_ns();
-
- /* if more time remaining? */
- time_to_send = netem_skb_cb(skb)->time_to_send;
- if (q->slot.slot_next && q->slot.slot_next < time_to_send)
- get_slot_next(q, now);
-
- if (time_to_send <= now && q->slot.slot_next <= now) {
- netem_erase_head(q, skb);
- q->t_len--;
- skb->next = NULL;
- skb->prev = NULL;
- /* skb->dev shares skb->rbnode area,
- * we need to restore its value.
- */
- skb->dev = qdisc_dev(sch);
-
- if (q->slot.slot_next) {
- q->slot.packets_left--;
- q->slot.bytes_left -= qdisc_pkt_len(skb);
- if (q->slot.packets_left <= 0 ||
- q->slot.bytes_left <= 0)
- get_slot_next(q, now);
- }
+ while ((skb = netem_peek(q)) != NULL) {
+ struct sk_buff *to_free = NULL;
+ unsigned int pkt_len;
+ int err;
- if (q->qdisc) {
- unsigned int pkt_len = qdisc_pkt_len(skb);
- struct sk_buff *to_free = NULL;
- int err;
-
- err = qdisc_enqueue(skb, q->qdisc, &to_free);
- kfree_skb_list(to_free);
- if (err != NET_XMIT_SUCCESS) {
- if (net_xmit_drop_count(err))
- qdisc_qstats_drop(sch);
- sch->qstats.backlog -= pkt_len;
- sch->q.qlen--;
- qdisc_tree_reduce_backlog(sch, 1, pkt_len);
- }
- goto tfifo_dequeue;
- }
+ if (netem_skb_cb(skb)->time_to_send > now)
+ break;
+ if (q->slot.slot_next && q->slot.slot_next > now)
+ break;
+
+ skb = netem_pull_tfifo(q, sch);
+ netem_slot_account(q, skb, now);
+
+ pkt_len = qdisc_pkt_len(skb);
+ err = qdisc_enqueue(skb, q->qdisc, &to_free);
+ kfree_skb_list(to_free);
+ if (unlikely(err != NET_XMIT_SUCCESS)) {
+ if (net_xmit_drop_count(err))
+ qdisc_qstats_drop(sch);
+ sch->qstats.backlog -= pkt_len;
sch->q.qlen--;
- goto deliver;
+ qdisc_tree_reduce_backlog(sch, 1, pkt_len);
}
+ }
- if (q->qdisc) {
- skb = q->qdisc->ops->dequeue(q->qdisc);
- if (skb) {
- sch->q.qlen--;
- goto deliver;
- }
- }
+ skb = q->qdisc->ops->dequeue(q->qdisc);
+ if (skb)
+ sch->q.qlen--;
- qdisc_watchdog_schedule_ns(&q->watchdog,
- max(time_to_send,
- q->slot.slot_next));
- }
+ return skb;
+}
- if (q->qdisc) {
- skb = q->qdisc->ops->dequeue(q->qdisc);
- if (skb) {
- sch->q.qlen--;
- goto deliver;
- }
+/* Dequeue directly from the tfifo when no child qdisc is configured. */
+static struct sk_buff *netem_dequeue_direct(struct Qdisc *sch)
+{
+ struct netem_sched_data *q = qdisc_priv(sch);
+ struct sk_buff *skb;
+ u64 time_to_send;
+ u64 now;
+
+ skb = netem_peek(q);
+ if (!skb)
+ return NULL;
+
+ now = ktime_get_ns();
+ time_to_send = netem_skb_cb(skb)->time_to_send;
+
+ if (q->slot.slot_next && q->slot.slot_next < time_to_send)
+ get_slot_next(q, now);
+
+ if (time_to_send > now || q->slot.slot_next > now)
+ return NULL;
+
+ skb = netem_pull_tfifo(q, sch);
+ netem_slot_account(q, skb, now);
+ sch->q.qlen--;
+
+ return skb;
+}
+
+static struct sk_buff *netem_dequeue(struct Qdisc *sch)
+{
+ struct netem_sched_data *q = qdisc_priv(sch);
+ struct sk_buff *skb;
+
+ /* First check the reorder queue */
+ skb = __qdisc_dequeue_head(&sch->q);
+ if (skb)
+ goto deliver;
+
+ if (q->qdisc)
+ skb = netem_dequeue_child(sch);
+ else
+ skb = netem_dequeue_direct(sch);
+
+ if (skb)
+ goto deliver;
+
+ /* Nothing ready — schedule watchdog for next packet */
+ skb = netem_peek(q);
+ if (skb) {
+ u64 time_to_send = netem_skb_cb(skb)->time_to_send;
+
+ qdisc_watchdog_schedule_ns(&q->watchdog,
+ max(time_to_send, q->slot.slot_next));
}
return NULL;
+
+deliver:
+ qdisc_qstats_backlog_dec(sch, skb);
+ qdisc_bstats_update(sch, skb);
+ return skb;
}
static void netem_reset(struct Qdisc *sch)
--
2.53.0
^ permalink raw reply related
* [PATCH net v3 3/7] net/sched: netem: only reseed PRNG when seed is explicitly provided
From: Stephen Hemminger @ 2026-04-02 20:19 UTC (permalink / raw)
To: netdev
Cc: Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
François Michel, open list
In-Reply-To: <20260402202037.176299-1-stephen@networkplumber.org>
netem_change() unconditionally reseeds the PRNG on every tc change
command. If TCA_NETEM_PRNG_SEED is not specified, a new random seed
is generated, destroying reproducibility for users who set a
deterministic seed on a previous change.
Move the initial random seed generation to netem_init() and only
reseed in netem_change() when TCA_NETEM_PRNG_SEED is explicitly
provided by the user.
Fixes: 4072d97ddc44 ("netem: add prng attribute to netem_sched_data")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index d400a730eadd..556f9747f0e7 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -1112,11 +1112,10 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
/* capping jitter to the range acceptable by tabledist() */
q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
- if (tb[TCA_NETEM_PRNG_SEED])
+ if (tb[TCA_NETEM_PRNG_SEED]) {
q->prng.seed = nla_get_u64(tb[TCA_NETEM_PRNG_SEED]);
- else
- q->prng.seed = get_random_u64();
- prandom_seed_state(&q->prng.prng_state, q->prng.seed);
+ prandom_seed_state(&q->prng.prng_state, q->prng.seed);
+ }
unlock:
sch_tree_unlock(sch);
@@ -1139,6 +1138,9 @@ static int netem_init(struct Qdisc *sch, struct nlattr *opt,
return -EINVAL;
q->loss_model = CLG_RANDOM;
+ q->prng.seed = get_random_u64();
+ prandom_seed_state(&q->prng.prng_state, q->prng.seed);
+
ret = netem_change(sch, opt, extack);
if (ret)
pr_info("netem: change failed\n");
--
2.53.0
^ permalink raw reply related
* [PATCH net v3 2/7] net/sched: netem: fix queue limit check to include reordered packets
From: Stephen Hemminger @ 2026-04-02 20:19 UTC (permalink / raw)
To: netdev
Cc: Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
open list
In-Reply-To: <20260402202037.176299-1-stephen@networkplumber.org>
The queue limit check in netem_enqueue() uses q->t_len which only
counts packets in the internal tfifo. Packets placed in sch->q by
the reorder path (__qdisc_enqueue_head) are not counted, allowing
the total queue occupancy to exceed sch->limit under reordering.
Include sch->q.qlen in the limit check.
Fixes: 50612537e9ab ("netem: fix classful handling")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 8ee72cac1faf..d400a730eadd 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -524,7 +524,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
1 << get_random_u32_below(8);
}
- if (unlikely(q->t_len >= sch->limit)) {
+ if (unlikely(sch->q.qlen >= sch->limit)) {
/* re-link segs, so that qdisc_drop_all() frees them all */
skb->next = segs;
qdisc_drop_all(skb, sch, to_free);
--
2.53.0
^ permalink raw reply related
* [PATCH net v3 1/7] net/sched: netem: fix probability gaps in 4-state loss model
From: Stephen Hemminger @ 2026-04-02 20:19 UTC (permalink / raw)
To: netdev
Cc: Stephen Hemminger, Jamal Hadi Salim, Jiri Pirko, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
open list
In-Reply-To: <20260402202037.176299-1-stephen@networkplumber.org>
The 4-state Markov chain in loss_4state() has gaps at the boundaries
between transition probability ranges. The comparisons use:
if (rnd < a4)
else if (a4 < rnd && rnd < a1 + a4)
When rnd equals a boundary value exactly, neither branch matches and
no state transition occurs. The redundant lower-bound check (a4 < rnd)
is already implied by being in the else branch.
Remove the unnecessary lower-bound comparisons so the ranges are
contiguous and every random value produces a transition, matching
the GI (General and Intuitive) loss model specification.
This bug goes back to original implementation of this model.
Fixes: 661b79725fea ("netem: revised correlated loss generator")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
net/sched/sch_netem.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 20df1c08b1e9..8ee72cac1faf 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -227,10 +227,10 @@ static bool loss_4state(struct netem_sched_data *q)
if (rnd < clg->a4) {
clg->state = LOST_IN_GAP_PERIOD;
return true;
- } else if (clg->a4 < rnd && rnd < clg->a1 + clg->a4) {
+ } else if (rnd < clg->a1 + clg->a4) {
clg->state = LOST_IN_BURST_PERIOD;
return true;
- } else if (clg->a1 + clg->a4 < rnd) {
+ } else {
clg->state = TX_IN_GAP_PERIOD;
}
@@ -247,9 +247,9 @@ static bool loss_4state(struct netem_sched_data *q)
case LOST_IN_BURST_PERIOD:
if (rnd < clg->a3)
clg->state = TX_IN_BURST_PERIOD;
- else if (clg->a3 < rnd && rnd < clg->a2 + clg->a3) {
+ else if (rnd < clg->a2 + clg->a3) {
clg->state = TX_IN_GAP_PERIOD;
- } else if (clg->a2 + clg->a3 < rnd) {
+ } else {
clg->state = LOST_IN_BURST_PERIOD;
return true;
}
--
2.53.0
^ permalink raw reply related
* [PATCH net v3 0/7] net/sched: netem: bug fixes
From: Stephen Hemminger @ 2026-04-02 20:19 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger
These bugs were identified while using AI-assisted code review of
sch_netem.c to analyze the packet duplication re-entrancy problem
(CVE-2025-37890, CVE-2025-38001), which are addressed in a separate
series.
The review uncovered several additional issues:
- probability gaps in the 4-state Markov loss model where
boundary values produce no state transition
- queue limit check not accounting for reordered packets
- PRNG reseeded on every tc change, breaking reproducibility
- the core dequeue re-entrancy issue with child qdiscs
causing HFSC eltree corruption and DRR class stalls
- missing NULL termination on the tfifo linear list tail
- slot delay configuration not validated for inverted ranges
- slot delay arithmetic overflow for ranges above ~2.1 seconds
v3 - fix blank line after Fixes:
v2 - pickup the slot related bug fixes
Stephen Hemminger (7):
net/sched: netem: fix probability gaps in 4-state loss model
net/sched: netem: fix queue limit check to include reordered packets
net/sched: netem: only reseed PRNG when seed is explicitly provided
net/sched: netem: restructure dequeue to avoid re-entrancy with child
qdisc
net/sched: netem: null-terminate tfifo linear queue tail
net/sched: netem: check for invalid slot range
net/sched: netem: fix slot delay calculation overflow
net/sched/sch_netem.c | 245 +++++++++++++++++++++++++++---------------
1 file changed, 160 insertions(+), 85 deletions(-)
--
2.53.0
^ permalink raw reply
* Re: [PATCH net v3 0/7] net/sched: Fix packet loops in mirred and netem
From: Stephen Hemminger @ 2026-04-02 20:16 UTC (permalink / raw)
To: netdev
In-Reply-To: <20260326181701.308275-1-stephen@networkplumber.org>
On Thu, 26 Mar 2026 11:00:59 -0700
Stephen Hemminger <stephen@networkplumber.org> wrote:
> This a minor revision of Jamal's series that
> fixes packet loops caused by mirred ingress redirects
> and netem duplication in stacked qdisc trees.
>
> The core idea is a 2-bit per-skb tc_depth counter that travels with
> the packet. The existing per-CPU mirred nest tracking loses state
> when a packet is deferred through the backlog or moves between CPUs
> via XPS/RPS. A per-skb field covers both cases.
>
> Patch 1 adds the tc_depth field in a padding hole in sk_buff.
> Patches 2-3 revert the check_netem_in_tree() fix and its tests,
> which broke legitimate multi-netem configurations.
> Patch 4 uses tc_depth to stop netem duplicate recursion.
> Patch 5 uses tc_depth to catch mirred ingress redirect loops.
> Patches 6-7 add mirred and netem test cases.
>
> Thanks to Jamal and Victor for fixing this.
>
> There are additional netem bug fixes in the pipeline but those
> are held back until this series lands.
Why is this marked Changes Requested.
The only yellow in patchwork is AI review warning that the patch
didn't address my comments. Which is a clear case of AI confusion.
I updated comments and commit methods to my satisfaction.
Sorry if that didn't satisfy it.
^ permalink raw reply
* Re: [PATCH] sungem: fix PHY initialization hardware failure check and pointe style
From: Andrew Lunn @ 2026-04-02 20:04 UTC (permalink / raw)
To: Joel; +Cc: andrew+netdev, davem, edumazet, kuba, pabeni, netdev,
linux-kernel
In-Reply-To: <20260402194235.11986-1-joelcrouch@gmail.com>
On Thu, Apr 02, 2026 at 07:42:35PM +0000, Joel wrote:
> Currently, bcm5411_init does not validate the result of the PHY register
> reads. This can lead to silent failures if the hardware is unresponsive
> or the MDIO bus times out, as 0xffff would be treated as valid data.
>
> This patch:
> 1: Adds a check for -EIO and 0xffff during BCM5411 initialization.
> 2: Updates gem_init_phy to log an error message fi the PHY-
> specific init fails.
> 3: Cleans up pointer formatting(eg,. foo* bar to foo *bar) to
> align with Linux Kernel Coding Style in the modified files.
A patch which does three things should probably be three patches. We
want lots of small patches, with good commit messages, which are
obviously correct.
Code style changes should definitely be in a different patch to real
changes.
https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html
Andrew
---
pw-bot: cr
^ permalink raw reply
* Re: [PATCH net 1/3] net/mlx5e: SD, Fix race condition in secondary device probe/remove
From: Shay Drori @ 2026-04-02 20:03 UTC (permalink / raw)
To: Jakub Kicinski, Tariq Toukan
Cc: Eric Dumazet, Paolo Abeni, Andrew Lunn, David S. Miller,
Saeed Mahameed, Mark Bloch, Leon Romanovsky, Simon Horman,
Kees Cook, Parav Pandit, Patrisious Haddad, Gal Pressman, netdev,
linux-rdma, linux-kernel
In-Reply-To: <20260401200842.79322a24@kernel.org>
On 02/04/2026 6:08, Jakub Kicinski wrote:
> External email: Use caution opening links or attachments
>
>
> On Mon, 30 Mar 2026 22:34:10 +0300 Tariq Toukan wrote:
>> From: Shay Drory <shayd@nvidia.com>
>>
>> When utilizing Socket-Direct single netdev functionality the driver
>> resolves the actual auxiliary device using mlx5_sd_get_adev(). However,
>> the current implementation returns the primary ETH auxiliary device
>> without holding the device lock, leading to a potential race condition
>> where the ETH device could be unbound or removed concurrently during
>> probe, suspend, resume, or remove operations.[1]
>>
>> Fix this by introducing mlx5_sd_put_adev() and updating
>> mlx5_sd_get_adev() so that secondaries devices would acquire the device
>> lock of the returned auxiliary device. After the lock is acquired, a
>> second devcom check is needed[2].
>> In addition, update The callers to pair the get operation with the new
>> put operation, ensuring the lock is held while the auxiliary device is
>> being operated on and released afterwards.
>
> Please explain why the "primary" designation is reliable, and therefore
> we can be sure there will be no ABBA deadlock here
The "primary" designation is determined once in sd_register(). It's set
before devcom is marked ready, and it never changes after that.
In Addition, The primary path never locks a secondary: When the primary
device invoke mlx5_sd_get_adev(), it sees dev == primary and returns.
no additional lock is taken.
Therefore lock ordering is always: secondary_lock → primary_lock. The
reverse never happens, so ABBA deadlock is impossible.
Does the above is the explanation you looked for?
If not, can you elaborate?
If yes, to add it to the commit message in V2?
>
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
>> index b6c12460b54a..5761f655f488 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
>> @@ -6657,8 +6657,11 @@ static int mlx5e_resume(struct auxiliary_device *adev)
>> return err;
>>
>> actual_adev = mlx5_sd_get_adev(mdev, adev, edev->idx);
>> - if (actual_adev)
>> - return _mlx5e_resume(actual_adev);
>> + if (actual_adev) {
>> + err = _mlx5e_resume(actual_adev);
>> + mlx5_sd_put_adev(actual_adev, adev);
>> + return err;
>> + }
>> return 0;
>
> Feels like I recently complained about similar code y'all were trying
> to add. Magically and conditionally locking something in a get helper
> makes for extremely confusing code.
Do you think explicit locking API is preferred here?
something like:
new_locking_api()
mlx5_sd_get_adev()
new_unlocking_api()
thanks for the review
> --
> pw-bot: cr
^ permalink raw reply
* Re: [RFC PATCH 0/6] rust: net: introduce minimal rtnl/netdevice abstractions and nlmon reference driver
From: Andrew Lunn @ 2026-04-02 20:00 UTC (permalink / raw)
To: Wenzhao Liao
Cc: rust-for-linux, netdev, linux-kernel, ojeda, boqun, gary,
bjorn3_gh, lossin, a.hindborg, aliceryhl, tmgross, dakr,
andrew+netdev, davem, edumazet, kuba, pabeni
In-Reply-To: <20260402163640.1079056-1-wenzhaoliao@ruc.edu.cn>
On Thu, Apr 02, 2026 at 12:36:34PM -0400, Wenzhao Liao wrote:
> Hi,
>
> This RFC proposes a minimal set of Rust networking abstractions for
> link-type drivers, together with a Rust implementation of nlmon as a
> reference driver.
nlmon exists. Why would we want a second implementation in Rust?
It seems like we keep getting Rust submissions for the sake of
submitting Rust. We never seem to get Rust code adding something new,
something which does not already exist.
Please, if you want to submit Rust code, find a device which does not
have a driver and write a driver for it, in Rust. Or find a protocol
described in an RFC which we don't implement, and write a Rust
implementation. Or find a new firewall rule which cannot be described
using the current code, and implement it in Rust.
Unless it is something new, i doubt it will get accepted.
Andrew
^ permalink raw reply
* Re: [PATCH net 2/3] net/mlx5: SD, Keep multi-pf debugfs entries on primary
From: Shay Drori @ 2026-04-02 19:50 UTC (permalink / raw)
To: Jakub Kicinski, tariqt
Cc: edumazet, pabeni, andrew+netdev, davem, saeedm, mbloch, leon,
horms, kees, parav, phaddad, gal, netdev, linux-rdma,
linux-kernel
In-Reply-To: <20260402030911.878500-1-kuba@kernel.org>
On 02/04/2026 6:09, Jakub Kicinski wrote:
> External email: Use caution opening links or attachments
>
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> net/mlx5: SD, Keep multi-pf debugfs entries on primary
>
> This commit fixes an issue where the "multi-pf" debugfs directory was stored
> in the calling device's sd struct but created under the primary device's root.
> It explicitly stores the debugfs dentry in the primary device's sd struct.
>
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
>> index 060649645012..4c80b9d25283 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
> [ ... ]
>> @@ -491,6 +499,7 @@ void mlx5_sd_cleanup(struct mlx5_core_dev *dev)
>> {
>> struct mlx5_sd *sd = mlx5_get_sd(dev);
>> struct mlx5_core_dev *primary, *pos;
>> + struct mlx5_sd *primary_sd;
>> int i;
>>
>> if (!sd)
>> @@ -500,10 +509,12 @@ void mlx5_sd_cleanup(struct mlx5_core_dev *dev)
>> goto out;
>>
>> primary = mlx5_sd_get_primary(dev);
>> + primary_sd = mlx5_get_sd(primary);
>> mlx5_sd_for_each_secondary(i, primary, pos)
>> sd_cmd_unset_secondary(pos);
>> sd_cmd_unset_primary(primary);
>> - debugfs_remove_recursive(sd->dfs);
>> + debugfs_remove_recursive(primary_sd->dfs);
>> + primary_sd->dfs = NULL;
>
> Can concurrent unbind operations cause a use-after-free and double-free
> regression here?
>
> In mlx5_sd_cleanup(), the check !mlx5_devcom_comp_is_ready(sd->devcom) is
> performed locklessly. If multiple physical functions in the Socket-Direct
> group are unbound concurrently, multiple threads can observe ready == true
> and enter this teardown block simultaneously.
>
> Since the cleanup code now operates on the shared primary_sd pointer instead
> of the local device's sd, the thread for the primary physical function might
> complete its unbind and execute sd_cleanup(dev), freeing its sd object
> (which is primary_sd).
>
> Concurrently, the thread for a secondary physical function will dereference
> the freed primary_sd to access primary_sd->dfs, causing a use-after-free.
> Both threads could also pass the same pointer to debugfs_remove_recursive(),
> resulting in a double-free.
>
> Note: This was fixed later in the patch series by commit 92528cec4e0b91deb
> ("net/mlx5: SD: Serialize init/cleanup").
This is correct, will re-arrange the patches so that this patch will be
after "net/mlx5: SD: Serialize init/cleanup".
> --
> pw-bot: cr
^ permalink raw reply
* Re: [PATCH net 3/3] net/mlx5: SD: Serialize init/cleanup
From: Shay Drori @ 2026-04-02 19:49 UTC (permalink / raw)
To: Jakub Kicinski, tariqt
Cc: edumazet, pabeni, andrew+netdev, davem, saeedm, mbloch, leon,
horms, kees, parav, phaddad, gal, netdev, linux-rdma,
linux-kernel
In-Reply-To: <20260402030914.878606-1-kuba@kernel.org>
On 02/04/2026 6:09, Jakub Kicinski wrote:
> External email: Use caution opening links or attachments
>
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> net/mlx5: SD: Serialize init/cleanup
>
> This commit introduces a state tracker and locking around the Socket-Direct
> init and cleanup routines. It prevents multiple physical functions from
> concurrently bringing up or tearing down the SD group.
>
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
>> index 4c80b9d25283..374f27b78fbe 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
>
> [ ... ]
>
>> @@ -505,11 +520,16 @@ void mlx5_sd_cleanup(struct mlx5_core_dev *dev)
>> if (!sd)
>> return;
>>
>> + mlx5_devcom_comp_lock(sd->devcom);
>> if (!mlx5_devcom_comp_is_ready(sd->devcom))
>> - goto out;
>> + goto out_unlock;
>>
>> primary = mlx5_sd_get_primary(dev);
>> primary_sd = mlx5_get_sd(primary);
>> +
>> + if (primary_sd->state != MLX5_SD_STATE_UP)
>> + goto out_unlock;
>> +
>> mlx5_sd_for_each_secondary(i, primary, pos)
>> sd_cmd_unset_secondary(pos);
>> sd_cmd_unset_primary(primary);
>> @@ -517,7 +537,9 @@ void mlx5_sd_cleanup(struct mlx5_core_dev *dev)
>> primary_sd->dfs = NULL;
>>
>> sd_info(primary, "group id %#x, uncombined\n", sd->group_id);
>> -out:
>> + primary_sd->state = MLX5_SD_STATE_DOWN;
>> +out_unlock:
>> + mlx5_devcom_comp_unlock(sd->devcom);
>> sd_unregister(dev);
>> sd_cleanup(dev);
>> }
>
> Is there a race condition if a secondary PF calls mlx5_sd_init() while the
> primary PF is running mlx5_sd_cleanup()?
>
> In mlx5_sd_cleanup(), the code sets the state to MLX5_SD_STATE_DOWN and drops
> the devcom lock before calling sd_unregister(). At this point, the primary
> PF is still registered in the devcom group, so mlx5_devcom_comp_is_ready()
> remains true.
>
> If a secondary PF is concurrently probed, could it acquire the devcom lock
> and observe this intermediate state?
>
> CPU1
> mlx5_sd_cleanup()
> primary_sd->state = MLX5_SD_STATE_DOWN;
> mlx5_devcom_comp_unlock(sd->devcom);
> // Preempted before sd_unregister(dev)
>
> CPU2 would see this in mlx5_sd_init():
> mlx5_devcom_comp_lock(sd->devcom);
> if (!mlx5_devcom_comp_is_ready(sd->devcom)) // returns true
> goto out;
>
> primary = mlx5_sd_get_primary(dev);
> primary_sd = mlx5_get_sd(primary);
>
> if (primary_sd->state == MLX5_SD_STATE_UP) // returns false
> goto out;
> ...
> debugfs_create_file("primary", 0400, primary_sd->dfs, primary, &dev_fops);
>
> Would CPU2 proceed to initialize the group using the dying primary PF?
>
> If CPU1 then resumes and finishes sd_cleanup(), it would free the primary_sd
> structure and the primary device. This might leave the secondary PF with
> dangling pointers in the debugfs files, potentially leading to a
> use-after-free on access.
>
> Furthermore, when the secondary is later removed, mlx5_sd_cleanup(secondary)
> might see is_ready as false and skip the teardown entirely, leaving the
> dangling debugfs files permanently.
Thank, Good catch. will fix in V2
^ permalink raw reply
* [PATCH] sungem: fix PHY initialization hardware failure check and pointe style
From: Joel @ 2026-04-02 19:42 UTC (permalink / raw)
To: andrew+netdev; +Cc: davem, edumazet, kuba, pabeni, netdev, linux-kernel, Joel
Currently, bcm5411_init does not validate the result of the PHY register
reads. This can lead to silent failures if the hardware is unresponsive
or the MDIO bus times out, as 0xffff would be treated as valid data.
This patch:
1: Adds a check for -EIO and 0xffff during BCM5411 initialization.
2: Updates gem_init_phy to log an error message fi the PHY-
specific init fails.
3: Cleans up pointer formatting(eg,. foo* bar to foo *bar) to
align with Linux Kernel Coding Style in the modified files.
Signed-off-by: Joel <joelcrouch@gmail.com>
---
drivers/net/ethernet/sun/sungem.c | 8 +++--
drivers/net/sungem_phy.c | 60 +++++++++++++++++--------------
2 files changed, 39 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 8e69d917d..525aba527 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -1707,8 +1707,12 @@ static void gem_init_phy(struct gem *gp)
sungem_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
/* Init PHY */
- if (gp->phy_mii.def && gp->phy_mii.def->ops->init)
- gp->phy_mii.def->ops->init(&gp->phy_mii);
+ if (gp->phy_mii.def && gp->phy_mii.def->ops->init) {
+ int err = gp->phy_mii.def->ops->init(&gp->phy_mii);
+
+ if (err)
+ netdev_err(gp->dev, "PHY init failed: %d\n", err);
+ }
} else {
gem_pcs_reset(gp);
gem_pcs_reinit_adv(gp);
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index c10198d44..ec8800c93 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -44,27 +44,27 @@ static const int phy_BCM5400_link_table[8][3] = {
{ 1, 0, 1 }, /* 1000BT */
};
-static inline int __sungem_phy_read(struct mii_phy* phy, int id, int reg)
+static inline int __sungem_phy_read(struct mii_phy *phy, int id, int reg)
{
return phy->mdio_read(phy->dev, id, reg);
}
-static inline void __sungem_phy_write(struct mii_phy* phy, int id, int reg, int val)
+static inline void __sungem_phy_write(struct mii_phy *phy, int id, int reg, int val)
{
phy->mdio_write(phy->dev, id, reg, val);
}
-static inline int sungem_phy_read(struct mii_phy* phy, int reg)
+static inline int sungem_phy_read(struct mii_phy *phy, int reg)
{
return phy->mdio_read(phy->dev, phy->mii_id, reg);
}
-static inline void sungem_phy_write(struct mii_phy* phy, int reg, int val)
+static inline void sungem_phy_write(struct mii_phy *phy, int reg, int val)
{
phy->mdio_write(phy->dev, phy->mii_id, reg, val);
}
-static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
+static int reset_one_mii_phy(struct mii_phy *phy, int phy_id)
{
u16 val;
int limit = 10000;
@@ -88,7 +88,7 @@ static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
return limit <= 0;
}
-static int bcm5201_init(struct mii_phy* phy)
+static int bcm5201_init(struct mii_phy *phy)
{
u16 data;
@@ -101,7 +101,7 @@ static int bcm5201_init(struct mii_phy* phy)
return 0;
}
-static int bcm5201_suspend(struct mii_phy* phy)
+static int bcm5201_suspend(struct mii_phy *phy)
{
sungem_phy_write(phy, MII_BCM5201_INTERRUPT, 0);
sungem_phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
@@ -109,7 +109,7 @@ static int bcm5201_suspend(struct mii_phy* phy)
return 0;
}
-static int bcm5221_init(struct mii_phy* phy)
+static int bcm5221_init(struct mii_phy *phy)
{
u16 data;
@@ -132,7 +132,7 @@ static int bcm5221_init(struct mii_phy* phy)
return 0;
}
-static int bcm5221_suspend(struct mii_phy* phy)
+static int bcm5221_suspend(struct mii_phy *phy)
{
u16 data;
@@ -147,7 +147,7 @@ static int bcm5221_suspend(struct mii_phy* phy)
return 0;
}
-static int bcm5241_init(struct mii_phy* phy)
+static int bcm5241_init(struct mii_phy *phy)
{
u16 data;
@@ -170,7 +170,7 @@ static int bcm5241_init(struct mii_phy* phy)
return 0;
}
-static int bcm5241_suspend(struct mii_phy* phy)
+static int bcm5241_suspend(struct mii_phy *phy)
{
u16 data;
@@ -185,7 +185,7 @@ static int bcm5241_suspend(struct mii_phy* phy)
return 0;
}
-static int bcm5400_init(struct mii_phy* phy)
+static int bcm5400_init(struct mii_phy *phy)
{
u16 data;
@@ -214,7 +214,7 @@ static int bcm5400_init(struct mii_phy* phy)
return 0;
}
-static int bcm5400_suspend(struct mii_phy* phy)
+static int bcm5400_suspend(struct mii_phy *phy)
{
#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
sungem_phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -222,7 +222,7 @@ static int bcm5400_suspend(struct mii_phy* phy)
return 0;
}
-static int bcm5401_init(struct mii_phy* phy)
+static int bcm5401_init(struct mii_phy *phy)
{
u16 data;
int rev;
@@ -270,7 +270,7 @@ static int bcm5401_init(struct mii_phy* phy)
return 0;
}
-static int bcm5401_suspend(struct mii_phy* phy)
+static int bcm5401_suspend(struct mii_phy *phy)
{
#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
sungem_phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -278,8 +278,9 @@ static int bcm5401_suspend(struct mii_phy* phy)
return 0;
}
-static int bcm5411_init(struct mii_phy* phy)
+static int bcm5411_init(struct mii_phy *phy)
{
+ int val;
u16 data;
/* Here's some more Apple black magic to setup
@@ -295,7 +296,12 @@ static int bcm5411_init(struct mii_phy* phy)
sungem_phy_write(phy, MII_BMCR, BMCR_RESET);
sungem_phy_write(phy, MII_BMCR, 0x1340);
- data = sungem_phy_read(phy, MII_BCM5400_GB_CONTROL);
+ val = sungem_phy_read(phy, MII_BCM5400_GB_CONTROL);
+
+ if (val < 0 || val == 0xffff)
+ return -EIO;
+
+ data = (u16)val;
data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
sungem_phy_write(phy, MII_BCM5400_GB_CONTROL, data);
@@ -408,14 +414,14 @@ static int genmii_read_link(struct mii_phy *phy)
return 0;
}
-static int generic_suspend(struct mii_phy* phy)
+static int generic_suspend(struct mii_phy *phy)
{
sungem_phy_write(phy, MII_BMCR, BMCR_PDOWN);
return 0;
}
-static int bcm5421_init(struct mii_phy* phy)
+static int bcm5421_init(struct mii_phy *phy)
{
u16 data;
unsigned int id;
@@ -548,7 +554,7 @@ static int bcm54xx_read_link(struct mii_phy *phy)
u16 val;
if (phy->autoneg) {
- val = sungem_phy_read(phy, MII_BCM5400_AUXSTATUS);
+ val = sungem_phy_read(phy, MII_BCM5400_AUXSTATUS);
link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
phy->duplex = phy_BCM5400_link_table[link_mode][0] ?
@@ -568,7 +574,7 @@ static int bcm54xx_read_link(struct mii_phy *phy)
return 0;
}
-static int marvell88e1111_init(struct mii_phy* phy)
+static int marvell88e1111_init(struct mii_phy *phy)
{
u16 rev;
@@ -592,7 +598,7 @@ static int marvell88e1111_init(struct mii_phy* phy)
#define BCM5421_MODE_MASK (1 << 5)
-static int bcm5421_poll_link(struct mii_phy* phy)
+static int bcm5421_poll_link(struct mii_phy *phy)
{
u32 phy_reg;
int mode;
@@ -616,7 +622,7 @@ static int bcm5421_poll_link(struct mii_phy* phy)
return 1;
}
-static int bcm5421_read_link(struct mii_phy* phy)
+static int bcm5421_read_link(struct mii_phy *phy)
{
u32 phy_reg;
int mode;
@@ -644,7 +650,7 @@ static int bcm5421_read_link(struct mii_phy* phy)
return 0;
}
-static int bcm5421_enable_fiber(struct mii_phy* phy, int autoneg)
+static int bcm5421_enable_fiber(struct mii_phy *phy, int autoneg)
{
/* enable fiber mode */
sungem_phy_write(phy, MII_NCONFIG, 0x9020);
@@ -665,7 +671,7 @@ static int bcm5421_enable_fiber(struct mii_phy* phy, int autoneg)
#define BCM5461_FIBER_LINK (1 << 2)
#define BCM5461_MODE_MASK (3 << 1)
-static int bcm5461_poll_link(struct mii_phy* phy)
+static int bcm5461_poll_link(struct mii_phy *phy)
{
u32 phy_reg;
int mode;
@@ -691,7 +697,7 @@ static int bcm5461_poll_link(struct mii_phy* phy)
#define BCM5461_FIBER_DUPLEX (1 << 3)
-static int bcm5461_read_link(struct mii_phy* phy)
+static int bcm5461_read_link(struct mii_phy *phy)
{
u32 phy_reg;
int mode;
@@ -720,7 +726,7 @@ static int bcm5461_read_link(struct mii_phy* phy)
return 0;
}
-static int bcm5461_enable_fiber(struct mii_phy* phy, int autoneg)
+static int bcm5461_enable_fiber(struct mii_phy *phy, int autoneg)
{
/* select fiber mode, enable 1000 base-X registers */
sungem_phy_write(phy, MII_NCONFIG, 0xfc0b);
--
2.43.0
^ permalink raw reply related
* [syzbot] [net?] [bpf?] WARNING in sock_map_destroy (3)
From: syzbot @ 2026-04-02 19:39 UTC (permalink / raw)
To: andrii, ast, bpf, daniel, davem, edumazet, horms, jakub,
jiayuan.chen, john.fastabend, kuba, kuniyu, kuniyu, linux-kernel,
martin.lau, netdev, pabeni, syzkaller-bugs, willemb
Hello,
syzbot found the following issue on:
HEAD commit: 1b237f190eb3 Linux 6.17-rc3
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=13551c42580000
kernel config: https://syzkaller.appspot.com/x/.config?x=e1e1566c7726877e
dashboard link: https://syzkaller.appspot.com/bug?extid=b0842d38af58376d1fdc
compiler: Debian clang version 20.1.7 (++20250616065708+6146a88f6049-1~exp1~20250616065826.132), Debian LLD 20.1.7
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=168d6ef0580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=16f57862580000
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/d708c97252af/disk-1b237f19.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/3b964889e9fe/vmlinux-1b237f19.xz
kernel image: https://storage.googleapis.com/syzbot-assets/2d05741e1ef1/bzImage-1b237f19.xz
The issue was bisected to:
commit 8259eb0e06d8f64c700f5fbdb28a5c18e10de291
Author: Jiayuan Chen <jiayuan.chen@linux.dev>
Date: Fri May 16 14:17:12 2025 +0000
bpf, sockmap: Avoid using sk_socket after free when sending
bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=17fbce62580000
final oops: https://syzkaller.appspot.com/x/report.txt?x=1407ce62580000
console output: https://syzkaller.appspot.com/x/log.txt?x=1007ce62580000
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+b0842d38af58376d1fdc@syzkaller.appspotmail.com
Fixes: 8259eb0e06d8 ("bpf, sockmap: Avoid using sk_socket after free when sending")
------------[ cut here ]------------
WARNING: CPU: 1 PID: 8459 at net/core/sock_map.c:1667 sock_map_destroy+0x28b/0x2b0 net/core/sock_map.c:1667
Modules linked in:
CPU: 1 UID: 0 PID: 8459 Comm: syz.0.1109 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025
RIP: 0010:sock_map_destroy+0x28b/0x2b0 net/core/sock_map.c:1667
Code: 8b 36 49 83 c6 38 4c 89 f0 48 c1 e8 03 42 80 3c 38 00 74 08 4c 89 f7 e8 93 62 22 f9 4d 8b 3e e9 79 ff ff ff e8 a6 2b c3 f8 90 <0f> 0b 90 eb 9c e8 9b 2b c3 f8 4c 89 e7 be 03 00 00 00 e8 0e 4e bc
RSP: 0018:ffffc9000d067be8 EFLAGS: 00010293
RAX: ffffffff88fb30aa RBX: ffff888024832000 RCX: ffff888024283b80
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
R10: dffffc0000000000 R11: ffffed100862e946 R12: dffffc0000000000
R13: ffff888024832000 R14: ffffffff995b2208 R15: ffffffff88fb2e20
FS: 0000555579a7d500(0000) GS:ffff8881269c2000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00002000000048c0 CR3: 000000003713a000 CR4: 00000000003526f0
Call Trace:
<TASK>
inet_csk_destroy_sock+0x166/0x3a0 net/ipv4/inet_connection_sock.c:1294
__tcp_close+0xcc1/0xfd0 net/ipv4/tcp.c:3262
tcp_close+0x28/0x110 net/ipv4/tcp.c:3274
inet_release+0x144/0x190 net/ipv4/af_inet.c:435
__sock_release net/socket.c:649 [inline]
sock_close+0xc0/0x240 net/socket.c:1439
__fput+0x45b/0xa80 fs/file_table.c:468
task_work_run+0x1d4/0x260 kernel/task_work.c:227
resume_user_mode_work include/linux/resume_user_mode.h:50 [inline]
exit_to_user_mode_loop+0xec/0x110 kernel/entry/common.c:43
exit_to_user_mode_prepare include/linux/irq-entry-common.h:225 [inline]
syscall_exit_to_user_mode_work include/linux/entry-common.h:175 [inline]
syscall_exit_to_user_mode include/linux/entry-common.h:210 [inline]
do_syscall_64+0x2bd/0x3b0 arch/x86/entry/syscall_64.c:100
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f265847ebe9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffd158dfbd8 EFLAGS: 00000246 ORIG_RAX: 00000000000001b4
RAX: 0000000000000000 RBX: 000000000002ddb0 RCX: 00007f265847ebe9
RDX: 0000000000000000 RSI: 000000000000001e RDI: 0000000000000003
RBP: 00007f26586a7da0 R08: 0000000000000001 R09: 0000000e158dfecf
R10: 0000001b30a20000 R11: 0000000000000246 R12: 00007f26586a5fac
R13: 00007f26586a5fa0 R14: ffffffffffffffff R15: 00007ffd158dfcf0
</TASK>
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
For information about bisection process see: https://goo.gl/tpsmEJ#bisection
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply
* Re: [PATCH] vsock: avoid timeout for non-blocking accept() with empty backlog
From: Laurence Rowe @ 2026-04-02 19:22 UTC (permalink / raw)
To: Stefano Garzarella; +Cc: virtualization, netdev, Bobby Eshleman
In-Reply-To: <ac47PYPeL0IyRtY6@sgarzare-redhat>
On Thu, Apr 2, 2026 at 5:03 AM Stefano Garzarella <sgarzare@redhat.com> wrote:
> >Scheduling a timeout for a non-blocking accept with an empty backlog
> >meant AF_VSOCK sockets used by epoll network servers incurred hundreds
> >of microseconds of additional latency per accept loop compared to
> >AF_INET or AF_UNIX sockets.
>
> Not related to this patch, but should we do something similar (in
> another patch) also in vsock_connect() or doesn't matter since usually
> it's always blocking?
Looking at vsock_connect it's not immediately obvious to me whether it
is affected
in the same way. I'll capture some ftraces and follow up after
updating this patch.
> >diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
> >index 2f7d94d682..483889b6d8 100644
> >--- a/net/vmw_vsock/af_vsock.c
> >+++ b/net/vmw_vsock/af_vsock.c
> >@@ -1850,11 +1850,11 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
> > * created upon connection establishment.
> > */
> > timeout = sock_rcvtimeo(listener, arg->flags & O_NONBLOCK);
> >- prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
> >
> > while ((connected = vsock_dequeue_accept(listener)) == NULL &&
> >- listener->sk_err == 0) {
> >+ listener->sk_err == 0 && timeout != 0) {
> > release_sock(listener);
> >+ prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
>
> Is it okay to move prepare_to_wait() after `release_sock(listener)`?
>
> I'm worried if we can miss any wakeup. BTW if this change is okay, we
> should document that at least in the commit description.
I'm not sure. I'll swap them around so they are the same order as before.
> From checkpatch:
> CHECK: Comparison to NULL could be written "!connected"
> #58: FILE: net/vmw_vsock/af_vsock.c:1870:
> + } else if (timeout == 0 && connected == NULL) {
>
> >+ err = -EAGAIN;
> >+ goto out;
> >+ }
>
> What about simplifying this with (not a strong opinion):
>
> } else if (connected == NULL) {
> err = -EAGAIN;
> }
That definitely seems cleaner.
> Also
> https://patchwork.kernel.org/project/netdevbpf/patch/20260402044637.73531-1-laurencerowe@gmail.com/
> suggests to specify a tree (net-next I think for this change) and be
> sure to CC other maintainers (scripts/get_maintainer.pl can help).
Sorry about that, first kernel patch submission. Will do so when I
send the updated patch.
Laurence
^ permalink raw reply
* Re: [PATCH net-next] net-timestamp: take track of the skb when wait_for_space occurs
From: Willem de Bruijn @ 2026-04-02 19:18 UTC (permalink / raw)
To: Jason Xing, Eric Dumazet
Cc: davem, kuba, pabeni, horms, willemb, netdev, Jason Xing,
Yushan Zhou
In-Reply-To: <CAL+tcoBB+d-PwNzx1ugjDwZZBaQf8vxb3XooM3ARw9CtbiFeqw@mail.gmail.com>
Jason Xing wrote:
> On Thu, Apr 2, 2026 at 11:40 PM Eric Dumazet <edumazet@google.com> wrote:
> >
> > On Thu, Apr 2, 2026 at 8:03 AM Jason Xing <kerneljasonxing@gmail.com> wrote:
> > >
> > > On Thu, Apr 2, 2026 at 10:24 PM Eric Dumazet <edumazet@google.com> wrote:
> > > >
> > > > On Thu, Apr 2, 2026 at 1:58 AM Jason Xing <kerneljasonxing@gmail.com> wrote:
> > > > >
> > > > > From: Jason Xing <kernelxing@tencent.com>
> > > > >
> > > > > Tag the skb in tcp_sendmsg_locked() when wait_for_space occurs even
> > > > > though it might not carry the last byte of the sendmsg.
> > > > >
> > > > > If we don't do so, we might be faced with no single timestamp that
> > > > > can be received by application from the error queue. The following steps
> > > > > reproduce this:
> > > > > 1) skb A is the current last skb before entering wait_for_space process
> > > > > 2) tcp_push() pushes A without any tag
> > > > > 3) A is transmitted from TCP to driver without putting any skb carring
> > > > > timestamps in the error queue, like SCHED, DRV/HARDWARE.
> > > > > 4) sk_stream_wait_memory() sleeps for a while and then returns with an
> > > > > error code. Note that the socket lock is released.
> > > > > 5) skb A finally gets acked and removed from the rtx queue.
> > > > > 6) continue with the rest of tcp_sendmsg_locked(): it will jump to(goto)
> > > > > 'do_error' label and then 'out' label.
> > > > > 7) at this moment, skb A turns out to be the last one in this send
> > > > > syscall, and miss the following tcp_tx_timestamp() opportunity before
> > > > > the final tcp_push
> > > > > 8) application receives no timestamps this time
> > > > >
> > > > > The original commit ad02c4f54782 ("tcp: provide timestamps for partial writes")
> > > > > says it is best effort. Now it's time to cover the only potential point
> > > > > to avoid missing record.
> > > > >
> > > > > The side effect is obvious that we might record more than one time for a
> > > > > single send syscall since the skb that we keep track of in this scenario
> > > > > might not be the last one. But tracing more than one skb is not a bad
> > > > > thing since there is an emerging/promissing trend to do a detailed
> > > > > packet granularity monitor.
> > > >
> > > > This is rather weak/lazy, especially if you do not know how long the
> > > > thread is put to sleep?
> > >
> > > Thanks for the review!
> > >
> > > I actually thought about how to recognize which one should be the last
> > > skb in each send syscall. But it turns out that much more complicated
> > > work needs to be done which hurts the stack and common structures like
> > > tcp_sock. That's why I gave up and instead chose a much simpler way to
> > > minimize the impact.
> > >
> > > >
> > > > >
> > > > > Thanks to the great ID, namely, tskey, application that is responsible
> > > > > for the collect/sort of timestamps leverages it to put that record in
> > > > > between two consecutive send syscalls correctly.
> > > > >
> > > > > Signed-off-by: Yushan Zhou <katrinzhou@tencent.com>
> > > > > Signed-off-by: Jason Xing <kernelxing@tencent.com>
> > > > > ---
> > > > > net/ipv4/tcp.c | 4 +++-
> > > > > 1 file changed, 3 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> > > > > index 516087c622ad..2db80d75cfa4 100644
> > > > > --- a/net/ipv4/tcp.c
> > > > > +++ b/net/ipv4/tcp.c
> > > > > @@ -1411,9 +1411,11 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
> > > > > wait_for_space:
> > > > > set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
> > > > > tcp_remove_empty_skb(sk);
> > > > > - if (copied)
> > > > > + if (copied) {
> > > > > + tcp_tx_timestamp(sk, &sockc);
> > > > > tcp_push(sk, flags & ~MSG_MORE, mss_now,
> > > > > TCP_NAGLE_PUSH, size_goal);
> > > > > + }
> > > > >
> > > > > err = sk_stream_wait_memory(sk, &timeo);
> > > > > if (err != 0)
> > > >
> > > > I think non blocking model should be used by modern applications,
> > > > especially ones caring about timestamps.
> > >
> > > Please note that BPF timestamping has already been merged. It's a
> > > standalone script that monitors all kinds of flows and discovers those
> > > strange/unexpected behaviors. So we normally don't take a look at the
> > > implementation of each application before spotting any exceptions.
> > >
> > > Besides, sometimes monitoring the latency of the host doesn't have
> > > much to do with the mode of application. People might want to observe
> > > more deeper into the underlying layer. Right now, without the patch,
> > > the monitor possibly ends up missing the record of this send syscall,
> > > which has been reliably reproduced by Yushan.
> > >
> > > >
> > > > This patch has performance implications.
> > > >
> > > > tcp_tx_timestamp() is quite big and was inlined because it had a single caller.
> > > >
> > > > After this patch, it is no longer inlined.
> > > >
> > > > scripts/bloat-o-meter -t vmlinux.before vmlinux.after
> > > > add/remove: 2/0 grow/shrink: 0/1 up/down: 239/-192 (47)
> > > > Function old new delta
> > > > tcp_tx_timestamp - 223 +223
> > > > __pfx_tcp_tx_timestamp - 16 +16
> > > > tcp_sendmsg_locked 4560 4368 -192
> > > > Total: Before=29652698, After=29652745, chg +0.00%
> > >
> > > That's right and I really appreciate your recent great effort trying
> > > to mitigate the impact of function calls.
> > >
> > > My take is that it is a trade off. Adding one more track of the skb
> > > (which adds a function call) actually doesn't hurt much especially for
> > > this scenario and the last skb scenario. This path basically is not
> > > that hot. There are some left things to be done to improve the
> > > socket/BPF timestamping feature. And I plan to push more patches
> > > (sure, very carefully) to enhance the ability of BPF timestamping to
> > > observe TCP which is inevitable to add some extra functions and if
> > > statements.
> > >
> > > I'm wondering if the above makes sense to you.
> >
> > If you mostly care about BPF, I would suggest:
>
> For me, yes, I've been internally working on this stuff for a long
> while and still struggling with what part is worth upstreaming. I'm
> not sure how Willem thinks of the socket timestamping feature.
I think it's fine to move forward with BPF only features. We can make
that call on a case-by-case basis.
^ permalink raw reply
* Re: [PATCH 1/3] [v4, net-next] net: ethernet: ti-cpsw:: rename soft_reset() function
From: Arnd Bergmann @ 2026-04-02 19:16 UTC (permalink / raw)
To: Ilias Apalodimas, Arnd Bergmann
Cc: Netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Grygorii Strashko, Murali Karicheri,
Siddharth Vadapalli, Roger Quadros, Vladimir Oltean,
Alexander Sverdlin, Ioana Ciornei, Linux-OMAP, Kevin Hao,
Daniel Zahka, linux-kernel
In-Reply-To: <CAC_iWj+vjZ0WnKUuqeFfaPeSoj5ovxZiEmUD5R8hPsRfkqMihQ@mail.gmail.com>
On Thu, Apr 2, 2026, at 21:13, Ilias Apalodimas wrote:
> Hi Arnd,
>
> On Thu, 2 Apr 2026 at 21:47, Arnd Bergmann <arnd@kernel.org> wrote:
>>
>> From: Arnd Bergmann <arnd@arndb.de>
>>
>> While looking at the glob symbols shared between the cpsw drivers,
>> I noticed that soft_reset() is the only one that is missing a proper
>> namespace prefix, and will pollute the kernel namespace, so rename
>> it to be consistent with the other symbols.
>>
>> Fixes: c5013ac1dd0e1 ("net: ethernet: ti: cpsw: move set of common functions in cpsw_priv")
>
> The patch seems fine, but why the Fixes: tag?
Before the c5013ac1dd0e1 commit, this was a 'static inline' function,
which is allowed to clash with other identifiers. Making it a global
symbol during the move was a problem.
Arnd
^ permalink raw reply
* Re: [PATCH v5] rtnetlink: add missing netlink_ns_capable() check for peer netns
From: Kuniyuki Iwashima @ 2026-04-02 19:16 UTC (permalink / raw)
To: Nikolaos Gkarlis; +Cc: netdev, kuba
In-Reply-To: <20260402181432.4126920-1-nickgarlis@gmail.com>
On Thu, Apr 2, 2026 at 11:15 AM Nikolaos Gkarlis <nickgarlis@gmail.com> wrote:
>
> rtnl_newlink() lacks a CAP_NET_ADMIN capability check on the peer
> network namespace when creating paired devices (veth, vxcan,
> netkit). This allows an unprivileged user with a user namespace
> to create interfaces in arbitrary network namespaces, including
> init_net.
>
> Add a netlink_ns_capable() check for CAP_NET_ADMIN in the peer
> namespace before allowing device creation to proceed.
>
> Fixes: 81adee47dfb6 ("net: Support specifying the network namespace upon device creation.")
> Signed-off-by: Nikolaos Gkarlis <nickgarlis@gmail.com>
Looks good, thanks !
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
^ permalink raw reply
* Re: [PATCH 1/3] [v4, net-next] net: ethernet: ti-cpsw:: rename soft_reset() function
From: Ilias Apalodimas @ 2026-04-02 19:13 UTC (permalink / raw)
To: Arnd Bergmann
Cc: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Grygorii Strashko, Murali Karicheri,
Siddharth Vadapalli, Roger Quadros, Vladimir Oltean,
Alexander Sverdlin, Ioana Ciornei, linux-omap, Arnd Bergmann,
Kevin Hao, Daniel Zahka, linux-kernel
In-Reply-To: <20260402184726.3746487-1-arnd@kernel.org>
Hi Arnd,
On Thu, 2 Apr 2026 at 21:47, Arnd Bergmann <arnd@kernel.org> wrote:
>
> From: Arnd Bergmann <arnd@arndb.de>
>
> While looking at the glob symbols shared between the cpsw drivers,
> I noticed that soft_reset() is the only one that is missing a proper
> namespace prefix, and will pollute the kernel namespace, so rename
> it to be consistent with the other symbols.
>
> Fixes: c5013ac1dd0e1 ("net: ethernet: ti: cpsw: move set of common functions in cpsw_priv")
The patch seems fine, but why the Fixes: tag?
Cheers
/Ilias
> Reviewed-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/net/ethernet/ti/cpsw.c | 2 +-
> drivers/net/ethernet/ti/cpsw_new.c | 2 +-
> drivers/net/ethernet/ti/cpsw_priv.c | 2 +-
> drivers/net/ethernet/ti/cpsw_priv.h | 2 +-
> 4 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index b0e18bdc2c85..aa3531e844e8 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -706,7 +706,7 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
> struct cpsw_common *cpsw = priv->cpsw;
>
> /* soft reset the controller and initialize ale */
> - soft_reset("cpsw", &cpsw->regs->soft_reset);
> + cpsw_soft_reset("cpsw", &cpsw->regs->soft_reset);
> cpsw_ale_start(cpsw->ale);
>
> /* switch to vlan aware mode */
> diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
> index 7f42f58a4b03..c5be359f3c66 100644
> --- a/drivers/net/ethernet/ti/cpsw_new.c
> +++ b/drivers/net/ethernet/ti/cpsw_new.c
> @@ -573,7 +573,7 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
> u32 control_reg;
>
> /* soft reset the controller and initialize ale */
> - soft_reset("cpsw", &cpsw->regs->soft_reset);
> + cpsw_soft_reset("cpsw", &cpsw->regs->soft_reset);
> cpsw_ale_start(cpsw->ale);
>
> /* switch to vlan aware mode */
> diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c
> index bc4fdf17a99e..c6eb6b785b0b 100644
> --- a/drivers/net/ethernet/ti/cpsw_priv.c
> +++ b/drivers/net/ethernet/ti/cpsw_priv.c
> @@ -275,7 +275,7 @@ void cpsw_set_slave_mac(struct cpsw_slave *slave, struct cpsw_priv *priv)
> slave_write(slave, mac_lo(priv->mac_addr), SA_LO);
> }
>
> -void soft_reset(const char *module, void __iomem *reg)
> +void cpsw_soft_reset(const char *module, void __iomem *reg)
> {
> unsigned long timeout = jiffies + HZ;
>
> diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h
> index acb6181c5c9e..fddd7a79f4b0 100644
> --- a/drivers/net/ethernet/ti/cpsw_priv.h
> +++ b/drivers/net/ethernet/ti/cpsw_priv.h
> @@ -458,7 +458,7 @@ int cpsw_tx_poll(struct napi_struct *napi_tx, int budget);
> int cpsw_rx_mq_poll(struct napi_struct *napi_rx, int budget);
> int cpsw_rx_poll(struct napi_struct *napi_rx, int budget);
> void cpsw_rx_vlan_encap(struct sk_buff *skb);
> -void soft_reset(const char *module, void __iomem *reg);
> +void cpsw_soft_reset(const char *module, void __iomem *reg);
> void cpsw_set_slave_mac(struct cpsw_slave *slave, struct cpsw_priv *priv);
> void cpsw_ndo_tx_timeout(struct net_device *ndev, unsigned int txqueue);
> int cpsw_need_resplit(struct cpsw_common *cpsw);
> --
> 2.39.5
>
^ permalink raw reply
* [PATCH 3/3] [v4, net-next] dpaa2: avoid linking objects into multiple modules
From: Arnd Bergmann @ 2026-04-02 18:46 UTC (permalink / raw)
To: netdev, Ioana Ciornei, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Siddharth Vadapalli, Roger Quadros, Vladimir Oltean,
Alexander Sverdlin, linux-omap, Arnd Bergmann, linux-kernel
In-Reply-To: <20260402184726.3746487-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
Each object file contains information about which module it gets linked
into, so linking the same file into multiple modules now causes a warning:
scripts/Makefile.build:254: drivers/net/ethernet/freescale/dpaa2/Makefile: dpaa2-mac.o is added to multiple modules: fsl-dpaa2-eth fsl-dpaa2-switch
scripts/Makefile.build:254: drivers/net/ethernet/freescale/dpaa2/Makefile: dpmac.o is added to multiple modules: fsl-dpaa2-eth fsl-dpaa2-switch
Change the way that dpaa2 is built by moving the two common files into a
separate module with exported symbols instead.
Tested-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
v2: add missing module description
v3: rename "common" to "mac"
drop Kconfig change
rebase to linux-next
v4: fix changlog comment
post along with the corresponding ti-cpsw driver change
---
drivers/net/ethernet/freescale/dpaa2/Makefile | 9 +++++----
drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 16 ++++++++++++++++
2 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/freescale/dpaa2/Makefile b/drivers/net/ethernet/freescale/dpaa2/Makefile
index 1b05ba8d1cbf..5f74be76434f 100644
--- a/drivers/net/ethernet/freescale/dpaa2/Makefile
+++ b/drivers/net/ethernet/freescale/dpaa2/Makefile
@@ -3,15 +3,16 @@
# Makefile for the Freescale DPAA2 Ethernet controller
#
-obj-$(CONFIG_FSL_DPAA2_ETH) += fsl-dpaa2-eth.o
+obj-$(CONFIG_FSL_DPAA2_ETH) += fsl-dpaa2-eth.o fsl-dpaa2-mac.o
obj-$(CONFIG_FSL_DPAA2_PTP_CLOCK) += fsl-dpaa2-ptp.o
-obj-$(CONFIG_FSL_DPAA2_SWITCH) += fsl-dpaa2-switch.o
+obj-$(CONFIG_FSL_DPAA2_SWITCH) += fsl-dpaa2-switch.o fsl-dpaa2-mac.o
-fsl-dpaa2-eth-objs := dpaa2-eth.o dpaa2-ethtool.o dpni.o dpaa2-mac.o dpmac.o dpaa2-eth-devlink.o dpaa2-xsk.o
+fsl-dpaa2-eth-objs := dpaa2-eth.o dpaa2-ethtool.o dpni.o dpaa2-eth-devlink.o dpaa2-xsk.o
fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_DCB} += dpaa2-eth-dcb.o
fsl-dpaa2-eth-${CONFIG_DEBUG_FS} += dpaa2-eth-debugfs.o
fsl-dpaa2-ptp-objs := dpaa2-ptp.o dprtc.o
-fsl-dpaa2-switch-objs := dpaa2-switch.o dpaa2-switch-ethtool.o dpsw.o dpaa2-switch-flower.o dpaa2-mac.o dpmac.o
+fsl-dpaa2-switch-objs := dpaa2-switch.o dpaa2-switch-ethtool.o dpsw.o dpaa2-switch-flower.o
+fsl-dpaa2-mac-objs += dpaa2-mac.o dpmac.o
# Needed by the tracing framework
CFLAGS_dpaa2-eth.o := -I$(src)
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index ad812ebf3139..1f80a527264a 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -544,6 +544,7 @@ void dpaa2_mac_start(struct dpaa2_mac *mac)
phylink_start(mac->phylink);
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_start);
void dpaa2_mac_stop(struct dpaa2_mac *mac)
{
@@ -554,6 +555,7 @@ void dpaa2_mac_stop(struct dpaa2_mac *mac)
if (mac->serdes_phy)
phy_power_off(mac->serdes_phy);
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_stop);
int dpaa2_mac_connect(struct dpaa2_mac *mac)
{
@@ -646,6 +648,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
return err;
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_connect);
void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
{
@@ -658,6 +661,7 @@ void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
of_phy_put(mac->serdes_phy);
mac->serdes_phy = NULL;
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_disconnect);
int dpaa2_mac_open(struct dpaa2_mac *mac)
{
@@ -729,6 +733,7 @@ int dpaa2_mac_open(struct dpaa2_mac *mac)
dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
return err;
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_open);
void dpaa2_mac_close(struct dpaa2_mac *mac)
{
@@ -753,6 +758,7 @@ void dpaa2_mac_close(struct dpaa2_mac *mac)
if (mac->fw_node)
fwnode_handle_put(mac->fw_node);
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_close);
static void dpaa2_mac_transfer_stats(const struct dpmac_counter *counters,
size_t num_counters, void *s,
@@ -824,6 +830,7 @@ void dpaa2_mac_get_rmon_stats(struct dpaa2_mac *mac,
*ranges = dpaa2_mac_rmon_ranges;
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_get_rmon_stats);
void dpaa2_mac_get_pause_stats(struct dpaa2_mac *mac,
struct ethtool_pause_stats *s)
@@ -835,6 +842,7 @@ void dpaa2_mac_get_pause_stats(struct dpaa2_mac *mac,
DPAA2_MAC_NUM_PAUSE_STATS,
dpaa2_mac_pause_stats, s);
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_get_pause_stats);
void dpaa2_mac_get_ctrl_stats(struct dpaa2_mac *mac,
struct ethtool_eth_ctrl_stats *s)
@@ -846,6 +854,7 @@ void dpaa2_mac_get_ctrl_stats(struct dpaa2_mac *mac,
DPAA2_MAC_NUM_ETH_CTRL_STATS,
dpaa2_mac_eth_ctrl_stats, s);
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_get_ctrl_stats);
void dpaa2_mac_get_eth_mac_stats(struct dpaa2_mac *mac,
struct ethtool_eth_mac_stats *s)
@@ -857,11 +866,13 @@ void dpaa2_mac_get_eth_mac_stats(struct dpaa2_mac *mac,
DPAA2_MAC_NUM_ETH_MAC_STATS,
dpaa2_mac_eth_mac_stats, s);
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_get_eth_mac_stats);
int dpaa2_mac_get_sset_count(void)
{
return DPAA2_MAC_NUM_ETHTOOL_STATS;
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_get_sset_count);
void dpaa2_mac_get_strings(u8 **data)
{
@@ -870,6 +881,7 @@ void dpaa2_mac_get_strings(u8 **data)
for (i = 0; i < DPAA2_MAC_NUM_ETHTOOL_STATS; i++)
ethtool_puts(data, dpaa2_mac_ethtool_stats[i].name);
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_get_strings);
void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data)
{
@@ -921,3 +933,7 @@ void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data)
*(data + i) = value;
}
}
+EXPORT_SYMBOL_GPL(dpaa2_mac_get_ethtool_stats);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DPAA2 Ethernet MAC library");
--
2.39.5
^ permalink raw reply related
* [PATCH 2/3] [v4, net-next] net: ethernet: ti-cpsw: fix linking built-in code to modules
From: Arnd Bergmann @ 2026-04-02 18:46 UTC (permalink / raw)
To: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Grygorii Strashko
Cc: Siddharth Vadapalli, Roger Quadros, Vladimir Oltean,
Alexander Sverdlin, Ioana Ciornei, linux-omap, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev, Andrew F. Davis,
Basharath Hussain Khaja, Parvathi Pudi, linux-kernel, bpf
In-Reply-To: <20260402184726.3746487-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
There are six variants of the cpsw driver, sharing various parts of
the code: davinci-emac, cpsw, cpsw-switchdev, netcp, netcp_ethss and
am65-cpsw-nuss.
I noticed that this means some files can be linked into more than
one loadable module, or even part of vmlinux but also linked into
a loadable module, both of which mess up assumptions of the build
system, and causes warnings:
scripts/Makefile.build:279: cpsw_ale.o is added to multiple modules: ti-am65-cpsw-nuss ti_cpsw ti_cpsw_new
scripts/Makefile.build:279: cpsw_priv.o is added to multiple modules: ti_cpsw ti_cpsw_new
scripts/Makefile.build:279: cpsw_sl.o is added to multiple modules: ti-am65-cpsw-nuss ti_cpsw ti_cpsw_new
scripts/Makefile.build:279: cpsw_ethtool.o is added to multiple modules: ti_cpsw ti_cpsw_new
scripts/Makefile.build:279: davinci_cpdma.o is added to multiple modules: ti_cpsw ti_cpsw_new ti_davinci_emac
Change this back to having separate modules for each portion that
can be linked standalone, exporting symbols as needed:
- ti-cpsw-common.ko now contains both cpsw-common.o and
davinci_cpdma.o as they are always used together
- ti-cpsw-priv.ko contains cpsw_priv.o, cpsw_sl.o and cpsw_ethtool.o,
which are the core of the cpsw and cpsw-new drivers.
- ti-cpsw-sl.ko contains the cpsw-sl.o object and is used on
ti-am65-cpsw-nuss.ko in addition to the two other cpsw variants.
- ti-cpsw-ale.o is the one standalone module that is used by all
except davinci_emac.
Each of these will be built-in if any of its users are built-in, otherwise
it's a loadable module if there is at least one module using it. I did
not bring back the separate Kconfig symbols for this, but just handle
it using Makefile logic.
Note: ideally this is something that Kbuild complains about, but usually
we just notice when something using THIS_MODULE misbehaves in a way that
a user notices.
Fixes: 99f6297182729 ("net: ethernet: ti: cpsw: drop TI_DAVINCI_CPDMA config option")
Link: https://lore.kernel.org/lkml/20240417084400.3034104-1-arnd@kernel.org/
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
v2: rebase on top of v6.9-rc
v3: rebase on top of v7.0-rc
v4: resend together with soft_reset() change, which is a dependency
---
drivers/net/ethernet/ti/Makefile | 30 ++++++++++----------
drivers/net/ethernet/ti/cpsw_ale.c | 25 +++++++++++++++++
drivers/net/ethernet/ti/cpsw_ethtool.c | 24 ++++++++++++++++
drivers/net/ethernet/ti/cpsw_priv.c | 37 +++++++++++++++++++++++++
drivers/net/ethernet/ti/cpsw_sl.c | 11 ++++++++
drivers/net/ethernet/ti/davinci_cpdma.c | 27 ++++++++++++++++++
6 files changed, 139 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
index 6da50f4b7c2e..f4276c9a7762 100644
--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -6,30 +6,30 @@
obj-$(CONFIG_TI_PRUETH) += icssm-prueth.o
icssm-prueth-y := icssm/icssm_prueth.o icssm/icssm_prueth_switch.o icssm/icssm_switchdev.o
-obj-$(CONFIG_TI_CPSW) += cpsw-common.o
-obj-$(CONFIG_TI_DAVINCI_EMAC) += cpsw-common.o
-obj-$(CONFIG_TI_CPSW_SWITCHDEV) += cpsw-common.o
+ti-cpsw-common-y += cpsw-common.o davinci_cpdma.o
+ti-cpsw-priv-y += cpsw_priv.o cpsw_ethtool.o
+ti-cpsw-ale-y += cpsw_ale.o
+ti-cpsw-sl-y += cpsw_sl.o
obj-$(CONFIG_TLAN) += tlan.o
-obj-$(CONFIG_TI_DAVINCI_EMAC) += ti_davinci_emac.o
-ti_davinci_emac-y := davinci_emac.o davinci_cpdma.o
+obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o ti-cpsw-common.o
obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o
obj-$(CONFIG_TI_CPTS) += cpts.o
-obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
-ti_cpsw-y := cpsw.o davinci_cpdma.o cpsw_ale.o cpsw_priv.o cpsw_sl.o cpsw_ethtool.o
-obj-$(CONFIG_TI_CPSW_SWITCHDEV) += ti_cpsw_new.o
-ti_cpsw_new-y := cpsw_switchdev.o cpsw_new.o davinci_cpdma.o cpsw_ale.o cpsw_sl.o cpsw_priv.o cpsw_ethtool.o
+obj-$(CONFIG_TI_CPSW) += ti_cpsw.o ti-cpsw-common.o ti-cpsw-priv.o ti-cpsw-ale.o ti-cpsw-sl.o
+ti_cpsw-y := cpsw.o
+obj-$(CONFIG_TI_CPSW_SWITCHDEV) += ti_cpsw_new.o ti-cpsw-common.o ti-cpsw-priv.o ti-cpsw-ale.o ti-cpsw-sl.o
+ti_cpsw_new-y := cpsw_switchdev.o cpsw_new.o
-obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o
-keystone_netcp-y := netcp_core.o cpsw_ale.o
-obj-$(CONFIG_TI_KEYSTONE_NETCP_ETHSS) += keystone_netcp_ethss.o
-keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o cpsw_ale.o
+obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o ti-cpsw-ale.o
+keystone_netcp-y := netcp_core.o
+obj-$(CONFIG_TI_KEYSTONE_NETCP_ETHSS) += keystone_netcp_ethss.o ti-cpsw-ale.o
+keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o
obj-$(CONFIG_TI_K3_CPPI_DESC_POOL) += k3-cppi-desc-pool.o
-obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o
-ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o
+obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o ti-cpsw-sl.o ti-cpsw-ale.o
+ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o am65-cpsw-ethtool.o
ti-am65-cpsw-nuss-$(CONFIG_TI_AM65_CPSW_QOS) += am65-cpsw-qos.o
ti-am65-cpsw-nuss-$(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV) += am65-cpsw-switchdev.o
obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index be7b69319221..e202bba49480 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -493,6 +493,7 @@ int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
}
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_flush_multicast);
static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
int flags, u16 vid)
@@ -530,6 +531,7 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
cpsw_ale_write(ale, idx, ale_entry);
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_add_ucast);
int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
int flags, u16 vid)
@@ -545,6 +547,7 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
cpsw_ale_write(ale, idx, ale_entry);
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_del_ucast);
int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
int flags, u16 vid, int mcast_state)
@@ -578,6 +581,7 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
cpsw_ale_write(ale, idx, ale_entry);
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_add_mcast);
int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
int flags, u16 vid)
@@ -607,6 +611,7 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
cpsw_ale_write(ale, idx, ale_entry);
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_del_mcast);
/* ALE NetCP NU switch specific vlan functions */
static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
@@ -676,6 +681,7 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,
cpsw_ale_write(ale, idx, ale_entry);
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_add_vlan);
static void cpsw_ale_vlan_del_modify_int(struct cpsw_ale *ale, u32 *ale_entry,
u16 vid, int port_mask)
@@ -733,6 +739,7 @@ int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask)
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_vlan_del_modify);
int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
{
@@ -767,6 +774,7 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_del_vlan);
int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
int untag_mask, int reg_mask, int unreg_mask)
@@ -806,6 +814,7 @@ int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
return ret;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_vlan_add_modify);
void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
bool add)
@@ -833,6 +842,7 @@ void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
cpsw_ale_write(ale, idx, ale_entry);
}
}
+EXPORT_SYMBOL_GPL(cpsw_ale_set_unreg_mcast);
static void cpsw_ale_vlan_set_unreg_mcast(struct cpsw_ale *ale, u32 *ale_entry,
int allmulti)
@@ -898,6 +908,7 @@ void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)
cpsw_ale_write(ale, idx, ale_entry);
}
}
+EXPORT_SYMBOL_GPL(cpsw_ale_set_allmulti);
struct ale_control_info {
const char *name;
@@ -1155,6 +1166,7 @@ int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_control_set);
int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
{
@@ -1178,6 +1190,7 @@ int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
tmp = readl_relaxed(ale->params.ale_regs + offset) >> shift;
return tmp & BITMASK(info->bits);
}
+EXPORT_SYMBOL_GPL(cpsw_ale_control_get);
int cpsw_ale_rx_ratelimit_mc(struct cpsw_ale *ale, int port, unsigned int ratelimit_pps)
@@ -1200,6 +1213,7 @@ int cpsw_ale_rx_ratelimit_mc(struct cpsw_ale *ale, int port, unsigned int rateli
port, val * ALE_RATE_LIMIT_MIN_PPS);
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_rx_ratelimit_mc);
int cpsw_ale_rx_ratelimit_bc(struct cpsw_ale *ale, int port, unsigned int ratelimit_pps)
@@ -1222,6 +1236,7 @@ int cpsw_ale_rx_ratelimit_bc(struct cpsw_ale *ale, int port, unsigned int rateli
port, val * ALE_RATE_LIMIT_MIN_PPS);
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_rx_ratelimit_bc);
static void cpsw_ale_timer(struct timer_list *t)
{
@@ -1311,6 +1326,7 @@ void cpsw_ale_start(struct cpsw_ale *ale)
cpsw_ale_aging_start(ale);
}
+EXPORT_SYMBOL_GPL(cpsw_ale_start);
void cpsw_ale_stop(struct cpsw_ale *ale)
{
@@ -1318,6 +1334,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale)
cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
}
+EXPORT_SYMBOL_GPL(cpsw_ale_stop);
static const struct reg_field ale_fields_cpsw[] = {
/* CPSW_ALE_IDVER_REG */
@@ -1618,6 +1635,7 @@ struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
return ale;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_create);
void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
{
@@ -1628,6 +1646,7 @@ void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
data += ALE_ENTRY_WORDS;
}
}
+EXPORT_SYMBOL_GPL(cpsw_ale_dump);
void cpsw_ale_restore(struct cpsw_ale *ale, u32 *data)
{
@@ -1638,11 +1657,13 @@ void cpsw_ale_restore(struct cpsw_ale *ale, u32 *data)
data += ALE_ENTRY_WORDS;
}
}
+EXPORT_SYMBOL_GPL(cpsw_ale_restore);
u32 cpsw_ale_get_num_entries(struct cpsw_ale *ale)
{
return ale ? ale->params.ale_entries : 0;
}
+EXPORT_SYMBOL_GPL(cpsw_ale_get_num_entries);
/* Reads the specified policer index into ALE POLICER registers */
static void cpsw_ale_policer_read_idx(struct cpsw_ale *ale, u32 idx)
@@ -1745,3 +1766,7 @@ void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch)
1);
}
}
+EXPORT_SYMBOL_GPL(cpsw_ale_classifier_setup_default);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TI N-Port Ethernet Switch Address Lookup Engine");
diff --git a/drivers/net/ethernet/ti/cpsw_ethtool.c b/drivers/net/ethernet/ti/cpsw_ethtool.c
index a43f75ee269e..3f2682c461f9 100644
--- a/drivers/net/ethernet/ti/cpsw_ethtool.c
+++ b/drivers/net/ethernet/ti/cpsw_ethtool.c
@@ -144,6 +144,7 @@ u32 cpsw_get_msglevel(struct net_device *ndev)
return priv->msg_enable;
}
+EXPORT_SYMBOL_GPL(cpsw_get_msglevel);
void cpsw_set_msglevel(struct net_device *ndev, u32 value)
{
@@ -151,6 +152,7 @@ void cpsw_set_msglevel(struct net_device *ndev, u32 value)
priv->msg_enable = value;
}
+EXPORT_SYMBOL_GPL(cpsw_set_msglevel);
int cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
struct kernel_ethtool_coalesce *kernel_coal,
@@ -161,6 +163,7 @@ int cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
coal->rx_coalesce_usecs = cpsw->coal_intvl;
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_get_coalesce);
int cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
struct kernel_ethtool_coalesce *kernel_coal,
@@ -220,6 +223,7 @@ int cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_set_coalesce);
int cpsw_get_sset_count(struct net_device *ndev, int sset)
{
@@ -234,6 +238,7 @@ int cpsw_get_sset_count(struct net_device *ndev, int sset)
return -EOPNOTSUPP;
}
}
+EXPORT_SYMBOL_GPL(cpsw_get_sset_count);
static void cpsw_add_ch_strings(u8 **p, int ch_num, int rx_dir)
{
@@ -271,6 +276,7 @@ void cpsw_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
break;
}
}
+EXPORT_SYMBOL_GPL(cpsw_get_strings);
void cpsw_get_ethtool_stats(struct net_device *ndev,
struct ethtool_stats *stats, u64 *data)
@@ -303,6 +309,7 @@ void cpsw_get_ethtool_stats(struct net_device *ndev,
}
}
}
+EXPORT_SYMBOL_GPL(cpsw_get_ethtool_stats);
void cpsw_get_pauseparam(struct net_device *ndev,
struct ethtool_pauseparam *pause)
@@ -313,6 +320,7 @@ void cpsw_get_pauseparam(struct net_device *ndev,
pause->rx_pause = priv->rx_pause ? true : false;
pause->tx_pause = priv->tx_pause ? true : false;
}
+EXPORT_SYMBOL_GPL(cpsw_get_pauseparam);
void cpsw_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
{
@@ -326,6 +334,7 @@ void cpsw_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
if (cpsw->slaves[slave_no].phy)
phy_ethtool_get_wol(cpsw->slaves[slave_no].phy, wol);
}
+EXPORT_SYMBOL_GPL(cpsw_get_wol);
int cpsw_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
{
@@ -338,6 +347,7 @@ int cpsw_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
else
return -EOPNOTSUPP;
}
+EXPORT_SYMBOL_GPL(cpsw_set_wol);
int cpsw_get_regs_len(struct net_device *ndev)
{
@@ -346,6 +356,7 @@ int cpsw_get_regs_len(struct net_device *ndev)
return cpsw_ale_get_num_entries(cpsw->ale) *
ALE_ENTRY_WORDS * sizeof(u32);
}
+EXPORT_SYMBOL_GPL(cpsw_get_regs_len);
void cpsw_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *p)
{
@@ -357,6 +368,7 @@ void cpsw_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *p)
cpsw_ale_dump(cpsw->ale, reg);
}
+EXPORT_SYMBOL_GPL(cpsw_get_regs);
int cpsw_ethtool_op_begin(struct net_device *ndev)
{
@@ -370,6 +382,7 @@ int cpsw_ethtool_op_begin(struct net_device *ndev)
return ret;
}
+EXPORT_SYMBOL_GPL(cpsw_ethtool_op_begin);
void cpsw_ethtool_op_complete(struct net_device *ndev)
{
@@ -377,6 +390,7 @@ void cpsw_ethtool_op_complete(struct net_device *ndev)
pm_runtime_put(priv->cpsw->dev);
}
+EXPORT_SYMBOL_GPL(cpsw_ethtool_op_complete);
void cpsw_get_channels(struct net_device *ndev, struct ethtool_channels *ch)
{
@@ -391,6 +405,7 @@ void cpsw_get_channels(struct net_device *ndev, struct ethtool_channels *ch)
ch->tx_count = cpsw->tx_ch_num;
ch->combined_count = 0;
}
+EXPORT_SYMBOL_GPL(cpsw_get_channels);
int cpsw_get_link_ksettings(struct net_device *ndev,
struct ethtool_link_ksettings *ecmd)
@@ -405,6 +420,7 @@ int cpsw_get_link_ksettings(struct net_device *ndev,
phy_ethtool_ksettings_get(cpsw->slaves[slave_no].phy, ecmd);
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_get_link_ksettings);
int cpsw_set_link_ksettings(struct net_device *ndev,
const struct ethtool_link_ksettings *ecmd)
@@ -418,6 +434,7 @@ int cpsw_set_link_ksettings(struct net_device *ndev,
return phy_ethtool_ksettings_set(cpsw->slaves[slave_no].phy, ecmd);
}
+EXPORT_SYMBOL_GPL(cpsw_set_link_ksettings);
int cpsw_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
{
@@ -430,6 +447,7 @@ int cpsw_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
else
return -EOPNOTSUPP;
}
+EXPORT_SYMBOL_GPL(cpsw_get_eee);
int cpsw_nway_reset(struct net_device *ndev)
{
@@ -442,6 +460,7 @@ int cpsw_nway_reset(struct net_device *ndev)
else
return -EOPNOTSUPP;
}
+EXPORT_SYMBOL_GPL(cpsw_nway_reset);
static void cpsw_suspend_data_pass(struct net_device *ndev)
{
@@ -639,6 +658,7 @@ int cpsw_set_channels_common(struct net_device *ndev,
cpsw_fail(cpsw);
return ret;
}
+EXPORT_SYMBOL_GPL(cpsw_set_channels_common);
void cpsw_get_ringparam(struct net_device *ndev,
struct ethtool_ringparam *ering,
@@ -654,6 +674,7 @@ void cpsw_get_ringparam(struct net_device *ndev,
ering->rx_max_pending = cpsw->descs_pool_size - CPSW_MAX_QUEUES;
ering->rx_pending = cpdma_get_num_rx_descs(cpsw->dma);
}
+EXPORT_SYMBOL_GPL(cpsw_get_ringparam);
int cpsw_set_ringparam(struct net_device *ndev,
struct ethtool_ringparam *ering,
@@ -700,6 +721,7 @@ int cpsw_set_ringparam(struct net_device *ndev,
cpsw_fail(cpsw);
return ret;
}
+EXPORT_SYMBOL_GPL(cpsw_set_ringparam);
#if IS_ENABLED(CONFIG_TI_CPTS)
int cpsw_get_ts_info(struct net_device *ndev, struct kernel_ethtool_ts_info *info)
@@ -720,6 +742,7 @@ int cpsw_get_ts_info(struct net_device *ndev, struct kernel_ethtool_ts_info *inf
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_get_ts_info);
#else
int cpsw_get_ts_info(struct net_device *ndev, struct kernel_ethtool_ts_info *info)
{
@@ -729,4 +752,5 @@ int cpsw_get_ts_info(struct net_device *ndev, struct kernel_ethtool_ts_info *inf
info->rx_filters = 0;
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_get_ts_info);
#endif
diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c
index c6eb6b785b0b..1f6f374551cb 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.c
+++ b/drivers/net/ethernet/ti/cpsw_priv.c
@@ -32,6 +32,7 @@
#define CPTS_N_ETX_TS 4
int (*cpsw_slave_index)(struct cpsw_common *cpsw, struct cpsw_priv *priv);
+EXPORT_SYMBOL_GPL(cpsw_slave_index);
void cpsw_intr_enable(struct cpsw_common *cpsw)
{
@@ -40,6 +41,7 @@ void cpsw_intr_enable(struct cpsw_common *cpsw)
cpdma_ctlr_int_ctrl(cpsw->dma, true);
}
+EXPORT_SYMBOL_GPL(cpsw_intr_enable);
void cpsw_intr_disable(struct cpsw_common *cpsw)
{
@@ -48,6 +50,7 @@ void cpsw_intr_disable(struct cpsw_common *cpsw)
cpdma_ctlr_int_ctrl(cpsw->dma, false);
}
+EXPORT_SYMBOL_GPL(cpsw_intr_disable);
void cpsw_tx_handler(void *token, int len, int status)
{
@@ -82,6 +85,7 @@ void cpsw_tx_handler(void *token, int len, int status)
ndev->stats.tx_packets++;
ndev->stats.tx_bytes += len;
}
+EXPORT_SYMBOL_GPL(cpsw_tx_handler);
irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
{
@@ -98,6 +102,7 @@ irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
napi_schedule(&cpsw->napi_tx);
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(cpsw_tx_interrupt);
irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
{
@@ -114,6 +119,7 @@ irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
napi_schedule(&cpsw->napi_rx);
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(cpsw_rx_interrupt);
irqreturn_t cpsw_misc_interrupt(int irq, void *dev_id)
{
@@ -126,6 +132,7 @@ irqreturn_t cpsw_misc_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(cpsw_misc_interrupt);
int cpsw_tx_mq_poll(struct napi_struct *napi_tx, int budget)
{
@@ -158,6 +165,7 @@ int cpsw_tx_mq_poll(struct napi_struct *napi_tx, int budget)
return num_tx;
}
+EXPORT_SYMBOL_GPL(cpsw_tx_mq_poll);
int cpsw_tx_poll(struct napi_struct *napi_tx, int budget)
{
@@ -176,6 +184,7 @@ int cpsw_tx_poll(struct napi_struct *napi_tx, int budget)
return num_tx;
}
+EXPORT_SYMBOL_GPL(cpsw_tx_poll);
int cpsw_rx_mq_poll(struct napi_struct *napi_rx, int budget)
{
@@ -208,6 +217,7 @@ int cpsw_rx_mq_poll(struct napi_struct *napi_rx, int budget)
return num_rx;
}
+EXPORT_SYMBOL_GPL(cpsw_rx_mq_poll);
int cpsw_rx_poll(struct napi_struct *napi_rx, int budget)
{
@@ -226,6 +236,7 @@ int cpsw_rx_poll(struct napi_struct *napi_rx, int budget)
return num_rx;
}
+EXPORT_SYMBOL_GPL(cpsw_rx_poll);
void cpsw_rx_vlan_encap(struct sk_buff *skb)
{
@@ -268,12 +279,14 @@ void cpsw_rx_vlan_encap(struct sk_buff *skb)
skb_pull(skb, VLAN_HLEN);
}
}
+EXPORT_SYMBOL_GPL(cpsw_rx_vlan_encap);
void cpsw_set_slave_mac(struct cpsw_slave *slave, struct cpsw_priv *priv)
{
slave_write(slave, mac_hi(priv->mac_addr), SA_HI);
slave_write(slave, mac_lo(priv->mac_addr), SA_LO);
}
+EXPORT_SYMBOL_GPL(cpsw_set_slave_mac);
void cpsw_soft_reset(const char *module, void __iomem *reg)
{
@@ -286,6 +299,7 @@ void cpsw_soft_reset(const char *module, void __iomem *reg)
WARN(readl_relaxed(reg) & 1, "failed to soft-reset %s\n", module);
}
+EXPORT_SYMBOL_GPL(cpsw_soft_reset);
void cpsw_ndo_tx_timeout(struct net_device *ndev, unsigned int txqueue)
{
@@ -305,6 +319,7 @@ void cpsw_ndo_tx_timeout(struct net_device *ndev, unsigned int txqueue)
netif_trans_update(ndev);
netif_tx_wake_all_queues(ndev);
}
+EXPORT_SYMBOL_GPL(cpsw_ndo_tx_timeout);
static int cpsw_get_common_speed(struct cpsw_common *cpsw)
{
@@ -343,6 +358,7 @@ int cpsw_need_resplit(struct cpsw_common *cpsw)
return 1;
}
+EXPORT_SYMBOL_GPL(cpsw_need_resplit);
void cpsw_split_res(struct cpsw_common *cpsw)
{
@@ -428,6 +444,7 @@ void cpsw_split_res(struct cpsw_common *cpsw)
if (budget)
cpsw->rxv[0].budget += budget;
}
+EXPORT_SYMBOL_GPL(cpsw_split_res);
int cpsw_init_common(struct cpsw_common *cpsw, void __iomem *ss_regs,
int ale_ageout, phys_addr_t desc_mem_phys,
@@ -548,6 +565,7 @@ int cpsw_init_common(struct cpsw_common *cpsw, void __iomem *ss_regs,
return ret;
}
+EXPORT_SYMBOL_GPL(cpsw_init_common);
#if IS_ENABLED(CONFIG_TI_CPTS)
@@ -678,6 +696,7 @@ int cpsw_hwtstamp_set(struct net_device *dev,
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_hwtstamp_set);
int cpsw_hwtstamp_get(struct net_device *dev,
struct kernel_hwtstamp_config *cfg)
@@ -695,12 +714,14 @@ int cpsw_hwtstamp_get(struct net_device *dev,
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_hwtstamp_get);
#else
int cpsw_hwtstamp_get(struct net_device *dev,
struct kernel_hwtstamp_config *cfg)
{
return -EOPNOTSUPP;
}
+EXPORT_SYMBOL_GPL(cpsw_hwtstamp_set);
int cpsw_hwtstamp_set(struct net_device *dev,
struct kernel_hwtstamp_config *cfg,
@@ -708,6 +729,7 @@ int cpsw_hwtstamp_set(struct net_device *dev,
{
return -EOPNOTSUPP;
}
+EXPORT_SYMBOL_GPL(cpsw_hwtstamp_get);
#endif /*CONFIG_TI_CPTS*/
int cpsw_ndo_set_tx_maxrate(struct net_device *ndev, int queue, u32 rate)
@@ -758,6 +780,7 @@ int cpsw_ndo_set_tx_maxrate(struct net_device *ndev, int queue, u32 rate)
cpsw_split_res(cpsw);
return ret;
}
+EXPORT_SYMBOL_GPL(cpsw_ndo_set_tx_maxrate);
static int cpsw_tc_to_fifo(int tc, int num_tc)
{
@@ -782,6 +805,7 @@ bool cpsw_shp_is_off(struct cpsw_priv *priv)
return !val;
}
+EXPORT_SYMBOL_GPL(cpsw_shp_is_off);
static void cpsw_fifo_shp_on(struct cpsw_priv *priv, int fifo, int on)
{
@@ -1043,6 +1067,7 @@ int cpsw_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,
return -EOPNOTSUPP;
}
}
+EXPORT_SYMBOL_GPL(cpsw_ndo_setup_tc);
void cpsw_cbs_resume(struct cpsw_slave *slave, struct cpsw_priv *priv)
{
@@ -1056,6 +1081,7 @@ void cpsw_cbs_resume(struct cpsw_slave *slave, struct cpsw_priv *priv)
cpsw_set_fifo_rlimit(priv, fifo, bw);
}
}
+EXPORT_SYMBOL_GPL(cpsw_cbs_resume);
void cpsw_mqprio_resume(struct cpsw_slave *slave, struct cpsw_priv *priv)
{
@@ -1078,6 +1104,7 @@ void cpsw_mqprio_resume(struct cpsw_slave *slave, struct cpsw_priv *priv)
slave_write(slave, tx_prio_map, tx_prio_rg);
}
+EXPORT_SYMBOL_GPL(cpsw_mqprio_resume);
int cpsw_fill_rx_channels(struct cpsw_priv *priv)
{
@@ -1123,6 +1150,7 @@ int cpsw_fill_rx_channels(struct cpsw_priv *priv)
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_fill_rx_channels);
static struct page_pool *cpsw_create_page_pool(struct cpsw_common *cpsw,
int size)
@@ -1208,6 +1236,7 @@ void cpsw_destroy_xdp_rxqs(struct cpsw_common *cpsw)
cpsw->page_pool[ch] = NULL;
}
}
+EXPORT_SYMBOL_GPL(cpsw_destroy_xdp_rxqs);
int cpsw_create_xdp_rxqs(struct cpsw_common *cpsw)
{
@@ -1240,6 +1269,7 @@ int cpsw_create_xdp_rxqs(struct cpsw_common *cpsw)
return ret;
}
+EXPORT_SYMBOL_GPL(cpsw_create_xdp_rxqs);
static int cpsw_xdp_prog_setup(struct cpsw_priv *priv, struct netdev_bpf *bpf)
{
@@ -1267,6 +1297,7 @@ int cpsw_ndo_bpf(struct net_device *ndev, struct netdev_bpf *bpf)
return -EINVAL;
}
}
+EXPORT_SYMBOL_GPL(cpsw_ndo_bpf);
int cpsw_xdp_tx_frame(struct cpsw_priv *priv, struct xdp_frame *xdpf,
struct page *page, int port)
@@ -1300,6 +1331,7 @@ int cpsw_xdp_tx_frame(struct cpsw_priv *priv, struct xdp_frame *xdpf,
return ret;
}
+EXPORT_SYMBOL_GPL(cpsw_xdp_tx_frame);
int cpsw_run_xdp(struct cpsw_priv *priv, int ch, struct xdp_buff *xdp,
struct page *page, int port, int *len)
@@ -1362,6 +1394,7 @@ int cpsw_run_xdp(struct cpsw_priv *priv, int ch, struct xdp_buff *xdp,
page_pool_recycle_direct(cpsw->page_pool[ch], page);
return ret;
}
+EXPORT_SYMBOL_GPL(cpsw_run_xdp);
static int cpsw_qos_clsflower_add_policer(struct cpsw_priv *priv,
struct netlink_ext_ack *extack,
@@ -1564,3 +1597,7 @@ void cpsw_qos_clsflower_resume(struct cpsw_priv *priv)
cpsw_ale_rx_ratelimit_mc(priv->cpsw->ale, port_id,
priv->ale_mc_ratelimit.rate_packet_ps);
}
+EXPORT_SYMBOL_GPL(cpsw_qos_clsflower_resume);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TI CPSW Ethernet Switch Driver");
diff --git a/drivers/net/ethernet/ti/cpsw_sl.c b/drivers/net/ethernet/ti/cpsw_sl.c
index 0c7531cb0f39..761719a348fa 100644
--- a/drivers/net/ethernet/ti/cpsw_sl.c
+++ b/drivers/net/ethernet/ti/cpsw_sl.c
@@ -200,6 +200,7 @@ u32 cpsw_sl_reg_read(struct cpsw_sl *sl, enum cpsw_sl_regs reg)
dev_dbg(sl->dev, "cpsw_sl: reg: %04X r 0x%08X\n", sl->regs[reg], val);
return val;
}
+EXPORT_SYMBOL_GPL(cpsw_sl_reg_read);
void cpsw_sl_reg_write(struct cpsw_sl *sl, enum cpsw_sl_regs reg, u32 val)
{
@@ -212,6 +213,7 @@ void cpsw_sl_reg_write(struct cpsw_sl *sl, enum cpsw_sl_regs reg, u32 val)
dev_dbg(sl->dev, "cpsw_sl: reg: %04X w 0x%08X\n", sl->regs[reg], val);
writel(val, sl->sl_base + sl->regs[reg]);
}
+EXPORT_SYMBOL_GPL(cpsw_sl_reg_write);
static const struct cpsw_sl_dev_id *cpsw_sl_match_id(
const struct cpsw_sl_dev_id *id,
@@ -252,6 +254,7 @@ struct cpsw_sl *cpsw_sl_get(const char *device_id, struct device *dev,
return sl;
}
+EXPORT_SYMBOL_GPL(cpsw_sl_get);
void cpsw_sl_reset(struct cpsw_sl *sl, unsigned long tmo)
{
@@ -270,6 +273,7 @@ void cpsw_sl_reset(struct cpsw_sl *sl, unsigned long tmo)
if (cpsw_sl_reg_read(sl, CPSW_SL_SOFT_RESET) & CPSW_SL_SOFT_RESET_BIT)
dev_err(sl->dev, "cpsw_sl failed to soft-reset.\n");
}
+EXPORT_SYMBOL_GPL(cpsw_sl_reset);
u32 cpsw_sl_ctl_set(struct cpsw_sl *sl, u32 ctl_funcs)
{
@@ -287,6 +291,7 @@ u32 cpsw_sl_ctl_set(struct cpsw_sl *sl, u32 ctl_funcs)
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_sl_ctl_set);
u32 cpsw_sl_ctl_clr(struct cpsw_sl *sl, u32 ctl_funcs)
{
@@ -304,11 +309,13 @@ u32 cpsw_sl_ctl_clr(struct cpsw_sl *sl, u32 ctl_funcs)
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_sl_ctl_clr);
void cpsw_sl_ctl_reset(struct cpsw_sl *sl)
{
cpsw_sl_reg_write(sl, CPSW_SL_MACCONTROL, 0);
}
+EXPORT_SYMBOL_GPL(cpsw_sl_ctl_reset);
int cpsw_sl_wait_for_idle(struct cpsw_sl *sl, unsigned long tmo)
{
@@ -326,3 +333,7 @@ int cpsw_sl_wait_for_idle(struct cpsw_sl *sl, unsigned long tmo)
return 0;
}
+EXPORT_SYMBOL_GPL(cpsw_sl_wait_for_idle);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TI Ethernet Switch media-access-controller (MAC) submodule");
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index d2eab5cd1e0c..41e89a19be53 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -531,6 +531,7 @@ struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
ctlr->num_chan = CPDMA_MAX_CHANNELS;
return ctlr;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_create);
int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
{
@@ -591,6 +592,7 @@ int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
spin_unlock_irqrestore(&ctlr->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_start);
int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
{
@@ -623,6 +625,7 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
spin_unlock_irqrestore(&ctlr->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_stop);
int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
{
@@ -640,6 +643,7 @@ int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
cpdma_desc_pool_destroy(ctlr);
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_destroy);
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
{
@@ -660,21 +664,25 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
spin_unlock_irqrestore(&ctlr->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_int_ctrl);
void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value)
{
dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, value);
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_eoi);
u32 cpdma_ctrl_rxchs_state(struct cpdma_ctlr *ctlr)
{
return dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED);
}
+EXPORT_SYMBOL_GPL(cpdma_ctrl_rxchs_state);
u32 cpdma_ctrl_txchs_state(struct cpdma_ctlr *ctlr)
{
return dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED);
}
+EXPORT_SYMBOL_GPL(cpdma_ctrl_txchs_state);
static void cpdma_chan_set_descs(struct cpdma_ctlr *ctlr,
int rx, int desc_num,
@@ -802,6 +810,7 @@ int cpdma_chan_set_weight(struct cpdma_chan *ch, int weight)
spin_unlock_irqrestore(&ctlr->lock, flags);
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_set_weight);
/* cpdma_chan_get_min_rate - get minimum allowed rate for channel
* Should be called before cpdma_chan_set_rate.
@@ -816,6 +825,7 @@ u32 cpdma_chan_get_min_rate(struct cpdma_ctlr *ctlr)
return DIV_ROUND_UP(divident, divisor);
}
+EXPORT_SYMBOL_GPL(cpdma_chan_get_min_rate);
/* cpdma_chan_set_rate - limits bandwidth for transmit channel.
* The bandwidth * limited channels have to be in order beginning from lowest.
@@ -860,6 +870,7 @@ int cpdma_chan_set_rate(struct cpdma_chan *ch, u32 rate)
spin_unlock_irqrestore(&ctlr->lock, flags);
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_set_rate);
u32 cpdma_chan_get_rate(struct cpdma_chan *ch)
{
@@ -872,6 +883,7 @@ u32 cpdma_chan_get_rate(struct cpdma_chan *ch)
return rate;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_get_rate);
struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
cpdma_handler_fn handler, int rx_type)
@@ -931,6 +943,7 @@ struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
spin_unlock_irqrestore(&ctlr->lock, flags);
return chan;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_create);
int cpdma_chan_get_rx_buf_num(struct cpdma_chan *chan)
{
@@ -943,6 +956,7 @@ int cpdma_chan_get_rx_buf_num(struct cpdma_chan *chan)
return desc_num;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_get_rx_buf_num);
int cpdma_chan_destroy(struct cpdma_chan *chan)
{
@@ -964,6 +978,7 @@ int cpdma_chan_destroy(struct cpdma_chan *chan)
spin_unlock_irqrestore(&ctlr->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_destroy);
int cpdma_chan_get_stats(struct cpdma_chan *chan,
struct cpdma_chan_stats *stats)
@@ -976,6 +991,7 @@ int cpdma_chan_get_stats(struct cpdma_chan *chan,
spin_unlock_irqrestore(&chan->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_get_stats);
static void __cpdma_chan_submit(struct cpdma_chan *chan,
struct cpdma_desc __iomem *desc)
@@ -1100,6 +1116,7 @@ int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,
spin_unlock_irqrestore(&chan->lock, flags);
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_idle_submit);
int cpdma_chan_idle_submit_mapped(struct cpdma_chan *chan, void *token,
dma_addr_t data, int len, int directed)
@@ -1125,6 +1142,7 @@ int cpdma_chan_idle_submit_mapped(struct cpdma_chan *chan, void *token,
spin_unlock_irqrestore(&chan->lock, flags);
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_idle_submit_mapped);
int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
int len, int directed)
@@ -1150,6 +1168,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
spin_unlock_irqrestore(&chan->lock, flags);
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_submit);
int cpdma_chan_submit_mapped(struct cpdma_chan *chan, void *token,
dma_addr_t data, int len, int directed)
@@ -1175,6 +1194,7 @@ int cpdma_chan_submit_mapped(struct cpdma_chan *chan, void *token,
spin_unlock_irqrestore(&chan->lock, flags);
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_submit_mapped);
bool cpdma_check_free_tx_desc(struct cpdma_chan *chan)
{
@@ -1189,6 +1209,7 @@ bool cpdma_check_free_tx_desc(struct cpdma_chan *chan)
spin_unlock_irqrestore(&chan->lock, flags);
return free_tx_desc;
}
+EXPORT_SYMBOL_GPL(cpdma_check_free_tx_desc);
static void __cpdma_chan_free(struct cpdma_chan *chan,
struct cpdma_desc __iomem *desc,
@@ -1289,6 +1310,7 @@ int cpdma_chan_process(struct cpdma_chan *chan, int quota)
}
return used;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_process);
int cpdma_chan_start(struct cpdma_chan *chan)
{
@@ -1308,6 +1330,7 @@ int cpdma_chan_start(struct cpdma_chan *chan)
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_start);
int cpdma_chan_stop(struct cpdma_chan *chan)
{
@@ -1370,6 +1393,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
spin_unlock_irqrestore(&chan->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_stop);
int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
{
@@ -1416,11 +1440,13 @@ int cpdma_get_num_rx_descs(struct cpdma_ctlr *ctlr)
{
return ctlr->num_rx_desc;
}
+EXPORT_SYMBOL_GPL(cpdma_get_num_rx_descs);
int cpdma_get_num_tx_descs(struct cpdma_ctlr *ctlr)
{
return ctlr->num_tx_desc;
}
+EXPORT_SYMBOL_GPL(cpdma_get_num_tx_descs);
int cpdma_set_num_rx_descs(struct cpdma_ctlr *ctlr, int num_rx_desc)
{
@@ -1442,3 +1468,4 @@ int cpdma_set_num_rx_descs(struct cpdma_ctlr *ctlr, int num_rx_desc)
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_set_num_rx_descs);
--
2.39.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox