Netdev List
 help / color / mirror / Atom feed
* [PATCH 0/3] usb: Use %pe to print error pointers
From: Subasri S @ 2026-07-19 12:55 UTC (permalink / raw)
  To: Peter Chen, Greg Kroah-Hartman, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Duncan Sands,
	Chas Williams, Minas Harutyunyan, Hans de Goede, Heikki Krogerus,
	Badhri Jagan Sridharan
  Cc: linux-usb, imx, linux-arm-kernel, linux-kernel, linux-atm-general,
	netdev, Subasri S

This patchset replaces PTR_ERR() in format strings with 
%pe format specifier across the USB subsystem. %pe prints 
symbolic error names (e.g., -ENOMEM) instead of 
raw numbers (e.g., -12), making error logs more readable. 
These patches fix coccinelle reported warning: "Consider 
using %pe to print PTR_ERR()" in usb subsystem.

The patches are grouped by subsystem:
  1/3 - chipidea
  2/3 - miscellaneous USB drivers
  3/3 - typec

All patches are compile-tested on x86_64. Please let me know if 
any more testing is needed for any patch. 

Signed-off-by: Subasri S <subasris1210@gmail.com>
---
Subasri S (3):
      usb: chipidea: Use %pe to print error pointers
      usb: misc: Use %pe to print error pointers
      usb: typec: Use %pe to print error pointers

 drivers/usb/atm/usbatm.c               |  4 ++--
 drivers/usb/chipidea/ci_hdrc_imx.c     | 12 ++++++------
 drivers/usb/chipidea/core.c            |  4 ++--
 drivers/usb/core/hub.c                 |  4 ++--
 drivers/usb/dwc2/pci.c                 |  4 ++--
 drivers/usb/gadget/function/u_serial.c |  4 ++--
 drivers/usb/misc/usb3503.c             |  4 ++--
 drivers/usb/typec/mux/pi3usb30532.c    |  8 ++++----
 drivers/usb/typec/tcpm/tcpm.c          |  2 +-
 drivers/usb/typec/wusb3801.c           |  4 ++--
 10 files changed, 25 insertions(+), 25 deletions(-)
---
base-commit: a13c140cc289c0b7b3770bce5b3ad42ab35074aa
change-id: 20260718-usb-ptr_err_patchset-7c5d1547bee7

Best regards,
-- 
Subasri S <subasris1210@gmail.com>


^ permalink raw reply

* Re: [PATCH net] ipv6: Change allocation flags to match rcu_read_lock section requirements
From: Ido Schimmel @ 2026-07-19 12:55 UTC (permalink / raw)
  To: Nikola Z. Ivanov
  Cc: dsahern, davem, edumazet, kuba, pabeni, horms, kuniyu, netdev,
	linux-kernel, syzbot+84d4a405ed798b40c96d
In-Reply-To: <20260719105759.558050-1-zlatistiv@gmail.com>

On Sun, Jul 19, 2026 at 01:57:59PM +0300, Nikola Z. Ivanov wrote:
> Since the call to __ip6_del_rt_siblings has been converted under
> rcu read lock and it only has one call point
> we should no longer block or yield.
> 
> Our stack trace from the syzbot reproducer looks as follows:
> 
> __ip6_del_rt_siblings
>   rtnl_notify (Here we pass gfp_any() -> GFP_KERNEL)
>     nlmsg_notify
>       nlmsg_multicast
>         nlmsg_multicast_filtered
>           netlink_broadcast_filtered (GFP_KERNEL passed from earlier)
> 
> netlink_broadcast_filtered can yield if GFP_KERNEL
> is passed, which we do not want to happen.
> 
> Fix this by changing the allocation flag of rtnl_notify.
> 
> Also change the flag passed to nlmsg_new. Even though it
> is not related to the syzbot generated bug it still falls
> under the same requirements.

I believe that the nlmsg_new() change is a no-op given that gfp_any()
evaluates to GFP_ATOMIC under spin_lock_bh(), but it makes
__ip6_del_rt_siblings() consistent with inet6_rt_notify() which already
uses GFP_ATOMIC for both nlmsg_new() and rtnl_notify().

> 
> Reported-by: syzbot+84d4a405ed798b40c96d@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=84d4a405ed798b40c96d
> Fixes: bd11ff421d36 ("ipv6: Get rid of RTNL for SIOCDELRT and RTM_DELROUTE.")
> Signed-off-by: Nikola Z. Ivanov <zlatistiv@gmail.com>

Reviewed-by: Ido Schimmel <idosch@nvidia.com>

^ permalink raw reply

* Re: [PATCH net v2] net: erspan: set lltx to avoid sch_direct_xmit deadlock
From: Zhou, Yun @ 2026-07-19 12:40 UTC (permalink / raw)
  To: idosch
  Cc: netdev, linux-kernel, dsahern, davem, edumazet, kuba, pabeni,
	horms, yun.zhou
In-Reply-To: <20260713151435.1815104-1-yun.zhou@windriver.com>

Hi Ido,

Could you please help review this patch when you have a moment?

Thanks,
Yun

On 7/13/2026 11:14 PM, Yun Zhou wrote:
> erspan_xmit() re-enters the network stack via ip_tunnel_xmit(), causing
> nested acquisition of _xmit_lock on the underlay device while already
> holding the ERSPAN device's _xmit_lock. Both are ARPHRD_ETHER and share
> the same lockdep class, creating an ABBA deadlock:
> 
>    sch_direct_xmit [lock erspan] -> erspan_xmit -> ip_tunnel_xmit ->
>    ip_output -> __dev_queue_xmit -> sch_direct_xmit [lock underlay]
> 
> Set dev->lltx = true so HARD_TX_LOCK() skips the spinlock for ERSPAN.
> This is safe as erspan_xmit() has no shared mutable state: o_seqno is
> atomic, stats use atomic_long_inc, and dst_cache is per-CPU. GRETAP,
> the sibling device with identical xmit structure, already sets lltx.
> 
> Closes: https://syzkaller.appspot.com/bug?extid=9bda1b9fbb7fbdf9b62b
> Reported-by: syzbot+9bda1b9fbb7fbdf9b62b@syzkaller.appspotmail.com
> Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for ERSPAN")
> Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
> ---
> v2:
>    - change subject prefix to [PATCH net]
> 
>   net/ipv4/ip_gre.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
> index 3efdfb4ffa21..9fbff16cda1d 100644
> --- a/net/ipv4/ip_gre.c
> +++ b/net/ipv4/ip_gre.c
> @@ -1363,6 +1363,8 @@ static int erspan_tunnel_init(struct net_device *dev)
>   	dev->features		|= GRE_FEATURES;
>   	dev->hw_features	|= GRE_FEATURES;
>   	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
> +	/* Skip TX lock: xmit re-enters stack, risking ABBA with underlay */
> +	dev->lltx = true;
>   	netif_keep_dst(dev);
>   
>   	return ip_tunnel_init(dev);


^ permalink raw reply

* Re: [net-next v5 1/4] net: af_unix: enable custom setsockopt for all socket types
From: Jori Koolstra @ 2026-07-19 12:31 UTC (permalink / raw)
  To: Kuniyuki Iwashima
  Cc: Christian Brauner, Aleksa Sarai, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, netdev, linux-fsdevel,
	linux-kernel
In-Reply-To: <CAAVpQUCD27YphUQ=aL3PyPtWwTo0tEtaFt-hvyoyCnepGAmYCQ@mail.gmail.com>


> Op 14-07-2026 11:19 CEST schreef Kuniyuki Iwashima <kuniyu@google.com>:
> 
>  
> On Sun, Jul 12, 2026 at 9:29 PM Jori Koolstra <jkoolstra@xs4all.nl> wrote:
> >
> > unix_setsockopt() and the SOCK_CUSTOM_SOCKOPT flag were only wired up
> > for SOCK_STREAM (introduced along with the stream-only SO_INQ).
> > Consequently custom AF_UNIX options are unreachable on SOCK_DGRAM and
> > SOCK_SEQPACKET: those setsockopt() calls bypass unix_setsockopt() and
> > fall through to the generic sock_setsockopt(), failing with
> > -ENOPROTOOPT.
> >
> > Set SOCK_CUSTOM_SOCKOPT for every AF_UNIX socket type in unix_create(), and
> > also for accepted sockets in unix_accept() (reachable for stream and
> > seqpacket).
> >
> > This is a prerequisite for making SO_RIGHTS_NOTRUNC settable on all AF_UNIX
> > socket types.
> >
> > Signed-off-by: Jori Koolstra <jkoolstra@xs4all.nl>
> > ---
> >  net/unix/af_unix.c | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> >
> > diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> > index f7a9d55eee8a..3d256255085b 100644
> > --- a/net/unix/af_unix.c
> > +++ b/net/unix/af_unix.c
> > @@ -949,7 +949,7 @@ static int unix_setsockopt(struct socket *sock, int level, int optname,
> >         switch (optname) {
> >         case SO_INQ:
> >                 if (sk->sk_type != SOCK_STREAM)
> > -                       return -EINVAL;
> > +                       return -ENOPROTOOPT;
> >
> >                 if (val > 1 || val < 0)
> >                         return -EINVAL;
> > @@ -1005,6 +1005,7 @@ static const struct proto_ops unix_dgram_ops = {
> >  #endif
> >         .listen =       sock_no_listen,
> >         .shutdown =     unix_shutdown,
> > +       .setsockopt =   unix_setsockopt,
> >         .sendmsg =      unix_dgram_sendmsg,
> >         .read_skb =     unix_read_skb,
> >         .recvmsg =      unix_dgram_recvmsg,
> > @@ -1029,6 +1030,7 @@ static const struct proto_ops unix_seqpacket_ops = {
> >  #endif
> >         .listen =       unix_listen,
> >         .shutdown =     unix_shutdown,
> > +       .setsockopt =   unix_setsockopt,
> >         .sendmsg =      unix_seqpacket_sendmsg,
> >         .recvmsg =      unix_seqpacket_recvmsg,
> >         .mmap =         sock_no_mmap,
> > @@ -1142,9 +1144,10 @@ static int unix_create(struct net *net, struct socket *sock, int protocol,
> >         if (protocol && protocol != PF_UNIX)
> >                 return -EPROTONOSUPPORT;
> >
> > +       set_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags);
> 
> Please move this to unix_create1(), then we don't need the chunk below.
> 
> 

I don't understand how this helps. The accept() path gets its struct socket from
sock_alloc() not via unix_create() afaict. Also, unix_create1() is called with
sock == NULL on connect(), so now you have to guard against that too.

But maybe I misunderstand you?

I do agree with you other comment, accept() should probably inherit the truncate
behavior from the listen() socket.

Thanks,
Jori.

^ permalink raw reply

* [PATCH net v3] net: dpaa: fix mode setting
From: Christian Zigotzky @ 2026-07-19 11:58 UTC (permalink / raw)
  To: Sean Anderson, Michael Walle, Madalin Bucur, Andrew Lunn,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Christian Zigotzky
  Cc: netdev, linux-kernel, linuxppc-dev, R.T.Dickinson, mad skateman,
	Damien Stewart
In-Reply-To: <095e561e-1e36-9ea1-b0c6-958c825851cb@xenosoft.de>

On 18/07/26 18:31, Christian Zigotzky wrote:
> On 17/07/26 23:10, Sean Anderson wrote:
>> On 7/17/26 09:20, Michael Walle wrote:
>>> Before converting to the phylink interface, the init function would 
>>> have
>>> set a non-reserved I/F mode in the maccfg2 register. After 
>>> converting to
>>> phylink, 0 is written as mode, which is a reserved value (although it's
>>> the hardware default). Without a valid mode, a SGMII link is never
>>> established between the MAC and the PHY and thus .link_up() is never
>>> called which could set the correct mode according to the actual speed.
>>>
>>> Fix it by setting the maximum speed of the phy_interface_t in use in
>>> .mac_config() - just like the driver did before the phylink conversion.
>>>
>>> Fixes: 5d93cfcf7360 ("net: dpaa: Convert to phylink")
>>> Suggested-by: Sean Anderson <sean.anderson@linux.dev>
>>> Signed-off-by: Michael Walle <mwalle@kernel.org>
>>> ---
>>> I didn't grab Sean's Rb tag as this is somewhat different.
>>>
>>> Changes in v3:
>>>   - keep the mode setting also in .adjust_link().
>>>   - reword the commit message, to be (hopefully) more precise
>>>   - Link to v2: 
>>> https://lore.kernel.org/r/20260710143430.2276141-1-mwalle@kernel.org/
>>>
>>> Changes in v2:
>>>   - the setting is/was based on the maximum speed, not the current
>>>     speed. thus, move the setting into mac_config().
>>>   - Link to v1: 
>>> https://lore.kernel.org/r/20260706121011.1948906-1-mwalle@kernel.org/
>>>
>>>   .../net/ethernet/freescale/fman/fman_dtsec.c    | 17 
>>> ++++++++++++-----
>>>   1 file changed, 12 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c 
>>> b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
>>> index fe35703c509e..b8d70c0ecb6c 100644
>>> --- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
>>> +++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
>>> @@ -900,22 +900,28 @@ static void dtsec_mac_config(struct 
>>> phylink_config *config, unsigned int mode,
>>>   {
>>>       struct mac_device *mac_dev = fman_config_to_mac(config);
>>>       struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs;
>>> -    u32 tmp;
>>> +    u32 ecntrl, maccfg2;
>>> +
>>> +    maccfg2 = ioread32be(&regs->maccfg2);
>>> +    maccfg2 &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE);
>>>         switch (state->interface) {
>>>       case PHY_INTERFACE_MODE_RMII:
>>> -        tmp = DTSEC_ECNTRL_RMM;
>>> +        ecntrl = DTSEC_ECNTRL_RMM;
>>> +        maccfg2 |= MACCFG2_NIBBLE_MODE;
>>>           break;
>>>       case PHY_INTERFACE_MODE_RGMII:
>>>       case PHY_INTERFACE_MODE_RGMII_ID:
>>>       case PHY_INTERFACE_MODE_RGMII_RXID:
>>>       case PHY_INTERFACE_MODE_RGMII_TXID:
>>> -        tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM;
>>> +        ecntrl = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM;
>>> +        maccfg2 |= MACCFG2_BYTE_MODE;
>>>           break;
>>>       case PHY_INTERFACE_MODE_SGMII:
>>>       case PHY_INTERFACE_MODE_1000BASEX:
>>>       case PHY_INTERFACE_MODE_2500BASEX:
>>> -        tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM;
>>> +        ecntrl = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM;
>>> +        maccfg2 |= MACCFG2_BYTE_MODE;
>>>           break;
>>>       default:
>>>           dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n",
>>> @@ -923,7 +929,8 @@ static void dtsec_mac_config(struct 
>>> phylink_config *config, unsigned int mode,
>>>           return;
>>>       }
>>>   -    iowrite32be(tmp, &regs->ecntrl);
>>> +    iowrite32be(ecntrl, &regs->ecntrl);
>>> +    iowrite32be(maccfg2, &regs->maccfg2);
>>>   }
>>>     static void dtsec_link_up(struct phylink_config *config, struct 
>>> phy_device *phy,
>>
>> Reviewed-by: Sean Anderson <sean.anderson@linux.dev>
>>
>> Christian, can you test this patch with ethernet at 100/1G speed if 
>> you still have
>> access to those P5020/P5040 boards?
>>
>> https://lore.kernel.org/all/0bfc8f3d-cb62-25f4-2590-ff424adbe48a@xenosoft.de/ 
>>
> I tested the patch today. I don't see any differences.
>
> Further information: 
> https://github.com/chzigotzky/kernels/releases/tag/v7.2.0-rc3-fman-dtsec-patch
>
> Christian
>
I tested further the new patch today and switching between 100Mbit/s and 
1Gbit/s works without any problems.

[ 1692.006428] fsl_dpaa_mac ffe4e8000.ethernet eth0: PHY 
[mdio@ffe4e1120:03] driver [Micrel KSZ9021 Gigabit PHY] (irq=POLL)
[ 1692.006448] fsl_dpaa_mac ffe4e8000.ethernet eth0: configuring for 
phy/rgmii link mode
[ 1692.021436] fsl_dpaa_mac ffe5e8000.ethernet eth2: PHY 
[mdio@ffe4e1120:07] driver [Micrel KSZ9021 Gigabit PHY] (irq=POLL)
[ 1692.021456] fsl_dpaa_mac ffe5e8000.ethernet eth2: configuring for 
phy/rgmii link mode
[ 1695.057699] fsl_dpaa_mac ffe4e8000.ethernet eth0: Link is Up - 
1Gbps/Full - flow control rx/tx
[ 2148.681140] fsl_dpaa_mac ffe4e8000.ethernet eth0: Link is Down
[ 2149.704534] fsl_dpaa_mac ffe4e8000.ethernet eth0: Link is Up - 
100Mbps/Full - flow control rx/tx
[ 2199.875179] fsl_dpaa_mac ffe4e8000.ethernet eth0: Link is Down
[ 2201.923103] fsl_dpaa_mac ffe4e8000.ethernet eth0: Link is Up - 
1Gbps/Full - flow control rx/tx

- Christian

-- 
Sent with BrassMonkey 34.2.2 (https://github.com/chzigotzky/Web-Browsers-and-Suites-for-Linux-PPC/releases/tag/BrassMonkey_34.2.2)


^ permalink raw reply

* Re: [PATCH net v2] nfc: nci: fix uninit-value in the RF discover/activated NTF handlers
From: David Heidelberg @ 2026-07-19 11:54 UTC (permalink / raw)
  To: Sam P
  Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, oe-linux-nfc, netdev, linux-kernel, stable
In-Reply-To: <edfa1b87-a28c-40ca-85ca-e11ac3482518@bynar.io>


On Fri, 26 Jun 2026 10:03:01 +0100, Samuel Page wrote:
 > nfc: nci: fix uninit-value in the RF discover/activated NTF handlers

Applied, thanks!

[1/1] nfc: nci: fix uninit-value in the RF discover/activated NTF handlers
       commit: 7b5b8b3bb6d96474484b5666eac5a793eb0fdb4e

Best regards,
-- 
David Heidelberg <david@ixit.cz>

^ permalink raw reply

* Re: [PATCH net v2] nfc: nci: fix uninit-value in the RF discover/activated NTF handlers
From: David Heidelberg @ 2026-07-19 11:54 UTC (permalink / raw)
  To: Sam P
  Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, oe-linux-nfc, netdev, linux-kernel, stable
In-Reply-To: <edfa1b87-a28c-40ca-85ca-e11ac3482518@bynar.io>

On 29/06/2026 14:23, Sam P wrote:
> On 27/06/2026 19:41, David Heidelberg wrote:
>>> Assisted-by: Bynario AI
>>
>> Hello Samuel,
>>
>> the fix look good, may I ask you to follow the Assisted-by syntax as requested 
>> in [1]?
>>
>> Thank you
>> David
>>
>> [1] https://docs.kernel.org/process/coding-assistants.html
> 
> Hey David,
> 
> The :MODEL_VERSION was omitted as we use a range of different models and 
> versions in our pipeline, making it hard to attribute to a single model/version. 
> As for the AGENT_NAME, in this instance, would the correct syntax be to remove 
> the spacing here (e.g. Bynario-AI)?
> 
> Once clarified, I'll submit a new patch with the correct syntax.

Hello Sam,

with recent discussion about the tag itself, I'm fine to keep it as-is :)

David

> 
> Thanks,
> Sam
> 
> 

-- 
David Heidelberg


^ permalink raw reply

* Re: [PATCH net] nfc: pn533: prevent division by zero in the listen mode timer
From: David Heidelberg @ 2026-07-19 11:43 UTC (permalink / raw)
  To: Yinhao Hu, Simon Horman
  Cc: netdev, David Heidelberg, Krzysztof Kozlowski, Jakub Kicinski,
	Dan Carpenter, dzm91, hust-os-kernel-patches
In-Reply-To: <c14e4b47-0cc0-4141-b0d8-f80633594402@hust.edu.cn>

[...]

> 
> If you'd still prefer the lockless accesses marked explicitly, I can add
> READ_ONCE()/WRITE_ONCE() in v2.

Heya Simon,

what's your take here?

Thanks
David

> 
>>>   	dev->cancel_listen = 1;
>>>   
>>>   	pn533_poll_next_mod(dev);
>>> -- 
>>> 2.43.0
>>>
> 

^ permalink raw reply

* Re: [PATCH net-next v2 2/2] net: dsa: mv88e6xxx: embedded PTP timestamp support
From: Luke Howard @ 2026-07-19 11:35 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Vivien Didelot, Gregory CLEMENT, Andrew Lunn, Richard Cochran,
	Cedric Jehasse, Kieran Tyrrell, Max Holtmann, Max Hunter,
	Christoph Mellauner, Simon Gapp, netdev, linux-kernel
In-Reply-To: <20260719101241.xs4nz7r5bonb3qys@skbuf>


> We try to keep the data path protocol between the switch and the host
> API compatible, and identifiable by /sys/class/net/<conduit>/dsa/tagging.
> I would argue that the protocol where PTP timestamps are in registers,
> vs where they are in PTP header reserved fields, vs where they are
> appended as trailers, are 3 different protocols and should not be
> presented as "edsa".

For context: I added ArrTSMode support because even with the PTP worker process priority bumped, ptp4l frequently missed RX timestamps.

I can add these as non-default tagging variants that can be selected by the user. "edsa-arrts-trailer" and "edsa-arrts-ptp-reserved”?

Luke

^ permalink raw reply

* Re: [PATCH net-next 0/2] ipv6: report why a route was deleted in RTM_DELROUTE
From: Yuyang Huang @ 2026-07-19 11:24 UTC (permalink / raw)
  To: Ido Schimmel
  Cc: David S. Miller, Bobby Eshleman, Chris J Arges, Daniel Zahka,
	David Ahern, David Wei, Dimitri Daskalakis, Donald Hunter,
	Eric Dumazet, Gal Pressman, Jakub Kicinski, Paolo Abeni,
	Shuah Khan, Simon Horman, Stanislav Fomichev, Willem de Bruijn,
	linux-kernel, linux-kselftest, netdev
In-Reply-To: <20260719065310.GB1841238@shredder>

On Sun, Jul 19, 2026 at 3:53 PM Ido Schimmel <idosch@nvidia.com> wrote:
> Please expand more on the motivation: Which user space application is
> going to consume this information and what is it going to do with it?

Thanks for the review, let me add more background information.

My current use case comes from Android devices, but I think it is a
general problem that any consumer device running Linux will face,
especially on Wi-Fi networks (multicast delivery on Wi-Fi is not
guaranteed, e.g. frames can be lost around DTIM for clients in power
save mode).

On Android, the userspace NetworkStack process listens on
RTMGRP_IPV6_ROUTE and today treats any loss of the IPv6 default route
as "router lost". To prevent the device from repeatedly gaining and
losing IPv6 connectivity on a badly configured network (e.g. a
misconfigured RA interval), when it detects the device is on a
dual-stack network with working IPv4 connectivity, it defensively
clears accept_ra_defrtr and restarts IPv6. The intention is to stop
userspace apps from continuing to use broken global IPv6 connectivity
(while keeping link-local IPv6 working). However, if the route was
withdrawn by a zero-lifetime RA (some ISPs do this intentionally for
various reconfiguration reasons), that reaction is wrong - with
accept_ra_defrtr off, IPv6 never recovers when the router advertises
again. If the route genuinely expired, the defensive reaction is
right, since the router failed to refresh it in time.

We tried to fix this in userspace but found we cannot get the needed
information from the kernel. RTM_NEWROUTE carries the initial route
lifetime (in rta_cacheinfo), but when a later RA refreshes the
lifetime, the kernel does not resend RTM_NEWROUTE. So to distinguish
the cause of an RTM_DELROUTE, userspace would have to open a raw
socket, listen to RAs, and track lifetimes itself. That is not ideal:
this logic already exists in the kernel, and userspace should not
need to replicate it.

I also considered sending RTM_NEWROUTE on every RA lifetime update,
but that would be spammy and is technically wrong (a lifetime update
does not add a new route, so it should not trigger RTM_NEWROUTE).

I think RTA_DEL_REASON is the architecturally correct fix: it tells
userspace why the route was deleted so it can react accordingly. In
our use case, NetworkStack should defensively disable global IPv6
only on RTA_DEL_REASON_EXPIRED, and take no action on
RTA_DEL_REASON_RA_WITHDRAWN since that is RFC-compliant behavior.

Feel free to let me know if more background is needed. If this use
case makes sense, I will summarize it in the v2 commit message.

> Also, Sashiko has some valid comments. Please take a look.

Here is the reply to the sashiko's feedback.

>Does this new attribute violate the Netlink uAPI guidelines for integer
>types? The guidelines state we should avoid integer types smaller than 32
>bits since they save no memory due to 4-byte attribute alignment padding,
>unless the value is a fixed protocol header field.
>Should this be defined as a u32?
...
>Since this deletion reason is a software classification and not a compact
>protocol field, it has no natural requirement to be 8-bit. Would it be
>better to document and serialize this as a 32-bit integer to prevent
>artificially limiting the enum space for future additions?
...
>If the attribute type in the YAML spec is updated to u32, this call to
>nla_put_u8() in rt6_fill_node() would also need to be updated to
>nla_put_u32() to match the 32-bit width.

Good point, given u8 saves nothing, will change it to u32 in v2.

>Will this operation cause a TypeError crash during test execution?
>In Python 3, using the subtraction operator between a set and a dict_keys
>object raises an unsupported operand type error. Since the caller
>ipv6_route_del_reason_ra_withdrawn() passes a set for the want parameter,
>want - seen.keys() will crash the test.
>Should this be converted to a set first, such as want - set(seen.keys())?

I don't think this is a bug (dict_keys is a set-like view) and the
test passes correctly in my local test. But the suggested form reads
better, so I'll apply it in v2.

Thanks,

Yuyang

^ permalink raw reply

* Re: [PATCH net-next v2 0/2] net: dsa: mv88e6xxx: various hwstamp fixes
From: Luke Howard @ 2026-07-19 11:22 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Vivien Didelot, Gregory CLEMENT, Andrew Lunn, Richard Cochran,
	Cedric Jehasse, Kieran Tyrrell, Max Holtmann, Max Hunter,
	Christoph Mellauner, Simon Gapp, netdev, linux-kernel
In-Reply-To: <20260719095307.hwtnbrqdkjxntrcr@skbuf>

Hi Vladimir,

> ocelot_ptp_rx_timestamp() accesses MMIO-based registers, which can be
> done atomically.
> mv88e6xxx_ptp_clock_read() accesses MDIO bus registers, and the MDIO bus
> is sleepable. Fundamental difference.
> 
> Your hardware only provides 32 bits of partial timestamp, so
> mv88e6xxx_ptp_clock_read() will always be needed one way or another, to
> recover the full 64 bits. Either through tstamp_{cc,tc} or through
> direct calls.

This still happens from overflow_work().

>> Deferring to the worker can reorder frames such that PTP general
>> messages arrive before the timestamped event messages, which confuses
>> some other PTP implementations such as gptp2d [1].
> 
> True, this is a caveat, but event messages and general messages can
> already take different network paths, especially with PTP over IP where
> they go through different UDP ports (even if for gPTP that is not the case).
> The PTP user space implementation needs to be prepared to handle this.

Good point. So perhaps processing the embedded timestamp inline doesn’t confer much benefit. ptp4l (which we use) handles out-of-order messages fine.

>> This optimisation of course only works for ArrTSMode because there is
>> no MDIO read required.
> 
> I don't understand this comment given the partial 32-bit timestamp
> limitation.

Better phrased as no MDIO read to recover the arrival timestamp.

Luke

^ permalink raw reply

* [PATCH net] ipv6: Change allocation flags to match rcu_read_lock section requirements
From: Nikola Z. Ivanov @ 2026-07-19 10:57 UTC (permalink / raw)
  To: dsahern, idosch, davem, edumazet, kuba, pabeni, horms
  Cc: kuniyu, netdev, linux-kernel, Nikola Z. Ivanov,
	syzbot+84d4a405ed798b40c96d

Since the call to __ip6_del_rt_siblings has been converted under
rcu read lock and it only has one call point
we should no longer block or yield.

Our stack trace from the syzbot reproducer looks as follows:

__ip6_del_rt_siblings
  rtnl_notify (Here we pass gfp_any() -> GFP_KERNEL)
    nlmsg_notify
      nlmsg_multicast
        nlmsg_multicast_filtered
          netlink_broadcast_filtered (GFP_KERNEL passed from earlier)

netlink_broadcast_filtered can yield if GFP_KERNEL
is passed, which we do not want to happen.

Fix this by changing the allocation flag of rtnl_notify.

Also change the flag passed to nlmsg_new. Even though it
is not related to the syzbot generated bug it still falls
under the same requirements.

Reported-by: syzbot+84d4a405ed798b40c96d@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=84d4a405ed798b40c96d
Fixes: bd11ff421d36 ("ipv6: Get rid of RTNL for SIOCDELRT and RTM_DELROUTE.")
Signed-off-by: Nikola Z. Ivanov <zlatistiv@gmail.com>
---
 net/ipv6/route.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a1301334da48..fc42d67e5822 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -4022,7 +4022,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
 		struct fib6_node *fn;
 
 		/* prefer to send a single notification with all hops */
-		skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any());
+		skb = nlmsg_new(rt6_nlmsg_size(rt), GFP_ATOMIC);
 		if (skb) {
 			u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
 
@@ -4078,7 +4078,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
 
 	if (skb) {
 		rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE,
-			    info->nlh, gfp_any());
+			    info->nlh, GFP_ATOMIC);
 	}
 	return err;
 }
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH net-next v4 15/15] net: macb: use context swapping in .ndo_change_mtu()
From: Nicolai Buchwitz @ 2026-07-19 10:54 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-15-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> Use newly introduced context buffer management to implement
> .ndo_change_mtu() as a context swap: allocate new context ->
> reconfigure HW -> free old context.
> 
> This resists memory pressure well by failing without closing the
> interface and it is much faster by avoiding PHY reinit.
> 
> AT91 EMAC is handled differently as their buffer management is separate
> and they don't do NAPI. We refuse them (-EBUSY) to avoid implementing
> context swapping for them.
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/net/ethernet/cadence/macb_main.c | 22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index 5792647eb0a6..1de66f442c59 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -3493,11 +3493,29 @@ static int macb_close(struct net_device 
> *netdev)
> 
>  static int macb_change_mtu(struct net_device *netdev, int new_mtu)
>  {
> -	if (netif_running(netdev))
> -		return -EBUSY;
> +	struct macb *bp = netdev_priv(netdev);
> +	bool running = netif_running(netdev);
> +	struct macb_context *new_ctx;
> +
> +	if (running) {
> +		/* Context swapping is not supported for AT91. */
> +		if (bp->caps & MACB_CAPS_MACB_IS_EMAC)
> +			return -EBUSY;
> +
> +		new_ctx = macb_context_alloc(bp, new_mtu,
> +					     bp->configured_rx_ring_size,
> +					     bp->configured_tx_ring_size);
> +		if (IS_ERR(new_ctx))
> +			return PTR_ERR(new_ctx);
> +
> +		macb_context_swap_start(bp);
> +	}
> 
>  	WRITE_ONCE(netdev->mtu, new_mtu);
> 
> +	if (running)
> +		macb_context_swap_end(bp, new_ctx);
> +
>  	return 0;
>  }

Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>

Thanks
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v4 14/15] net: macb: use context swapping in .set_ringparam()
From: Nicolai Buchwitz @ 2026-07-19 10:53 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-14-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> ethtool_ops.set_ringparam() is implemented using the primitive close /
> update ring size / reopen sequence. Under memory pressure this does not
> fly: we free our buffers at close and cannot reallocate new ones at
> open. Also, it triggers a slow PHY reinit.
> 
> Instead, exploit the new context mechanism and improve our sequence to:
>  - allocate a new context (including buffers) first
>  - if it fails, early return without any impact to the interface
>  - stop interface
>  - update global state (bp, netdev, etc)
>  - pass buffer pointers to the hardware
>  - start interface
>  - free old context.
> 
> The HW disable sequence is inspired by macb_reset_hw() but avoids
> (1) setting NCR bit CLRSTAT and (2) clearing register PBUFRXCUT.
> 
> The HW re-enable sequence is inspired by macb_mac_link_up(), skipping
> over register writes which would be redundant (because values have not
> changed).
> 
> The generic context swapping parts are isolated into helper functions
> macb_context_swap_start|end(), reusable by other operations 
> (change_mtu,
> set_channels, etc).
> 
> Introduce a new locking primitive (mac_cfg_lock mutex) to serialise 
> swap
> with phylink MAC callbacks. Avoid stopping phylink to avoid a slow PHY
> retrain. Those callbacks grab phydev->lock if it exists so we could
> imagine grabbing that from the swap op, but phydev->lock doesn't exist
> in the SFP case.
> 
> AT91 EMAC is handled differently as their buffer management is separate
> and they don't do NAPI. We refuse them (-EBUSY) to avoid implementing
> context swapping for them.
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/net/ethernet/cadence/macb.h      |   5 +
>  drivers/net/ethernet/cadence/macb_main.c | 162 
> +++++++++++++++++++++++++++++--
>  2 files changed, 158 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb.h 
> b/drivers/net/ethernet/cadence/macb.h
> index ac2f2d8065d7..93e513cf1fbb 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -1361,6 +1361,8 @@ struct macb {
>  	struct macb_queue	queues[MACB_MAX_QUEUES];
> 
>  	spinlock_t		lock;
> +	/* Serializes context swap against phylink MAC callbacks. */
> +	struct mutex		mac_cfg_lock;
>  	struct clk		*pclk;
>  	struct clk		*hclk;
>  	struct clk		*tx_clk;
> @@ -1421,6 +1423,9 @@ struct macb {
>  	struct delayed_work	tx_lpi_work;
>  	u32			tx_lpi_timer;
> 
> +	/* ISR must not drive NAPI & BH mechanisms. Protected by bp->lock. */
> +	bool			ctx_swap;
> +
>  	u32	rx_intr_mask;
> 
>  	struct macb_pm_data pm_data;
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index c832b6c1b98c..5792647eb0a6 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c

> [...]

> +
> +	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
> +		/* Must be done before NAPI is disabled. */
> +		cancel_work_sync(&queue->tx_error_task);
> +
> +		napi_disable(&queue->napi_rx);
> +		napi_disable(&queue->napi_tx);
> +		netdev_tx_reset_queue(netdev_get_tx_queue(bp->netdev, q));
> +	}
> +
> +	/* Must be done after napi_tx is disabled. */
> +	cancel_delayed_work_sync(&bp->tx_lpi_work);
> +
> +	/* Can finally disable software Tx; need to wait until napi_tx and
> +	 * tx_error_task cannot be scheduled as either might wakeup Tx.
> +	 */
> +	netif_tx_disable(bp->netdev);

Shouldn't netdev_tx_reset_queue() come after netif_tx_disable()? Tx is
still running here, so an xmit right after the reset adds bytes to the
DQL that never get completed (macb_free() frees the old skbs without
netdev_tx_completed_queue()). Not sure, but that could leave the queue
stopped by BQL forever?

> [...]

Thanks
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v4 13/15] net: macb: read ISR inside bp->lock critical section
From: Nicolai Buchwitz @ 2026-07-19 10:48 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-13-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> The IRQ handler reads ISR register into the `status` stack variable.
> If empty, it early returns. Else, it grabs bp->lock and iterates on
> the status bits.
> 
> We risk a race on spinlock acquire; status might have changed.
> Move the readl(ISR) inside the bp->lock critical section.
> 
> One risk remains with spurious interrupts that would, in addition to
> taking excessive CPU time, also create lock contention. How bad is it?
> Probably not too bad.
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/net/ethernet/cadence/macb_main.c | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index 4c94c23d925a..c832b6c1b98c 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -2185,13 +2185,14 @@ static irqreturn_t macb_interrupt(int irq, void 
> *dev_id)
>  	struct net_device *netdev = bp->netdev;
>  	u32 status;
> 
> -	status = queue_readl(queue, ISR);
> -
> -	if (unlikely(!status))
> -		return IRQ_NONE;
> -
>  	spin_lock(&bp->lock);
> 
> +	status = queue_readl(queue, ISR);
> +	if (unlikely(!status)) {
> +		spin_unlock(&bp->lock);
> +		return IRQ_NONE;
> +	}
> +
>  	while (status) {
>  		/* close possible race with dev_close */
>  		if (unlikely(!netif_running(netdev))) {

Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>

Thanks
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v4 12/15] net: macb: introduce macb_context_alloc() helper
From: Nicolai Buchwitz @ 2026-07-19 10:47 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-12-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> Move the context allocation sequence from inline macb_open() to its own
> helper function called macb_context_alloc(). All ops doing context
> swapping (set_ringparam, change_mtu, etc) will use this helper.
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/net/ethernet/cadence/macb_main.c | 56 
> +++++++++++++++++++++-----------
>  1 file changed, 37 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index d396a307310b..4c94c23d925a 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -2866,6 +2866,36 @@ static int macb_alloc(struct macb_context *ctx)
>  	return -ENOMEM;
>  }
> 
> +static struct macb_context *macb_context_alloc(struct macb *bp,
> +					       unsigned int mtu,
> +					       unsigned int rx_ring_size,
> +					       unsigned int tx_ring_size)
> +{
> +	struct macb_context *ctx;
> +	int err;
> +
> +	ctx = kzalloc_obj(*ctx);
> +	if (!ctx)
> +		return ERR_PTR(-ENOMEM);
> +
> +	ctx->info = &bp->info;
> +	ctx->rx_buffer_size = macb_rx_buffer_size(bp, mtu);
> +	ctx->rx_ring_size = rx_ring_size;
> +	ctx->tx_ring_size = tx_ring_size;
> +
> +	err = macb_alloc(ctx);
> +	if (err) {
> +		netdev_err(bp->netdev,
> +			   "Unable to allocate DMA memory (error %d)\n", err);
> +		kfree(ctx);
> +		return ERR_PTR(err);
> +	}
> +
> +	bp->macbgem_ops.mog_init_rings(ctx);
> +
> +	return ctx;
> +}
> +
>  static void gem_init_rx_ring(struct macb_context *ctx, unsigned int q)
>  {
>  	struct macb_rxq *rxq = &ctx->rxq[q];
> @@ -3233,27 +3263,15 @@ static int macb_open(struct net_device *netdev)
>  	if (err < 0)
>  		return err;
> 
> -	bp->ctx = kzalloc_obj(*bp->ctx);
> -	if (!bp->ctx) {
> -		err = -ENOMEM;
> +	bp->ctx = macb_context_alloc(bp, netdev->mtu,
> +				     bp->configured_rx_ring_size,
> +				     bp->configured_tx_ring_size);
> +	if (IS_ERR(bp->ctx)) {
> +		err = PTR_ERR(bp->ctx);
> +		bp->ctx = NULL;
>  		goto pm_exit;
>  	}
> 
> -	bp->ctx->info = &bp->info;
> -
> -	/* RX buffers initialization */
> -	bp->ctx->rx_buffer_size = macb_rx_buffer_size(bp, netdev->mtu);
> -	bp->ctx->rx_ring_size = bp->configured_rx_ring_size;
> -	bp->ctx->tx_ring_size = bp->configured_tx_ring_size;
> -
> -	err = macb_alloc(bp->ctx);
> -	if (err) {
> -		netdev_err(netdev, "Unable to allocate DMA memory (error %d)\n",
> -			   err);
> -		goto free_ctx;
> -	}
> -
> -	bp->macbgem_ops.mog_init_rings(bp->ctx);
>  	macb_init_buffers(bp);
> 
>  	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
> @@ -3292,7 +3310,6 @@ static int macb_open(struct net_device *netdev)
>  		napi_disable(&queue->napi_tx);
>  	}
>  	macb_free(bp->ctx);
> -free_ctx:
>  	kfree(bp->ctx);
>  	bp->ctx = NULL;
>  pm_exit:
> @@ -5175,6 +5192,7 @@ static int at91ether_open(struct net_device 
> *netdev)
>  		ret = -ENOMEM;
>  		goto pm_exit;
>  	}
> +	bp->ctx->info = &bp->info;
> 
>  	/* Clear internal statistics */
>  	ctl = macb_readl(bp, NCR);

Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>

Thanks
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v4 11/15] net: macb: change function signatures to take contexts
From: Nicolai Buchwitz @ 2026-07-19 10:46 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-11-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> For parallel MACB context to start become a reality, many functions 
> need
> to stop operating on bp->ctx (the currently active context) and instead
> work on a context they get passed. That context might be
> (1) the new one that is getting allocated and initialised, or,
> (2) the old one to be freed.
> 
> To reduce bug surface area, taint those functions to *only* take a
> context `struct macb_context *ctx` and no `struct macb *bp`. That way,
> no bug of using `bp->ctx` instead of `ctx` will ever occur.
> 
> We also convert functions that take a `struct macb_queue *queue` to
> instead take `struct macb_context *ctx, unsigned int q`, with q
> indexing ctx->txq[] and ctx->rxq[].
> 
> Full list:
> 
>    macb_adj_dma_desc_idx()
>    macb_tx_ring_wrap()
>    macb_tx_desc()
>    macb_rx_ring_wrap()
>    macb_rx_desc()
>    macb_get_addr()
>    gem_rx_refill()
>    macb_init_rx_ring()
>    gem_free_rx_buffers()
>    macb_free_rx_buffers()
>    macb_tx_ring_size_per_queue()
>    macb_rx_ring_size_per_queue()
>    macb_free()
>    gem_alloc_rx_buffers()
>    macb_alloc_rx_buffers()
>    macb_alloc()
>    gem_init_rx_ring()
>    gem_init_rings()
>    macb_init_rings()
> 
> Note about gem_rx_refill(): it ends with a netdev_vdbg() that prints 
> the
> queue pointer. Change to print the queue index because we do not have
> access to the queue anymore.
> 
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/net/ethernet/cadence/macb.h      |   7 +-
>  drivers/net/ethernet/cadence/macb_main.c | 398 
> ++++++++++++++++---------------
>  2 files changed, 215 insertions(+), 190 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb.h 
> b/drivers/net/ethernet/cadence/macb.h
> index c551d7db8ebe..ac2f2d8065d7 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -1196,11 +1196,12 @@ static const struct gem_statistic 
> queue_statistics[] = {
> 
>  struct macb;
>  struct macb_queue;
> +struct macb_context;
> 
>  struct macb_or_gem_ops {
> -	int	(*mog_alloc_rx_buffers)(struct macb *bp);
> -	void	(*mog_free_rx_buffers)(struct macb *bp);
> -	void	(*mog_init_rings)(struct macb *bp);
> +	int	(*mog_alloc_rx_buffers)(struct macb_context *ctx);
> +	void	(*mog_free_rx_buffers)(struct macb_context *ctx);
> +	void	(*mog_init_rings)(struct macb_context *ctx);
>  	int	(*mog_rx)(struct macb_queue *queue, struct napi_struct *napi,
>  			  int budget);
>  };
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index 7574418d5094..d396a307310b 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c

> [...]

> @@ -5083,7 +5107,7 @@ static int at91ether_start(struct macb *bp)
> 
>  	addr = rxq->buffers_dma;
>  	for (i = 0; i < AT91ETHER_MAX_RX_DESCR; i++) {
> -		desc = macb_rx_desc(queue, i);
> +		desc = macb_rx_desc(bp->ctx, 0, i);

AFAIU at91ether_open() doesn't set bp->ctx->info at this point in the
series, so with CONFIG_MACB_USE_HWSTAMP=y this should oops on ifup:

     macb_rx_desc()
       macb_adj_dma_desc_idx()
         macb_dma_ptp(ctx->info)   -> NULL deref

The next patch adds the missing assignment to at91ether_open(), so
only bisection is affected. Maybe move that line here or into patch 9?

> [...]

Thanks
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v4 10/15] net: macb: change caps helpers signatures
From: Nicolai Buchwitz @ 2026-07-19 10:42 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-10-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> For parallel MACB context to start becoming a reality, many functions
> will soon not have access to `struct macb *bp`. Those will still have
> access to caps through ctx->info->caps.
> 
> Change all caps helpers signatures, from taking `struct macb *bp` to
> taking `struct macb_info *info`. Info is accessible in both bp and ctx
> and it ensures type safety (versus passing raw `u32 caps`).
> 
> Function list:
> 
>    macb_is_gem()
>    gem_has_ptp()
>    macb_dma64()
>    macb_dma_ptp()
>    macb_dma_desc_get_size()
>    macb_set_addr()
>    macb_get_addr()
>    macb_64b_desc()
> 
> Note: drop macb_64b_desc(bp, ...) parameter; it is unused and it must
> be dropped as macb_{set,get}_addr() call macb_64b_desc().
> 
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/net/ethernet/cadence/macb.h      |  21 ++---
>  drivers/net/ethernet/cadence/macb_main.c | 138 
> ++++++++++++++++---------------
>  drivers/net/ethernet/cadence/macb_ptp.c  |   8 +-
>  3 files changed, 86 insertions(+), 81 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb.h 
> b/drivers/net/ethernet/cadence/macb.h
> index 2db01fa81559..c551d7db8ebe 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -840,7 +840,7 @@
>   */
>  #define macb_or_gem_writel(__bp, __reg, __value) \
>  	({ \
> -		if (macb_is_gem((__bp))) \
> +		if (macb_is_gem(&(__bp)->info)) \
>  			gem_writel((__bp), __reg, __value); \
>  		else \
>  			macb_writel((__bp), __reg, __value); \
> @@ -849,7 +849,7 @@
>  #define macb_or_gem_readl(__bp, __reg) \
>  	({ \
>  		u32 __v; \
> -		if (macb_is_gem((__bp))) \
> +		if (macb_is_gem(&(__bp)->info)) \
>  			__v = gem_readl((__bp), __reg); \
>  		else \
>  			__v = macb_readl((__bp), __reg); \
> @@ -1471,14 +1471,15 @@ static inline void gem_ptp_do_txstamp(struct 
> macb *bp, struct sk_buff *skb, stru
>  static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff 
> *skb, struct macb_dma_desc *desc) { }
>  #endif
> 
> -static inline bool macb_is_gem(struct macb *bp)
> +static inline bool macb_is_gem(const struct macb_info *info)
>  {
> -	return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
> +	return !!(info->caps & MACB_CAPS_MACB_IS_GEM);
>  }
> 
> -static inline bool gem_has_ptp(struct macb *bp)
> +static inline bool gem_has_ptp(const struct macb_info *info)
>  {
> -	return IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) && (bp->caps & 
> MACB_CAPS_GEM_HAS_PTP);
> +	return IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) &&
> +	       (info->caps & MACB_CAPS_GEM_HAS_PTP);
>  }
> 
>  /* ENST Helper functions */
> @@ -1494,16 +1495,16 @@ static inline u64 enst_max_hw_interval(u32 
> speed_mbps)
>  			    ENST_TIME_GRANULARITY_NS * 1000, (speed_mbps));
>  }
> 
> -static inline bool macb_dma64(struct macb *bp)
> +static inline bool macb_dma64(const struct macb_info *info)
>  {
>  	return IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) &&
> -	       bp->caps & MACB_CAPS_DMA_64B;
> +	       info->caps & MACB_CAPS_DMA_64B;
>  }
> 
> -static inline bool macb_dma_ptp(struct macb *bp)
> +static inline bool macb_dma_ptp(const struct macb_info *info)
>  {
>  	return IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) &&
> -	       bp->caps & MACB_CAPS_DMA_PTP;
> +	       info->caps & MACB_CAPS_DMA_PTP;
>  }
> 
>  static inline void macb_queue_isr_clear(struct macb *bp,
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index 40ebe20bb40c..7574418d5094 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -126,13 +126,13 @@ struct sifive_fu540_macb_mgmt {
>   *    word 5: timestamp word 1
>   *    word 6: timestamp word 2
>   */
> -static unsigned int macb_dma_desc_get_size(struct macb *bp)
> +static unsigned int macb_dma_desc_get_size(const struct macb_info 
> *info)
>  {
>  	unsigned int desc_size = sizeof(struct macb_dma_desc);
> 
> -	if (macb_dma64(bp))
> +	if (macb_dma64(info))
>  		desc_size += sizeof(struct macb_dma_desc_64);
> -	if (macb_dma_ptp(bp))
> +	if (macb_dma_ptp(info))
>  		desc_size += sizeof(struct macb_dma_desc_ptp);
> 
>  	return desc_size;
> @@ -140,10 +140,10 @@ static unsigned int macb_dma_desc_get_size(struct 
> macb *bp)
> 
>  static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned 
> int desc_idx)
>  {
> -	return desc_idx * (1 + macb_dma64(bp) + macb_dma_ptp(bp));
> +	return desc_idx * (1 + macb_dma64(&bp->info) + 
> macb_dma_ptp(&bp->info));
>  }
> 
> -static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct 
> macb_dma_desc *desc)
> +static struct macb_dma_desc_64 *macb_64b_desc(struct macb_dma_desc 
> *desc)
>  {
>  	return (struct macb_dma_desc_64 *)((void *)desc
>  		+ sizeof(struct macb_dma_desc));
> @@ -195,7 +195,7 @@ static dma_addr_t macb_tx_dma(struct macb_queue 
> *queue, unsigned int index)
>  	dma_addr_t offset;
> 
>  	offset = macb_tx_ring_wrap(queue->bp, index) *
> -			macb_dma_desc_get_size(queue->bp);
> +			macb_dma_desc_get_size(&queue->bp->info);
> 
>  	return txq->ring_dma + offset;
>  }
> @@ -282,7 +282,7 @@ static void macb_set_hwaddr(struct macb *bp)
>  	top = get_unaligned_le16(bp->netdev->dev_addr + 4);
>  	macb_or_gem_writel(bp, SA1T, top);
> 
> -	if (gem_has_ptp(bp)) {
> +	if (gem_has_ptp(&bp->info)) {
>  		gem_writel(bp, RXPTPUNI, bottom);
>  		gem_writel(bp, TXPTPUNI, bottom);
>  	}
> @@ -493,7 +493,7 @@ static void macb_init_buffers(struct macb *bp)
>  	unsigned int q;
> 
>  	/* Single register for all queues' high 32 bits. */
> -	if (macb_dma64(bp)) {
> +	if (macb_dma64(&bp->info)) {
>  		rxq = &bp->ctx->rxq[0];
>  		txq = &bp->ctx->txq[0];
>  		macb_writel(bp, RBQPH, upper_32_bits(rxq->ring_dma));
> @@ -776,7 +776,7 @@ static void macb_mac_config(struct phylink_config 
> *config, unsigned int mode,
>  	if (bp->caps & MACB_CAPS_MACB_IS_EMAC) {
>  		if (state->interface == PHY_INTERFACE_MODE_RMII)
>  			ctrl |= MACB_BIT(RM9200_RMII);
> -	} else if (macb_is_gem(bp)) {
> +	} else if (macb_is_gem(&bp->info)) {
>  		ctrl &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
>  		ncr &= ~GEM_BIT(ENABLE_HS_MAC);
> 
> @@ -834,7 +834,7 @@ static void gem_shuffle_tx_one_ring(struct 
> macb_queue *queue)
>  	unsigned char desc[24];
>  	unsigned long flags;
> 
> -	desc_size = macb_dma_desc_get_size(bp);
> +	desc_size = macb_dma_desc_get_size(&bp->info);
> 
>  	if (WARN_ON_ONCE(desc_size > ARRAY_SIZE(desc)))
>  		return;
> @@ -941,7 +941,7 @@ static void macb_mac_link_up(struct phylink_config 
> *config,
> 
>  	if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) {
>  		ctrl &= ~MACB_BIT(PAE);
> -		if (macb_is_gem(bp)) {
> +		if (macb_is_gem(&bp->info)) {
>  			ctrl &= ~GEM_BIT(GBE);
> 
>  			if (speed == SPEED_1000)
> @@ -972,7 +972,7 @@ static void macb_mac_link_up(struct phylink_config 
> *config,
> 
>  	/* Enable Rx and Tx; Enable PTP unicast */
>  	ctrl = macb_readl(bp, NCR);
> -	if (gem_has_ptp(bp))
> +	if (gem_has_ptp(&bp->info))
>  		ctrl |= MACB_BIT(PTPUNI);
> 
>  	macb_writel(bp, NCR, ctrl | MACB_BIT(RE) | MACB_BIT(TE));
> @@ -1082,7 +1082,8 @@ static int macb_mii_probe(struct net_device 
> *netdev)
>  		  bp->phylink_config.supported_interfaces);
> 
>  	/* Determine what modes are supported */
> -	if (macb_is_gem(bp) && (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)) 
> {
> +	if (macb_is_gem(&bp->info) &&
> +	    (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)) {
>  		bp->phylink_config.mac_capabilities |= MAC_1000FD;
>  		if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF))
>  			bp->phylink_config.mac_capabilities |= MAC_1000HD;
> @@ -1250,12 +1251,13 @@ static void macb_tx_unmap(struct macb *bp, 
> struct macb_tx_skb *tx_skb, int budge
>  	}
>  }
> 
> -static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, 
> dma_addr_t addr)
> +static void macb_set_addr(const struct macb_info *info,
> +			  struct macb_dma_desc *desc, dma_addr_t addr)
>  {
> -	if (macb_dma64(bp)) {
> +	if (macb_dma64(info)) {
>  		struct macb_dma_desc_64 *desc_64;
> 
> -		desc_64 = macb_64b_desc(bp, desc);
> +		desc_64 = macb_64b_desc(desc);
>  		desc_64->addrh = upper_32_bits(addr);
>  		/* The low bits of RX address contain the RX_USED bit, clearing
>  		 * of which allows packet RX. Make sure the high bits are also
> @@ -1267,18 +1269,19 @@ static void macb_set_addr(struct macb *bp, 
> struct macb_dma_desc *desc, dma_addr_
>  	desc->addr = lower_32_bits(addr);
>  }
> 
> -static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc 
> *desc)
> +static dma_addr_t macb_get_addr(const struct macb_info *info,
> +				struct macb_dma_desc *desc)
>  {
>  	dma_addr_t addr = 0;
> 
> -	if (macb_dma64(bp)) {
> +	if (macb_dma64(info)) {
>  		struct macb_dma_desc_64 *desc_64;
> 
> -		desc_64 = macb_64b_desc(bp, desc);
> +		desc_64 = macb_64b_desc(desc);
>  		addr = ((u64)(desc_64->addrh) << 32);
>  	}
>  	addr |= MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
> -	if (macb_dma_ptp(bp))
> +	if (macb_dma_ptp(info))
>  		addr &= ~GEM_BIT(DMA_RXVALID);
>  	return addr;
>  }
> @@ -1378,7 +1381,7 @@ static void macb_tx_error_task(struct work_struct 
> *work)
> 
>  	/* Set end of TX queue */
>  	desc = macb_tx_desc(queue, 0);
> -	macb_set_addr(bp, desc, 0);
> +	macb_set_addr(&bp->info, desc, 0);
>  	desc->ctrl = MACB_BIT(TX_USED);
> 
>  	/* Make descriptor updates visible to hardware */
> @@ -1563,7 +1566,7 @@ static void gem_rx_refill(struct macb_queue 
> *queue)
>  			 * make sure ctrl is cleared first to avoid a race.
>  			 */
>  			dma_wmb();
> -			macb_set_addr(bp, desc, paddr);
> +			macb_set_addr(&bp->info, desc, paddr);
> 
>  			/* Properly align Ethernet header.
>  			 *
> @@ -1637,7 +1640,7 @@ static int gem_rx(struct macb_queue *queue, 
> struct napi_struct *napi,
>  		rmb();
> 
>  		rxused = (desc->addr & MACB_BIT(RX_USED)) ? true : false;
> -		addr = macb_get_addr(bp, desc);
> +		addr = macb_get_addr(&bp->info, desc);
> 
>  		if (!rxused)
>  			break;
> @@ -1799,7 +1802,7 @@ static inline void macb_init_rx_ring(struct 
> macb_queue *queue)
>  	addr = rxq->buffers_dma;
>  	for (i = 0; i < bp->ctx->rx_ring_size; i++) {
>  		desc = macb_rx_desc(queue, i);
> -		macb_set_addr(bp, desc, addr);
> +		macb_set_addr(&bp->info, desc, addr);
>  		desc->ctrl = 0;
>  		addr += bp->ctx->rx_buffer_size;
>  	}
> @@ -1952,7 +1955,7 @@ static void macb_tx_restart(struct macb_queue 
> *queue)
>  	if (txq->head == txq->tail)
>  		goto out_tx_ptr_unlock;
> 
> -	tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(bp);
> +	tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(&bp->info);
>  	tbqp = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, tbqp));
>  	head_idx = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, 
> txq->head));
> 
> @@ -2129,7 +2132,7 @@ static int macb_interrupt_misc(struct macb_queue 
> *queue, u32 status)
>  	if (status & MACB_BIT(ISR_ROVR)) {
>  		/* We missed at least one packet */
>  		spin_lock(&bp->stats_lock);
> -		if (macb_is_gem(bp))
> +		if (macb_is_gem(&bp->info))
>  			bp->hw_stats.gem.rx_overruns++;
>  		else
>  			bp->hw_stats.macb.rx_overruns++;
> @@ -2143,7 +2146,7 @@ static int macb_interrupt_misc(struct macb_queue 
> *queue, u32 status)
>  		macb_queue_isr_clear(bp, queue, MACB_BIT(HRESP));
>  	}
> 
> -	if (macb_is_gem(bp)) {
> +	if (macb_is_gem(&bp->info)) {
>  		if (status & GEM_BIT(WOL))
>  			gem_wol_interrupt(queue, status);
>  	} else {
> @@ -2381,7 +2384,7 @@ static unsigned int macb_tx_map(struct macb *bp,
>  			ctrl |= MACB_BF(MSS_MFS, mss_mfs);
> 
>  		/* Set TX buffer descriptor */
> -		macb_set_addr(bp, desc, tx_skb->mapping);
> +		macb_set_addr(&bp->info, desc, tx_skb->mapping);
>  		/* desc->addr must be visible to hardware before clearing
>  		 * 'TX_USED' bit in desc->ctrl.
>  		 */
> @@ -2532,7 +2535,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff 
> *skb,
>  		return ret;
>  	}
> 
> -	if (macb_dma_ptp(bp) &&
> +	if (macb_dma_ptp(&bp->info) &&
>  	    (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
>  		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
> 
> @@ -2619,7 +2622,7 @@ static unsigned int macb_rx_buffer_size(struct 
> macb *bp, unsigned int mtu)
>  {
>  	unsigned int size;
> 
> -	if (!macb_is_gem(bp)) {
> +	if (!macb_is_gem(&bp->info)) {
>  		size = MACB_RX_BUFFER_SIZE;
>  	} else {
>  		size = mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;
> @@ -2660,7 +2663,7 @@ static void gem_free_rx_buffers(struct macb *bp)
>  				continue;
> 
>  			desc = macb_rx_desc(queue, i);
> -			addr = macb_get_addr(bp, desc);
> +			addr = macb_get_addr(&bp->info, desc);
> 
>  			dma_unmap_single(&bp->pdev->dev, addr,
>  					 bp->ctx->rx_buffer_size,
> @@ -2689,13 +2692,13 @@ static void macb_free_rx_buffers(struct macb 
> *bp)
> 
>  static unsigned int macb_tx_ring_size_per_queue(struct macb *bp)
>  {
> -	return macb_dma_desc_get_size(bp) * bp->ctx->tx_ring_size +
> +	return macb_dma_desc_get_size(&bp->info) * bp->ctx->tx_ring_size +
>  		bp->tx_bd_rd_prefetch;
>  }
> 
>  static unsigned int macb_rx_ring_size_per_queue(struct macb *bp)
>  {
> -	return macb_dma_desc_get_size(bp) * bp->ctx->rx_ring_size +
> +	return macb_dma_desc_get_size(&bp->info) * bp->ctx->rx_ring_size +
>  		bp->rx_bd_rd_prefetch;
>  }
> 
> @@ -2859,7 +2862,7 @@ static void gem_init_rings(struct macb *bp)
>  		txq = &bp->ctx->txq[q];
>  		for (i = 0; i < bp->ctx->tx_ring_size; i++) {
>  			desc = macb_tx_desc(queue, i);
> -			macb_set_addr(bp, desc, 0);
> +			macb_set_addr(&bp->info, desc, 0);
>  			desc->ctrl = MACB_BIT(TX_USED);
>  		}
>  		desc->ctrl |= MACB_BIT(TX_WRAP);
> @@ -2880,7 +2883,7 @@ static void macb_init_rings(struct macb *bp)
> 
>  	for (i = 0; i < bp->ctx->tx_ring_size; i++) {
>  		desc = macb_tx_desc(&bp->queues[0], i);
> -		macb_set_addr(bp, desc, 0);
> +		macb_set_addr(&bp->info, desc, 0);
>  		desc->ctrl = MACB_BIT(TX_USED);
>  	}
>  	txq->head = 0;
> @@ -2949,7 +2952,7 @@ static u32 macb_mdc_clk_div(struct macb *bp)
>  	u32 config;
>  	unsigned long pclk_hz;
> 
> -	if (macb_is_gem(bp))
> +	if (macb_is_gem(&bp->info))
>  		return gem_mdc_clk_div(bp);
> 
>  	pclk_hz = clk_get_rate(bp->pclk);
> @@ -2971,7 +2974,7 @@ static u32 macb_mdc_clk_div(struct macb *bp)
>   */
>  static u32 macb_dbw(struct macb *bp)
>  {
> -	if (!macb_is_gem(bp))
> +	if (!macb_is_gem(&bp->info))
>  		return 0;
> 
>  	switch (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1))) {
> @@ -3000,7 +3003,7 @@ static void macb_configure_dma(struct macb *bp)
>  	u32 dmacfg;
> 
>  	buffer_size = bp->ctx->rx_buffer_size / RX_BUFFER_MULTIPLE;
> -	if (macb_is_gem(bp)) {
> +	if (macb_is_gem(&bp->info)) {
>  		dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
>  		for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
>  			if (q)
> @@ -3024,9 +3027,9 @@ static void macb_configure_dma(struct macb *bp)
>  			dmacfg &= ~GEM_BIT(TXCOEN);
> 
>  		dmacfg &= ~GEM_BIT(ADDR64);
> -		if (macb_dma64(bp))
> +		if (macb_dma64(&bp->info))
>  			dmacfg |= GEM_BIT(ADDR64);
> -		if (macb_dma_ptp(bp))
> +		if (macb_dma_ptp(&bp->info))
>  			dmacfg |= GEM_BIT(RXEXT) | GEM_BIT(TXEXT);
>  		netdev_dbg(bp->netdev, "Cadence configure DMA with 0x%08x\n",
>  			   dmacfg);
> @@ -3054,7 +3057,7 @@ static void macb_init_hw(struct macb *bp)
>  		config |= MACB_BIT(BIG);	/* Receive oversized frames */
>  	if (bp->netdev->flags & IFF_PROMISC)
>  		config |= MACB_BIT(CAF);	/* Copy All Frames */
> -	else if (macb_is_gem(bp) && bp->netdev->features & NETIF_F_RXCSUM)
> +	else if (macb_is_gem(&bp->info) && bp->netdev->features & 
> NETIF_F_RXCSUM)
>  		config |= GEM_BIT(RXCOEN);
>  	if (!(bp->netdev->flags & IFF_BROADCAST))
>  		config |= MACB_BIT(NBC);	/* No BroadCast */
> @@ -3162,14 +3165,14 @@ static void macb_set_rx_mode(struct net_device 
> *netdev)
>  		cfg |= MACB_BIT(CAF);
> 
>  		/* Disable RX checksum offload */
> -		if (macb_is_gem(bp))
> +		if (macb_is_gem(&bp->info))
>  			cfg &= ~GEM_BIT(RXCOEN);
>  	} else {
>  		/* Disable promiscuous mode */
>  		cfg &= ~MACB_BIT(CAF);
> 
>  		/* Enable RX checksum offload only if requested */
> -		if (macb_is_gem(bp) && netdev->features & NETIF_F_RXCSUM)
> +		if (macb_is_gem(&bp->info) && netdev->features & NETIF_F_RXCSUM)
>  			cfg |= GEM_BIT(RXCOEN);
>  	}
> 
> @@ -3452,7 +3455,7 @@ static void macb_get_stats(struct net_device 
> *netdev,
>  	struct macb_stats *hwstat = &bp->hw_stats.macb;
> 
>  	netdev_stats_to_stats64(nstat, &bp->netdev->stats);
> -	if (macb_is_gem(bp)) {
> +	if (macb_is_gem(&bp->info)) {
>  		gem_get_stats(bp, nstat);
>  		return;
>  	}
> @@ -3700,7 +3703,7 @@ static void macb_get_regs(struct net_device 
> *netdev, struct ethtool_regs *regs,
> 
>  	if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
>  		regs_buff[12] = macb_or_gem_readl(bp, USRIO);
> -	if (macb_is_gem(bp))
> +	if (macb_is_gem(&bp->info))
>  		regs_buff[13] = gem_readl(bp, DMACFG);
>  }
> 
> @@ -3832,7 +3835,7 @@ static int gem_get_ts_info(struct net_device 
> *netdev,
>  {
>  	struct macb *bp = netdev_priv(netdev);
> 
> -	if (!macb_dma_ptp(bp)) {
> +	if (!macb_dma_ptp(&bp->info)) {
>  		ethtool_op_get_ts_info(netdev, info);
>  		return 0;
>  	}
> @@ -3933,7 +3936,7 @@ static void gem_prog_cmp_regs(struct macb *bp, 
> struct ethtool_rx_flow_spec *fs)
>  	bool cmp_b = false;
>  	bool cmp_c = false;
> 
> -	if (!macb_is_gem(bp))
> +	if (!macb_is_gem(&bp->info))
>  		return;
> 
>  	tp4sp_v = &(fs->h_u.tcp_ip4_spec);
> @@ -4294,7 +4297,7 @@ static inline void macb_set_txcsum_feature(struct 
> macb *bp,
>  {
>  	u32 val;
> 
> -	if (!macb_is_gem(bp))
> +	if (!macb_is_gem(&bp->info))
>  		return;
> 
>  	val = gem_readl(bp, DMACFG);
> @@ -4312,7 +4315,7 @@ static inline void macb_set_rxcsum_feature(struct 
> macb *bp,
>  	struct net_device *netdev = bp->netdev;
>  	u32 val;
> 
> -	if (!macb_is_gem(bp))
> +	if (!macb_is_gem(&bp->info))
>  		return;
> 
>  	val = gem_readl(bp, NCFGR);
> @@ -4327,7 +4330,7 @@ static inline void macb_set_rxcsum_feature(struct 
> macb *bp,
>  static inline void macb_set_rxflow_feature(struct macb *bp,
>  					   netdev_features_t features)
>  {
> -	if (!macb_is_gem(bp))
> +	if (!macb_is_gem(&bp->info))
>  		return;
> 
>  	gem_enable_flow_filters(bp, !!(features & NETIF_F_NTUPLE));
> @@ -4654,7 +4657,7 @@ static void macb_configure_caps(struct macb *bp,
>  			bp->caps |= MACB_CAPS_FIFO_MODE;
>  		if (GEM_BFEXT(PBUF_RSC, gem_readl(bp, DCFG6)))
>  			bp->caps |= MACB_CAPS_RSC;
> -		if (gem_has_ptp(bp)) {
> +		if (gem_has_ptp(&bp->info)) {
>  			if (!GEM_BFEXT(TSU, gem_readl(bp, DCFG5)))
>  				dev_err(&bp->pdev->dev,
>  					"GEM doesn't support hardware ptp.\n");
> @@ -4866,7 +4869,7 @@ static int macb_init_dflt(struct platform_device 
> *pdev)
>  	netdev->netdev_ops = &macb_netdev_ops;
> 
>  	/* setup appropriated routines according to adapter type */
> -	if (macb_is_gem(bp)) {
> +	if (macb_is_gem(&bp->info)) {
>  		bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers;
>  		bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers;
>  		bp->macbgem_ops.mog_init_rings = gem_init_rings;
> @@ -4895,7 +4898,7 @@ static int macb_init_dflt(struct platform_device 
> *pdev)
>  		netdev->hw_features |= MACB_NETIF_LSO;
> 
>  	/* Checksum offload is only available on gem with packet buffer */
> -	if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE))
> +	if (macb_is_gem(&bp->info) && !(bp->caps & MACB_CAPS_FIFO_MODE))
>  		netdev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
>  	if (bp->caps & MACB_CAPS_SG_DISABLED)
>  		netdev->hw_features &= ~NETIF_F_SG;
> @@ -5021,7 +5024,7 @@ static int at91ether_alloc_coherent(struct macb 
> *bp)
> 
>  	rxq->ring = dma_alloc_coherent(&bp->pdev->dev,
>  				       (AT91ETHER_MAX_RX_DESCR *
> -					macb_dma_desc_get_size(bp)),
> +					macb_dma_desc_get_size(&bp->info)),
>  				       &rxq->ring_dma, GFP_KERNEL);
>  	if (!rxq->ring)
>  		return -ENOMEM;
> @@ -5034,7 +5037,7 @@ static int at91ether_alloc_coherent(struct macb 
> *bp)
>  	if (!rxq->buffers) {
>  		dma_free_coherent(&bp->pdev->dev,
>  				  AT91ETHER_MAX_RX_DESCR *
> -				  macb_dma_desc_get_size(bp),
> +				  macb_dma_desc_get_size(&bp->info),
>  				  rxq->ring, rxq->ring_dma);
>  		rxq->ring = NULL;
>  		return -ENOMEM;
> @@ -5050,7 +5053,7 @@ static void at91ether_free_coherent(struct macb 
> *bp)
>  	if (rxq->ring) {
>  		dma_free_coherent(&bp->pdev->dev,
>  				  AT91ETHER_MAX_RX_DESCR *
> -				  macb_dma_desc_get_size(bp),
> +				  macb_dma_desc_get_size(&bp->info),
>  				  rxq->ring, rxq->ring_dma);
>  		rxq->ring = NULL;
>  	}
> @@ -5081,7 +5084,7 @@ static int at91ether_start(struct macb *bp)
>  	addr = rxq->buffers_dma;
>  	for (i = 0; i < AT91ETHER_MAX_RX_DESCR; i++) {
>  		desc = macb_rx_desc(queue, i);
> -		macb_set_addr(bp, desc, addr);
> +		macb_set_addr(&bp->info, desc, addr);
>  		desc->ctrl = 0;
>  		addr += AT91ETHER_MAX_RBUFF_SZ;
>  	}
> @@ -5609,13 +5612,13 @@ static int macb_alloc_tieoff(struct macb *bp)
>  		return 0;
> 
>  	bp->rx_ring_tieoff = dma_alloc_coherent(&bp->pdev->dev,
> -						macb_dma_desc_get_size(bp),
> +						macb_dma_desc_get_size(&bp->info),
>  						&bp->rx_ring_tieoff_dma,
>  						GFP_KERNEL);
>  	if (!bp->rx_ring_tieoff)
>  		return -ENOMEM;
> 
> -	macb_set_addr(bp, bp->rx_ring_tieoff,
> +	macb_set_addr(&bp->info, bp->rx_ring_tieoff,
>  		      MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED));
> 
>  	bp->rx_ring_tieoff->ctrl = 0;
> @@ -5628,7 +5631,7 @@ static void macb_free_tieoff(struct macb *bp)
>  	if (!bp->rx_ring_tieoff)
>  		return;
> 
> -	dma_free_coherent(&bp->pdev->dev, macb_dma_desc_get_size(bp),
> +	dma_free_coherent(&bp->pdev->dev, macb_dma_desc_get_size(&bp->info),
>  			  bp->rx_ring_tieoff,
>  			  bp->rx_ring_tieoff_dma);
>  	bp->rx_ring_tieoff = NULL;
> @@ -6012,12 +6015,12 @@ static int macb_probe(struct platform_device 
> *pdev)
>  		val = GEM_BFEXT(RXBD_RDBUFF, gem_readl(bp, DCFG10));
>  		if (val)
>  			bp->rx_bd_rd_prefetch = (2 << (val - 1)) *
> -						macb_dma_desc_get_size(bp);
> +						macb_dma_desc_get_size(&bp->info);
> 
>  		val = GEM_BFEXT(TXBD_RDBUFF, gem_readl(bp, DCFG10));
>  		if (val)
>  			bp->tx_bd_rd_prefetch = (2 << (val - 1)) *
> -						macb_dma_desc_get_size(bp);
> +						macb_dma_desc_get_size(&bp->info);
>  	}
> 
>  	bp->rx_intr_mask = MACB_RX_INT_FLAGS;
> @@ -6062,8 +6065,9 @@ static int macb_probe(struct platform_device 
> *pdev)
>  	INIT_DELAYED_WORK(&bp->tx_lpi_work, macb_tx_lpi_work_fn);
> 
>  	netdev_info(netdev, "Cadence %s rev 0x%08x at 0x%08lx irq %d 
> (%pM)\n",
> -		    macb_is_gem(bp) ? "GEM" : "MACB", macb_readl(bp, MID),
> -		    netdev->base_addr, netdev->irq, netdev->dev_addr);
> +		    macb_is_gem(&bp->info) ? "GEM" : "MACB",
> +		    macb_readl(bp, MID), netdev->base_addr, netdev->irq,
> +		    netdev->dev_addr);
> 
>  	pm_runtime_put_autosuspend(&bp->pdev->dev);
> 
> @@ -6190,7 +6194,7 @@ static int __maybe_unused macb_suspend(struct 
> device *dev)
>  			tmp |= MACB_BFEXT(IP, ifa_local);
>  		}
> 
> -		if (macb_is_gem(bp)) {
> +		if (macb_is_gem(&bp->info)) {
>  			queue_writel(bp->queues, IER, GEM_BIT(WOL));
>  			gem_writel(bp, WOL, tmp);
>  		} else {
> @@ -6252,7 +6256,7 @@ static int __maybe_unused macb_resume(struct 
> device *dev)
>  	if (bp->wol & MACB_WOL_ENABLED) {
>  		spin_lock_irqsave(&bp->lock, flags);
>  		/* Disable WoL */
> -		if (macb_is_gem(bp)) {
> +		if (macb_is_gem(&bp->info)) {
>  			queue_writel(bp->queues, IDR, GEM_BIT(WOL));
>  			gem_writel(bp, WOL, 0);
>  		} else {
> @@ -6280,7 +6284,7 @@ static int __maybe_unused macb_resume(struct 
> device *dev)
>  	for (q = 0, queue = bp->queues; q < bp->num_queues;
>  	     ++q, ++queue) {
>  		if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) {
> -			if (macb_is_gem(bp))
> +			if (macb_is_gem(&bp->info))
>  				gem_init_rx_ring(queue);
>  			else
>  				macb_init_rx_ring(queue);
> diff --git a/drivers/net/ethernet/cadence/macb_ptp.c 
> b/drivers/net/ethernet/cadence/macb_ptp.c
> index e5195d7dac1d..8765c4782509 100644
> --- a/drivers/net/ethernet/cadence/macb_ptp.c
> +++ b/drivers/net/ethernet/cadence/macb_ptp.c
> @@ -28,10 +28,10 @@
>  static struct macb_dma_desc_ptp *macb_ptp_desc(struct macb *bp,
>  					       struct macb_dma_desc *desc)
>  {
> -	if (!macb_dma_ptp(bp))
> +	if (!macb_dma_ptp(&bp->info))
>  		return NULL;
> 
> -	if (macb_dma64(bp))
> +	if (macb_dma64(&bp->info))
>  		return (struct macb_dma_desc_ptp *)
>  				((u8 *)desc + sizeof(struct macb_dma_desc)
>  				+ sizeof(struct macb_dma_desc_64));
> @@ -384,7 +384,7 @@ int gem_get_hwtst(struct net_device *netdev,
>  	struct macb *bp = netdev_priv(netdev);
> 
>  	*tstamp_config = bp->tstamp_config;
> -	if (!macb_dma_ptp(bp))
> +	if (!macb_dma_ptp(&bp->info))
>  		return -EOPNOTSUPP;
> 
>  	return 0;
> @@ -411,7 +411,7 @@ int gem_set_hwtst(struct net_device *netdev,
>  	struct macb *bp = netdev_priv(netdev);
>  	u32 regval;
> 
> -	if (!macb_dma_ptp(bp))
> +	if (!macb_dma_ptp(&bp->info))
>  		return -EOPNOTSUPP;
> 
>  	switch (tstamp_config->tx_type) {

Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>

Thanks
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v4 09/15] net: macb: make `struct macb` subset reachable from macb_context struct
From: Nicolai Buchwitz @ 2026-07-19 10:40 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-9-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> For parallel MACB context to start become a reality, many functions 
> need
> to stop operating on bp->ctx (the currently active context) and instead
> work on a context they get passed. That context might be
> (1) the new one that is getting allocated and initialised, or,
> (2) the old one to be freed.
> 
> To reduce bug surface area, we will taint those functions to *only* 
> take
> a context and no `struct macb *bp`. That way, no bug of using `bp->ctx`
> instead of `ctx` will ever occur.
> 
> For that, we need to embed a subset of `struct macb` information into
> each context so that all helpers can still do their jobs. That subset
> must be constant once probe is completed. Do this by taking a pointer
> to a subset of macb called `struct macb_info`.
> 
> That subset is accessible from context (ctx->info->caps) or
> from bp (bp->caps) using `-fms-extensions` option, thanks to
> commit c4781dc3d1cf ("Kbuild: enable -fms-extensions").
> https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html
> 
> Add the structure and assign ctx->info at alloc,
> but nothing uses it yet.
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/net/ethernet/cadence/macb.h      | 31 
> ++++++++++++++++++++++---------
>  drivers/net/ethernet/cadence/macb_main.c |  5 +++++
>  2 files changed, 27 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb.h 
> b/drivers/net/ethernet/cadence/macb.h
> index 452b2c8f8641..2db01fa81559 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -1290,6 +1290,17 @@ struct ethtool_rx_fs_list {
>  	unsigned int count;
>  };
> 
> +struct macb_info {
> +	struct platform_device	*pdev;
> +	struct net_device	*netdev;
> +	struct macb_or_gem_ops	macbgem_ops;
> +	unsigned int		num_queues;
> +	u32			caps;
> +	int			rx_bd_rd_prefetch;
> +	int			tx_bd_rd_prefetch;
> +	struct queue_stats	*queue_stats[MACB_MAX_QUEUES];
> +};
> +
>  struct macb_rxq {
>  	struct macb_dma_desc	*ring;		/* MACB & GEM */
>  	dma_addr_t		ring_dma;	/* MACB & GEM */
> @@ -1309,6 +1320,8 @@ struct macb_txq {
>  };
> 
>  struct macb_context {
> +	const struct macb_info	*info;
> +
>  	unsigned int		rx_buffer_size;
>  	unsigned int		rx_ring_size;
>  	unsigned int		tx_ring_size;
> @@ -1324,6 +1337,15 @@ struct macb {
>  	u32	(*macb_reg_readl)(struct macb *bp, int offset);
>  	void	(*macb_reg_writel)(struct macb *bp, int offset, u32 value);
> 
> +	/*
> +	 * Give direct access (bp->caps) and
> +	 * allow taking a pointer to it (&bp->info) for contexts.
> +	 */
> +	union {
> +		struct macb_info;
> +		struct macb_info info;
> +	};
> +
>  	/*
>  	 * Context stores all its parameters.
>  	 * But we must remember them across closure.
> @@ -1335,17 +1357,14 @@ struct macb {
>  	struct macb_dma_desc	*rx_ring_tieoff;
>  	dma_addr_t		rx_ring_tieoff_dma;
> 
> -	unsigned int		num_queues;
>  	struct macb_queue	queues[MACB_MAX_QUEUES];
> 
>  	spinlock_t		lock;
> -	struct platform_device	*pdev;
>  	struct clk		*pclk;
>  	struct clk		*hclk;
>  	struct clk		*tx_clk;
>  	struct clk		*rx_clk;
>  	struct clk		*tsu_clk;
> -	struct net_device	*netdev;
>  	/* Protects hw_stats and ethtool_stats */
>  	spinlock_t		stats_lock;
>  	union {
> @@ -1353,15 +1372,12 @@ struct macb {
>  		struct gem_stats	gem;
>  	}			hw_stats;
> 
> -	struct macb_or_gem_ops	macbgem_ops;
> -
>  	struct mii_bus		*mii_bus;
>  	struct phylink		*phylink;
>  	struct phylink_config	phylink_config;
>  	struct phylink_pcs	phylink_usx_pcs;
>  	struct phylink_pcs	phylink_sgmii_pcs;
> 
> -	u32			caps;
>  	unsigned int		dma_burst_length;
> 
>  	phy_interface_t		phy_interface;
> @@ -1404,9 +1420,6 @@ struct macb {
>  	struct delayed_work	tx_lpi_work;
>  	u32			tx_lpi_timer;
> 
> -	int	rx_bd_rd_prefetch;
> -	int	tx_bd_rd_prefetch;
> -
>  	u32	rx_intr_mask;
> 
>  	struct macb_pm_data pm_data;
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index 29bf3c497f2a..40ebe20bb40c 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -3211,6 +3211,8 @@ static int macb_open(struct net_device *netdev)
>  		goto pm_exit;
>  	}
> 
> +	bp->ctx->info = &bp->info;
> +
>  	/* RX buffers initialization */
>  	bp->ctx->rx_buffer_size = macb_rx_buffer_size(bp, netdev->mtu);
>  	bp->ctx->rx_ring_size = bp->configured_rx_ring_size;
> @@ -5870,6 +5872,7 @@ static int macb_probe(struct platform_device 
> *pdev)
>  	u32 wtrmrk_rst_val;
>  	void __iomem *mem;
>  	struct macb *bp;
> +	unsigned int q;
>  	int num_queues;
>  	bool native_io;
>  	int err, val;
> @@ -5915,6 +5918,8 @@ static int macb_probe(struct platform_device 
> *pdev)
>  	bp->netdev = netdev;
>  	bp->regs = mem;
>  	bp->native_io = native_io;
> +	for (q = 0; q < MACB_MAX_QUEUES; q++)
> +		bp->info.queue_stats[q] = &bp->queues[q].stats;
>  	if (native_io) {
>  		bp->macb_reg_readl = hw_readl_native;
>  		bp->macb_reg_writel = hw_writel_native;

Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>

Thanks,
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v4 08/15] net: macb: avoid macb_init_rx_buffer_size() modifying state
From: Nicolai Buchwitz @ 2026-07-19 10:39 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-8-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> macb_init_rx_buffer_size() takes the macb private data struct and
> overrides its bp->ctx->rx_buffer_size. To make it usable with multiple
> contexts, make it return its value.
> 
> Also, move the `bufsz` computation into it. The value is only used if
> GEM, and for historical reason it currently lives in macb_open().
> 
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/net/ethernet/cadence/macb_main.c | 26 
> +++++++++++++-------------
>  1 file changed, 13 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb_main.c 
> b/drivers/net/ethernet/cadence/macb_main.c
> index d50d8520231c..29bf3c497f2a 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -2615,25 +2615,26 @@ static netdev_tx_t macb_start_xmit(struct 
> sk_buff *skb,
>  	return ret;
>  }
> 
> -static void macb_init_rx_buffer_size(struct macb *bp, size_t size)
> +static unsigned int macb_rx_buffer_size(struct macb *bp, unsigned int 
> mtu)
>  {
> -	if (!macb_is_gem(bp)) {
> -		bp->ctx->rx_buffer_size = MACB_RX_BUFFER_SIZE;
> -	} else {
> -		bp->ctx->rx_buffer_size = MIN(size, RX_BUFFER_MAX);
> +	unsigned int size;
> 
> -		if (bp->ctx->rx_buffer_size % RX_BUFFER_MULTIPLE) {
> +	if (!macb_is_gem(bp)) {
> +		size = MACB_RX_BUFFER_SIZE;
> +	} else {
> +		size = mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;
> +		size = MIN(size, RX_BUFFER_MAX);
> +
> +		if (size % RX_BUFFER_MULTIPLE) {
>  			netdev_dbg(bp->netdev,
>  				   "RX buffer must be multiple of %d bytes, expanding\n",
>  				   RX_BUFFER_MULTIPLE);
> -			bp->ctx->rx_buffer_size =
> -				roundup(bp->ctx->rx_buffer_size,
> -					RX_BUFFER_MULTIPLE);
> +			size = roundup(size, RX_BUFFER_MULTIPLE);
>  		}
>  	}
> 
> -	netdev_dbg(bp->netdev, "mtu [%u] rx_buffer_size [%u]\n",
> -		   bp->netdev->mtu, bp->ctx->rx_buffer_size);
> +	netdev_dbg(bp->netdev, "mtu [%u] rx_buffer_size [%u]\n", mtu, size);
> +	return size;
>  }
> 
>  static void gem_free_rx_buffers(struct macb *bp)
> @@ -3193,7 +3194,6 @@ static void macb_set_rx_mode(struct net_device 
> *netdev)
> 
>  static int macb_open(struct net_device *netdev)
>  {
> -	size_t bufsz = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;
>  	struct macb *bp = netdev_priv(netdev);
>  	struct macb_queue *queue;
>  	unsigned int q;
> @@ -3212,7 +3212,7 @@ static int macb_open(struct net_device *netdev)
>  	}
> 
>  	/* RX buffers initialization */
> -	macb_init_rx_buffer_size(bp, bufsz);
> +	bp->ctx->rx_buffer_size = macb_rx_buffer_size(bp, netdev->mtu);
>  	bp->ctx->rx_ring_size = bp->configured_rx_ring_size;
>  	bp->ctx->tx_ring_size = bp->configured_tx_ring_size;

Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>

Thanks,
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v4 07/15] net: macb: introduce macb_context struct for buffer management
From: Nicolai Buchwitz @ 2026-07-19 10:38 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-7-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> Whenever an operation requires buffer realloc, we close the interface,
> update parameters and reopen. To improve reliability under memory
> pressure, we should rather alloc new buffers, reconfigure HW and free
> old buffers. This requires MACB to support having multiple "contexts"
> in parallel.
> 
> Introduce this concept by adding the macb_context struct, which owns 
> all
> queue buffers and the parameters associated. We do not yet support
> multiple contexts in parallel, because all functions access bp->ctx
> (the currently active context) directly.
> 
> Steps:
> 
>  - Introduce `struct macb_context` and its children `struct macb_rxq`
>    and `struct macb_txq`. Context fields are stolen from `struct macb`
>    and rxq/txq fields are from `struct macb_queue`.
> 
>    Making it two separate structs per queue simplifies accesses: we 
> grab
>    a txq/rxq local variable and access fields like txq->head instead of
>    queue->tx_head. It also anecdotally improves data locality.
> 
>  - macb_init_dflt() / macb_get_ringparam() do not access
>    bp->ctx->{rx,tx}_ring_size as they will/might run while interface is
>    offline and ctx is not NULL. Instead, introduce
>    bp->configured_{rx,tx}_ring_size which get updated on user requests.

nit: In the commit message: "ctx is not NULL" should be "ctx is NULL".

> 
>  - macb_open() starts by allocating bp->ctx. It gets freed in the
>    open error codepath or by macb_close().
> 
>  - Guided by compile errors, update all codepaths. Most diff is 
> changing
>    `queue->tx_*` to `txq->*` and `queue->rx_*` to `rxq->*`, with a new
>    local variable. Also rx_buffer_size / rx_ring_size / tx_ring_size
>    move from bp to bp->ctx.
> 
>    Introduce two helpers macb_txq|rxq() functions to convert macb_queue
>    pointers.
> 
>  - macb_get_regs() is tweaked to support being ran while interface is
>    offline (and context is NULL). Use default values at zero and
>    override them only if context is present.
> 
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---

> [...]

Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>

Thanks,
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v4 02/15] net: macb: unify device pointer naming convention
From: Nicolai Buchwitz @ 2026-07-19 10:32 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Conor Dooley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
	netdev, linux-kernel, Nicolas Ferre, Claudiu Beznea,
	Paolo Valerio, Vladimir Kondratiev, Gregory CLEMENT,
	Benoît Monin, Tawfik Bayouk, Thomas Petazzoni,
	Maxime Chevallier
In-Reply-To: <20260717-macb-context-v4-2-0acbe7f10cdb@bootlin.com>

Hi Théo

On 17.7.2026 21:48, Théo Lebrun wrote:
> Here are all device pointer variable permutations inside MACB:
> 
>    struct device *dev;
>    struct net_device *dev;
>    struct net_device *ndev;
>    struct net_device *netdev;
>    struct pci_dev *pdev;              // inside macb_pci.c
>    struct phy_device *phy;
>    struct phy_device *phydev;
>    struct platform_device *pdev;
>    struct platform_device *plat_dev;  // inside macb_pci.c
> 
> Unify to this convention:
> 
>    struct device *dev;
>    struct net_device *netdev;
>    struct pci_dev *pci;
>    struct phy_device *phydev;
>    struct platform_device *pdev;
> 
> Ensure nothing slipped through using ctags tooling:
> 
> ⟩ ctags -o - --kinds-c='{local}{member}{parameter}' \
>     --fields='{typeref}' drivers/net/ethernet/cadence/* | \
>   awk -F"\t" '
>     $NF~/struct:.*(device|dev) / {print $NF, $1}' | \
>   sort -u
> typeref:struct:device * dev
> typeref:struct:in_device * idev        // ignored
> typeref:struct:net_device * netdev
> typeref:struct:pci_dev * pci
> typeref:struct:phy_device * phydev
> typeref:struct:platform_device * pdev
> 
> Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/net/ethernet/cadence/macb.h      |  20 +-
>  drivers/net/ethernet/cadence/macb_main.c | 636 
> ++++++++++++++++---------------
>  drivers/net/ethernet/cadence/macb_pci.c  |  46 +--
>  drivers/net/ethernet/cadence/macb_ptp.c  |  18 +-
>  4 files changed, 361 insertions(+), 359 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb.h 
> b/drivers/net/ethernet/cadence/macb.h
> index 2de56017ee0d..9857df5b57f0 100644
> --- a/drivers/net/ethernet/cadence/macb.h
> +++ b/drivers/net/ethernet/cadence/macb.h
> @@ -1207,11 +1207,11 @@ struct macb_or_gem_ops {
> 
>  /* MACB-PTP interface: adapt to platform needs. */
>  struct macb_ptp_info {
> -	void (*ptp_init)(struct net_device *ndev);
> -	void (*ptp_remove)(struct net_device *ndev);
> +	void (*ptp_init)(struct net_device *netdev);
> +	void (*ptp_remove)(struct net_device *netdev);
>  	s32 (*get_ptp_max_adj)(void);
>  	unsigned int (*get_tsu_rate)(struct macb *bp);
> -	int (*get_ts_info)(struct net_device *dev,
> +	int (*get_ts_info)(struct net_device *netdev,
>  			   struct kernel_ethtool_ts_info *info);
>  	int (*get_hwtst)(struct net_device *netdev,
>  			 struct kernel_hwtstamp_config *tstamp_config);
> @@ -1326,7 +1326,7 @@ struct macb {
>  	struct clk		*tx_clk;
>  	struct clk		*rx_clk;
>  	struct clk		*tsu_clk;
> -	struct net_device	*dev;
> +	struct net_device	*netdev;

Looks like you have missed the one in macb_free(), from commit 
27f575836cfe ("net:
macb: drop in-flight Tx SKBs on close"):

	bp->dev->stats.tx_dropped += dropped;

This breaks the build until patch 7 rewrites thatline, which breaks 
bisection.

> [...]

Thanks,
Nicolai

^ permalink raw reply

* Re: [PATCH net-next v2 2/2] net: dsa: mv88e6xxx: embedded PTP timestamp support
From: Vladimir Oltean @ 2026-07-19 10:12 UTC (permalink / raw)
  To: Luke Howard
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Vivien Didelot, Gregory CLEMENT, Andrew Lunn, Richard Cochran,
	Cedric Jehasse, Kieran Tyrrell, Max Holtmann, Max Hunter,
	Christoph Mellauner, Simon Gapp, netdev, linux-kernel
In-Reply-To: <20260710-mv88e6xxx-ptp-fixes-v2-2-af97c38df247@padl.com>

On Fri, Jul 10, 2026 at 04:43:42PM +1000, Luke Howard wrote:
> @@ -6370,6 +6371,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
>  		.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
>  		.ptp_support = true,
>  		.ops = &mv88e6341_ops,
> +		.arr_ts_mode = offsetof(struct ptp_header, reserved2),
>  	},
>  
>  	[MV88E6350] = {
> @@ -6447,6 +6449,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
>  		.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
>  		.ptp_support = true,
>  		.ops = &mv88e6352_ops,
> +		.arr_ts_mode = offsetof(struct ptp_header, reserved2),
>  	},
>  	[MV88E6361] = {
>  		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361,
> diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.h b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
> index c359821d5a6ea..c25f53923e768 100644
> --- a/drivers/net/dsa/mv88e6xxx/hwtstamp.h
> +++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
> @@ -68,6 +68,20 @@
>  #define MV88E6XXX_PORT_PTP_CFG2_DEP_IRQ_EN		0x0002
>  #define MV88E6XXX_PORT_PTP_CFG2_ARR_IRQ_EN		0x0001
>  
> +/* Arrival Time Stamp Mode (ArrTSMode), CFG2 bits [15:8]: configures how the
> + * switch embeds the arrival time stamp (PTPArr0Time) into enabled PTP event
> + * frames.
> + *   0x00        frame modification disabled (time stamp read from registers)
> + *   0x01        append the 4-byte time stamp at the end of the frame,
> + *               growing the frame by four bytes
> + *   0x04..0xEF  overwrite the 4-byte time stamp in place, that many bytes past
> + *               the start of the PTP common header, without growing the frame
> + *               (offsetof(struct ptp_header, reserved2) targets the reserved
> + *               bytes of the header)
> + *   others      reserved
> + */
> +#define MV88E6XXX_PTP_ARR_TS_MODE_APPEND		0x01
> +
>  /* Offset 0x03: PTP LED Configuration */
>  #define MV88E6XXX_PORT_PTP_LED_CFG	0x03

We try to keep the data path protocol between the switch and the host
API compatible, and identifiable by /sys/class/net/<conduit>/dsa/tagging.
I would argue that the protocol where PTP timestamps are in registers,
vs where they are in PTP header reserved fields, vs where they are
appended as trailers, are 3 different protocols and should not be
presented as "edsa".

Two different switches both use the "edsa" protocol (say MV88E6390 and
MV88E6352), yet one expects timestamps in registers and the other in the
PTP header reserved fields. Strange.

In some instances, user space cares (though perhaps not imminently).
For example, libpcap/tcpdump might get confused by a non-zero arr_ts_mode.
Or an XDP/AF_XDP implementation of the edsa protocol might not understand
(because it has no access to this information) what arr_ts_mode the
underlying switch is configured for, and thus where to get timestamps from.

^ permalink raw reply

* [PATCH net-next] net: sfp: add quirk for HORACO copper SFP+ module
From: Aleksander Jan Bajkowski @ 2026-07-19 10:01 UTC (permalink / raw)
  To: linux, andrew, hkallweit1, davem, edumazet, kuba, pabeni, netdev,
	linux-kernel
  Cc: Aleksander Jan Bajkowski

Add quirk for a copper SFP+ module that identifies itself as "OEM"
"HC-10GE-113C". It uses RollBall protocol to talk to the PHY.

Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
---
 drivers/net/phy/sfp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index f520206734da..6c25b73c668a 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -594,6 +594,9 @@ static const struct sfp_quirk sfp_quirks[] = {
 
 	SFP_QUIRK_F("YV", "SFP+ONU-XGSPON", sfp_fixup_potron),
 
+	// HORACO HC-10GE-113C uses Rollball protocol to talk to the PHY.
+	SFP_QUIRK_F("OEM", "HC-10GE-113C", sfp_fixup_rollball),
+
 	// OEM SFP-GE-T is a 1000Base-T module with broken TX_FAULT indicator
 	SFP_QUIRK_F("OEM", "SFP-GE-T", sfp_fixup_ignore_tx_fault),
 
-- 
2.53.0


^ permalink raw reply related

* [syzbot] [kernfs?] possible deadlock in kernfs_remove_by_name_ns (2)
From: syzbot @ 2026-07-19 10:02 UTC (permalink / raw)
  To: driver-core, gregkh, linux-kernel, netdev, syzkaller-bugs, tj

Hello,

syzbot found the following issue on:

HEAD commit:    56d96fededd6 mpls: fix NULL deref in mpls_valid_fib_dump_r..
git tree:       net
console output: https://syzkaller.appspot.com/x/log.txt?x=136d4746580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=5c4196ba0e33631d
dashboard link: https://syzkaller.appspot.com/bug?extid=b50eba6bf6cd3f8ba7d0
compiler:       Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8

Unfortunately, I don't have any reproducer for this issue yet.

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/8a219d5f8172/disk-56d96fed.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/bc2c4acbf659/vmlinux-56d96fed.xz
kernel image: https://storage.googleapis.com/syzbot-assets/2f3b2152262f/bzImage-56d96fed.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+b50eba6bf6cd3f8ba7d0@syzkaller.appspotmail.com

======================================================
WARNING: possible circular locking dependency detected
syzkaller #0 Not tainted
------------------------------------------------------
kworker/0:1/21181 is trying to acquire lock:
ffff88801c295180 (&root->kernfs_rwsem){++++}-{4:4}, at: kernfs_remove_by_name_ns+0x4e/0x140 fs/kernfs/dir.c:1792

but task is already holding lock:
ffff88801c2952a0 (&root->kernfs_supers_rwsem){++++}-{4:4}, at: kernfs_remove_by_name_ns+0x3f/0x140 fs/kernfs/dir.c:1791

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #10 (&root->kernfs_supers_rwsem){++++}-{4:4}:
       down_read+0x4a/0x330 kernel/locking/rwsem.c:1574
       kernfs_remove_by_name_ns+0x3f/0x140 fs/kernfs/dir.c:1791
       kernfs_remove_by_name include/linux/kernfs.h:644 [inline]
       create_files fs/sysfs/group.c:66 [inline]
       internal_create_group+0x58e/0x1180 fs/sysfs/group.c:189
       internal_create_groups fs/sysfs/group.c:229 [inline]
       sysfs_update_groups+0x60/0x130 fs/sysfs/group.c:273
       pmu_dev_alloc+0x29b/0x300 kernel/events/core.c:12772
       perf_event_sysfs_init+0x76/0x100 kernel/events/core.c:15368
       do_one_initcall+0x250/0x870 init/main.c:1347
       do_initcall_level+0x10a/0x1a0 init/main.c:1409
       do_initcalls+0x59/0xa0 init/main.c:1425
       kernel_init_freeable+0x29d/0x3e0 init/main.c:1658
       kernel_init+0x1d/0x1d0 init/main.c:1548
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #9 (pmus_lock){+.+.}-{4:4}:
       __mutex_lock_common kernel/locking/mutex.c:646 [inline]
       __mutex_lock+0x19d/0x1550 kernel/locking/mutex.c:821
       perf_event_init_cpu+0x1d1/0x7a0 kernel/events/core.c:15270
       cpuhp_invoke_callback+0x434/0x810 kernel/cpu.c:194
       cpuhp_thread_fun+0x362/0x780 kernel/cpu.c:1109
       smpboot_thread_fn+0x57c/0xa80 kernel/smpboot.c:160
       kthread+0x388/0x470 kernel/kthread.c:436
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #8 (cpuhp_state-up){+.+.}-{0:0}:
       cpuhp_lock_acquire kernel/cpu.c:103 [inline]
       cpuhp_thread_fun+0x127/0x780 kernel/cpu.c:1086
       smpboot_thread_fn+0x57c/0xa80 kernel/smpboot.c:160
       kthread+0x388/0x470 kernel/kthread.c:436
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #7 (cpu_hotplug_lock){++++}-{0:0}:
       percpu_down_read_internal include/linux/percpu-rwsem.h:53 [inline]
       percpu_down_read include/linux/percpu-rwsem.h:77 [inline]
       cpus_read_lock+0x42/0x160 kernel/cpu.c:490
       static_key_slow_inc+0x12/0x30 kernel/jump_label.c:190
       nbd_reconnect_socket drivers/block/nbd.c:1379 [inline]
       nbd_genl_reconfigure+0x1301/0x1e80 drivers/block/nbd.c:2468
       genl_family_rcv_msg_doit+0x233/0x340 net/netlink/genetlink.c:1114
       genl_family_rcv_msg net/netlink/genetlink.c:1194 [inline]
       genl_rcv_msg+0x614/0x7a0 net/netlink/genetlink.c:1209
       netlink_rcv_skb+0x226/0x4a0 net/netlink/af_netlink.c:2556
       genl_rcv+0x28/0x40 net/netlink/genetlink.c:1218
       netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
       netlink_unicast+0x7bb/0x940 net/netlink/af_netlink.c:1345
       netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1900
       sock_sendmsg_nosec+0x13a/0x180 net/socket.c:775
       __sock_sendmsg net/socket.c:790 [inline]
       ____sys_sendmsg+0x54e/0x850 net/socket.c:2684
       ___sys_sendmsg+0x2a5/0x360 net/socket.c:2738
       __sys_sendmsg net/socket.c:2770 [inline]
       __do_sys_sendmsg net/socket.c:2775 [inline]
       __se_sys_sendmsg net/socket.c:2773 [inline]
       __x64_sys_sendmsg+0x1b1/0x290 net/socket.c:2773
       do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
       do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
       entry_SYSCALL_64_after_hwframe+0x77/0x7f

-> #6 (&nsock->tx_lock){+.+.}-{4:4}:
       __mutex_lock_common kernel/locking/mutex.c:646 [inline]
       __mutex_lock+0x19d/0x1550 kernel/locking/mutex.c:821
       nbd_handle_cmd drivers/block/nbd.c:1143 [inline]
       nbd_queue_rq+0x373/0x1150 drivers/block/nbd.c:1207
       blk_mq_dispatch_rq_list+0x499/0x1990 block/blk-mq.c:2117
       __blk_mq_do_dispatch_sched block/blk-mq-sched.c:168 [inline]
       blk_mq_do_dispatch_sched block/blk-mq-sched.c:182 [inline]
       __blk_mq_sched_dispatch_requests+0xd36/0x1580 block/blk-mq-sched.c:307
       blk_mq_sched_dispatch_requests+0xd7/0x190 block/blk-mq-sched.c:329
       blk_mq_run_work_fn+0x16c/0x300 block/blk-mq.c:2532
       process_one_work kernel/workqueue.c:3322 [inline]
       process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
       worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
       kthread+0x388/0x470 kernel/kthread.c:436
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #5 (&cmd->lock){+.+.}-{4:4}:
       __mutex_lock_common kernel/locking/mutex.c:646 [inline]
       __mutex_lock+0x19d/0x1550 kernel/locking/mutex.c:821
       nbd_queue_rq+0xc1/0x1150 drivers/block/nbd.c:1199
       blk_mq_dispatch_rq_list+0x499/0x1990 block/blk-mq.c:2117
       __blk_mq_do_dispatch_sched block/blk-mq-sched.c:168 [inline]
       blk_mq_do_dispatch_sched block/blk-mq-sched.c:182 [inline]
       __blk_mq_sched_dispatch_requests+0xd36/0x1580 block/blk-mq-sched.c:307
       blk_mq_sched_dispatch_requests+0xd7/0x190 block/blk-mq-sched.c:329
       blk_mq_run_work_fn+0x16c/0x300 block/blk-mq.c:2532
       process_one_work kernel/workqueue.c:3322 [inline]
       process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
       worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
       kthread+0x388/0x470 kernel/kthread.c:436
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #4 (set->srcu){.+.+}-{0:0}:
       srcu_lock_sync include/linux/srcu.h:199 [inline]
       __synchronize_srcu+0xc9/0x2f0 kernel/rcu/srcutree.c:1481
       elevator_switch+0x1e8/0x7b0 block/elevator.c:576
       elevator_change+0x2fa/0x480 block/elevator.c:681
       elevator_set_default+0x375/0x440 block/elevator.c:754
       blk_register_queue+0x3f3/0x4e0 block/blk-sysfs.c:992
       __add_disk+0x6cb/0xe30 block/genhd.c:528
       add_disk_fwnode+0xfb/0x4b0 block/genhd.c:597
       add_disk include/linux/blkdev.h:800 [inline]
       nbd_dev_add+0x733/0xb60 drivers/block/nbd.c:2021
       nbd_init+0x15f/0x1e0 drivers/block/nbd.c:2729
       do_one_initcall+0x250/0x870 init/main.c:1347
       do_initcall_level+0x10a/0x1a0 init/main.c:1409
       do_initcalls+0x59/0xa0 init/main.c:1425
       kernel_init_freeable+0x29d/0x3e0 init/main.c:1658
       kernel_init+0x1d/0x1d0 init/main.c:1548
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #3 (&q->elevator_lock){+.+.}-{4:4}:
       __mutex_lock_common kernel/locking/mutex.c:646 [inline]
       __mutex_lock+0x19d/0x1550 kernel/locking/mutex.c:821
       elevator_change+0x1af/0x480 block/elevator.c:679
       elevator_set_none+0xb5/0x140 block/elevator.c:769
       blk_mq_elv_switch_none block/blk-mq.c:5101 [inline]
       __blk_mq_update_nr_hw_queues block/blk-mq.c:5146 [inline]
       blk_mq_update_nr_hw_queues+0x5ef/0x19f0 block/blk-mq.c:5211
       nbd_start_device+0x189/0xb30 drivers/block/nbd.c:1526
       nbd_genl_connect+0x1597/0x1c10 drivers/block/nbd.c:2276
       genl_family_rcv_msg_doit+0x233/0x340 net/netlink/genetlink.c:1114
       genl_family_rcv_msg net/netlink/genetlink.c:1194 [inline]
       genl_rcv_msg+0x614/0x7a0 net/netlink/genetlink.c:1209
       netlink_rcv_skb+0x226/0x4a0 net/netlink/af_netlink.c:2556
       genl_rcv+0x28/0x40 net/netlink/genetlink.c:1218
       netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
       netlink_unicast+0x7bb/0x940 net/netlink/af_netlink.c:1345
       netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1900
       sock_sendmsg_nosec+0x13a/0x180 net/socket.c:775
       __sock_sendmsg net/socket.c:790 [inline]
       ____sys_sendmsg+0x54e/0x850 net/socket.c:2684
       ___sys_sendmsg+0x2a5/0x360 net/socket.c:2738
       __sys_sendmsg net/socket.c:2770 [inline]
       __do_sys_sendmsg net/socket.c:2775 [inline]
       __se_sys_sendmsg net/socket.c:2773 [inline]
       __x64_sys_sendmsg+0x1b1/0x290 net/socket.c:2773
       do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
       do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
       entry_SYSCALL_64_after_hwframe+0x77/0x7f

-> #2 (&q->q_usage_counter(io)#54){++++}-{0:0}:
       blk_alloc_queue+0x544/0x690 block/blk-core.c:504
       blk_mq_alloc_queue block/blk-mq.c:4420 [inline]
       __blk_mq_alloc_disk+0x194/0x390 block/blk-mq.c:4467
       nbd_dev_add+0x494/0xb60 drivers/block/nbd.c:1991
       nbd_init+0x15f/0x1e0 drivers/block/nbd.c:2729
       do_one_initcall+0x250/0x870 init/main.c:1347
       do_initcall_level+0x10a/0x1a0 init/main.c:1409
       do_initcalls+0x59/0xa0 init/main.c:1425
       kernel_init_freeable+0x29d/0x3e0 init/main.c:1658
       kernel_init+0x1d/0x1d0 init/main.c:1548
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #1 (fs_reclaim){+.+.}-{0:0}:
       __fs_reclaim_acquire mm/page_alloc.c:4329 [inline]
       fs_reclaim_acquire+0x71/0x100 mm/page_alloc.c:4343
       might_alloc include/linux/sched/mm.h:317 [inline]
       slab_pre_alloc_hook mm/slub.c:4565 [inline]
       slab_alloc_node mm/slub.c:4925 [inline]
       kmem_cache_alloc_lru_noprof+0x65/0x5f0 mm/slub.c:4978
       alloc_inode+0xb8/0x1b0 fs/inode.c:340
       iget_locked+0x131/0x6a0 fs/inode.c:1477
       kernfs_get_inode+0x4f/0x770 fs/kernfs/inode.c:252
       kernfs_fill_super fs/kernfs/mount.c:308 [inline]
       kernfs_get_tree+0x5cd/0x980 fs/kernfs/mount.c:392
       vfs_get_tree+0x92/0x2a0 fs/super.c:1694
       fc_mount fs/namespace.c:1198 [inline]
       do_new_mount_fc fs/namespace.c:3765 [inline]
       do_new_mount+0x319/0xdc0 fs/namespace.c:3841
       do_mount fs/namespace.c:4174 [inline]
       __do_sys_mount fs/namespace.c:4390 [inline]
       __se_sys_mount+0x31d/0x420 fs/namespace.c:4367
       do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
       do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
       entry_SYSCALL_64_after_hwframe+0x77/0x7f

-> #0 (&root->kernfs_rwsem){++++}-{4:4}:
       check_prev_add kernel/locking/lockdep.c:3165 [inline]
       check_prevs_add kernel/locking/lockdep.c:3284 [inline]
       validate_chain kernel/locking/lockdep.c:3908 [inline]
       __lock_acquire+0x1520/0x2cf0 kernel/locking/lockdep.c:5237
       lock_acquire+0x106/0x350 kernel/locking/lockdep.c:5868
       down_write+0x96/0x200 kernel/locking/rwsem.c:1631
       kernfs_remove_by_name_ns+0x4e/0x140 fs/kernfs/dir.c:1792
       _cfg80211_unregister_wdev+0x133/0x5a0 net/wireless/core.c:1420
       ieee80211_if_remove+0x289/0x340 net/mac80211/iface.c:2432
       ieee80211_del_iface+0x19/0x30 net/mac80211/cfg.c:254
       rdev_del_virtual_intf net/wireless/rdev-ops.h:62 [inline]
       cfg80211_remove_virtual_intf+0x221/0x3f0 net/wireless/util.c:3006
       cfg80211_destroy_ifaces+0x23f/0x300 net/wireless/core.c:436
       cfg80211_destroy_iface_wk+0x21/0x30 net/wireless/core.c:464
       process_one_work kernel/workqueue.c:3322 [inline]
       process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
       worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
       kthread+0x388/0x470 kernel/kthread.c:436
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

other info that might help us debug this:

Chain exists of:
  &root->kernfs_rwsem --> pmus_lock --> &root->kernfs_supers_rwsem

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  rlock(&root->kernfs_supers_rwsem);
                               lock(pmus_lock);
                               lock(&root->kernfs_supers_rwsem);
  lock(&root->kernfs_rwsem);

 *** DEADLOCK ***

5 locks held by kworker/0:1/21181:
 #0: ffff88801b02b140 ((wq_completion)events){+.+.}-{0:0}, at: process_one_work kernel/workqueue.c:3297 [inline]
 #0: ffff88801b02b140 ((wq_completion)events){+.+.}-{0:0}, at: process_scheduled_works+0xa20/0x14e0 kernel/workqueue.c:3405
 #1: ffffc900041dfc40 ((work_completion)(&rdev->destroy_work)){+.+.}-{0:0}, at: process_one_work kernel/workqueue.c:3297 [inline]
 #1: ffffc900041dfc40 ((work_completion)(&rdev->destroy_work)){+.+.}-{0:0}, at: process_scheduled_works+0xa20/0x14e0 kernel/workqueue.c:3405
 #2: ffffffff9002c040 (rtnl_mutex){+.+.}-{4:4}, at: cfg80211_destroy_iface_wk+0x19/0x30 net/wireless/core.c:463
 #3: ffff888088e907a0 (&rdev->wiphy.mtx){+.+.}-{4:4}, at: class_wiphy_constructor include/net/cfg80211.h:6884 [inline]
 #3: ffff888088e907a0 (&rdev->wiphy.mtx){+.+.}-{4:4}, at: cfg80211_destroy_ifaces+0x233/0x300 net/wireless/core.c:434
 #4: ffff88801c2952a0 (&root->kernfs_supers_rwsem){++++}-{4:4}, at: kernfs_remove_by_name_ns+0x3f/0x140 fs/kernfs/dir.c:1791

stack backtrace:
CPU: 0 UID: 0 PID: 21181 Comm: kworker/0:1 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/09/2026
Workqueue: events cfg80211_destroy_iface_wk
Call Trace:
 <TASK>
 dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
 print_circular_bug+0x2e1/0x300 kernel/locking/lockdep.c:2043
 check_noncircular+0x12e/0x150 kernel/locking/lockdep.c:2175
 check_prev_add kernel/locking/lockdep.c:3165 [inline]
 check_prevs_add kernel/locking/lockdep.c:3284 [inline]
 validate_chain kernel/locking/lockdep.c:3908 [inline]
 __lock_acquire+0x1520/0x2cf0 kernel/locking/lockdep.c:5237
 lock_acquire+0x106/0x350 kernel/locking/lockdep.c:5868
 down_write+0x96/0x200 kernel/locking/rwsem.c:1631
 kernfs_remove_by_name_ns+0x4e/0x140 fs/kernfs/dir.c:1792
 _cfg80211_unregister_wdev+0x133/0x5a0 net/wireless/core.c:1420
 ieee80211_if_remove+0x289/0x340 net/mac80211/iface.c:2432
 ieee80211_del_iface+0x19/0x30 net/mac80211/cfg.c:254
 rdev_del_virtual_intf net/wireless/rdev-ops.h:62 [inline]
 cfg80211_remove_virtual_intf+0x221/0x3f0 net/wireless/util.c:3006
 cfg80211_destroy_ifaces+0x23f/0x300 net/wireless/core.c:436
 cfg80211_destroy_iface_wk+0x21/0x30 net/wireless/core.c:464
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </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.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

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


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