Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] net: bridge: replace simple_strtoul with kstrtoul
From: Nikolay Aleksandrov @ 2026-05-05  6:22 UTC (permalink / raw)
  To: Aadarsh Chandra, idosch; +Cc: davem, kuba, netdev, bridge, linux-kernel
In-Reply-To: <20260504150146.457562-1-aadarsh.official.xz@gmail.com>

On 04/05/2026 18:01, Aadarsh Chandra wrote:
> The simple_strtoul() function is deprecated. It does not handle
> errors or overflows correctly. Replace it with kstrtoul() in
> brport_store() to ensure that invalid user input is caught and
> returned as an error.
> 
> Signed-off-by: Aadarsh Chandra <aadarsh.official.xz@gmail.com>
> ---
>   net/bridge/br_sysfs_if.c | 8 +++++---
>   1 file changed, 5 insertions(+), 3 deletions(-)
> 

This patch should be targeted at net-next (PATCH net-next in subject).

> diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
> index 1f57c36a7fc0..3e948d781970 100644
> --- a/net/bridge/br_sysfs_if.c
> +++ b/net/bridge/br_sysfs_if.c
> @@ -318,7 +318,7 @@ static ssize_t brport_store(struct kobject *kobj,
>   	struct net_bridge_port *p = kobj_to_brport(kobj);
>   	ssize_t ret = -EINVAL;
>   	unsigned long val;
> -	char *endp;
> +	int err;
>   
>   	if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN))
>   		return -EPERM;
> @@ -339,9 +339,11 @@ static ssize_t brport_store(struct kobject *kobj,
>   		spin_unlock_bh(&p->br->lock);
>   		kfree(buf_copy);
>   	} else if (brport_attr->store) {
> -		val = simple_strtoul(buf, &endp, 0);
> -		if (endp == buf)
> +		err = kstrtoul(buf, 0, &val);

You can just use ret = kstrtoul() here and make this simpler, ssize_t is an
int on 32 bit archs and a long on 64 bit ones, so it can hold the return val.

> +		if (err) {
> +			ret = err;
>   			goto out_unlock;
> +		}
>   		spin_lock_bh(&p->br->lock);
>   		ret = brport_attr->store(p, val);
>   		spin_unlock_bh(&p->br->lock);

Cheers,
  Nik


^ permalink raw reply

* [PATCH net-next v2] rtase: Fix flow control configuration
From: Justin Lai @ 2026-05-05  6:41 UTC (permalink / raw)
  To: kuba
  Cc: davem, edumazet, pabeni, andrew+netdev, linux-kernel, netdev,
	horms, pkshih, larry.chiu, Justin Lai

The hardware has two sets of registers controlling TX/RX flow control.
The effective flow control state is determined by the logical OR of
these two sets of bits.

RTASE_FORCE_TXFLOW_EN and RTASE_FORCE_RXFLOW_EN in RTASE_CPLUS_CMD are
the bits used by the driver to control TX/RX flow control according to
the ethtool pause configuration.

RTASE_TXFLOW_EN and RTASE_RXFLOW_EN in RTASE_GPHY_STD_00 are another
set of TX/RX flow control enable bits. Clear them by default so they do
not keep flow control enabled independently of the driver setting.

With the RTASE_GPHY_STD_00 bits cleared, the effective flow control
state is controlled through RTASE_CPLUS_CMD, so the ethtool setting can
take effect correctly.

Signed-off-by: Justin Lai <justinlai0215@realtek.com>
---
v1 -> v2:
- Rebase onto net-next.
- Expand commit message.
---
 drivers/net/ethernet/realtek/rtase/rtase.h      | 4 ++++
 drivers/net/ethernet/realtek/rtase/rtase_main.c | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/drivers/net/ethernet/realtek/rtase/rtase.h b/drivers/net/ethernet/realtek/rtase/rtase.h
index b9209eb6ea73..9bd6872474c1 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase.h
+++ b/drivers/net/ethernet/realtek/rtase/rtase.h
@@ -153,6 +153,10 @@ enum rtase_registers {
 #define RTASE_FORCE_TXFLOW_EN BIT(10)
 #define RTASE_RX_CHKSUM       BIT(5)
 
+	RTASE_GPHY_STD_00 = 0x6024,
+#define RTASE_RXFLOW_EN BIT(7)
+#define RTASE_TXFLOW_EN BIT(6)
+
 	RTASE_Q0_RX_DESC_ADDR0 = 0x00E4,
 	RTASE_Q0_RX_DESC_ADDR4 = 0x00E8,
 	RTASE_Q1_RX_DESC_ADDR0 = 0x4000,
diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c
index ef13109c49cf..bde9bccfb5a9 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
+++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
@@ -974,6 +974,9 @@ static void rtase_hw_config(struct net_device *dev)
 	rtase_hw_set_features(dev, dev->features);
 
 	/* enable flow control */
+	reg_data16 = rtase_r16(tp, RTASE_GPHY_STD_00);
+	reg_data16 &= ~(RTASE_TXFLOW_EN | RTASE_RXFLOW_EN);
+	rtase_w16(tp, RTASE_GPHY_STD_00, reg_data16);
 	reg_data16 = rtase_r16(tp, RTASE_CPLUS_CMD);
 	reg_data16 |= (RTASE_FORCE_TXFLOW_EN | RTASE_FORCE_RXFLOW_EN);
 	rtase_w16(tp, RTASE_CPLUS_CMD, reg_data16);
-- 
2.40.1


^ permalink raw reply related

* Re: [PATCH net-next] net: usb: mcs7830: fix typo in module description and clarify it
From: Andy Shevchenko @ 2026-05-05  6:43 UTC (permalink / raw)
  To: Ethan Nelson-Moore
  Cc: linux-usb, netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Vadim Fedorenko
In-Reply-To: <20260505013504.45975-1-enelsonmoore@gmail.com>

On Mon, May 04, 2026 at 06:34:59PM -0700, Ethan Nelson-Moore wrote:
> The mcs7830 driver's MODULE_DESCRIPTION has an errant parenthesis

MODULE_DESCRIPTION()

> and does not indicate that the device is an Ethernet adapter. Remove
> the parenthesis and improve the description.

...

> -MODULE_DESCRIPTION("USB to network adapter MCS7830)");
> +MODULE_DESCRIPTION("MCS7830 USB to Ethernet adapter driver");

It's better to align this with the top comment

 * MOSCHIP MCS7830 based (7730/7830/7832) USB 2.0 Ethernet Devices

Another option is to align to Kconfig help

	tristate "MosChip MCS7830 based Ethernet adapters"

(ideally all three should be the same).

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH net-next] net: usb: mcs7830: adjust incorrect comment implying a vulnerability
From: Andy Shevchenko @ 2026-05-05  6:46 UTC (permalink / raw)
  To: Ethan Nelson-Moore
  Cc: linux-usb, netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Peter Korsgaard
In-Reply-To: <20260505014634.49100-1-enelsonmoore@gmail.com>

On Mon, May 04, 2026 at 06:46:30PM -0700, Ethan Nelson-Moore wrote:
> The mcs7830 driver contains a comment indicating that mcs7830_get_regs

See, even in the comment the function is referred as func(). Please,
follow this convention everywhere (comments, commit messages, documentation
where it's appropriate).

> leaks uninitialized memory to user space on some devices. If true, this
> would indicate a security vulnerability. However, I investigated the
> issue and found that it is not true because ethtool_get_regs (in

ethtool_get_regs()


> net/ethtool/ioctl.c) uses vzalloc to allocate its buffer, which zeroes

vzalloc()

> the memory. Update the comment to explain this behavior.

...

>   * - implement get_eeprom/[set_eeprom]
>   * - switch PHY on/off on ifup/ifdown (perhaps in usbnet.c, via MII)
>   * - mcs7830_get_regs() handling is weird: for rev 2 we return 32 regs,
> - *   can access only ~ 24, remaining user buffer is uninitialized garbage
> + *   can access only ~ 24; this is not a security vulnerability because
> + *   ethtool_get_regs allocates a zeroed buffer

Same as above.

>   * - anything else?

...

Also, while the patches are not conflicting with or dependent on each other,
they are against the same driver, hence the series is preferable over
individual patches.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH v2 1/2] vfio: add dma-buf get_tph callback and DMA_BUF_TPH feature
From: Zhiping Zhang @ 2026-05-05  6:54 UTC (permalink / raw)
  To: Alex Williamson
  Cc: Jason Gunthorpe, Leon Romanovsky, Bjorn Helgaas, linux-rdma,
	linux-pci, netdev, dri-devel, Keith Busch, Yochai Cohen,
	Yishai Hadas, kvm
In-Reply-To: <20260504154459.77b8153d@shazbot.org>

On Mon, May 4, 2026 at 2:45 PM Alex Williamson <alex@shazbot.org> wrote:
>
> >
> On Thu, 30 Apr 2026 13:06:56 -0700
> Zhiping Zhang <zhipingz@meta.com> wrote:
>
> > Add a dma-buf callback that returns raw TPH metadata from the exporter
> > so peer devices can reuse the steering tag and processing hint
> > associated with a VFIO-exported buffer.
> >
> > Add a new VFIO_DEVICE_FEATURE_DMA_BUF_TPH ioctl that takes the fd from
> > VFIO_DEVICE_FEATURE_DMA_BUF along with a steering tag and processing
> > hint, validates the fd is a vfio-exported dma-buf belonging to this
> > device, and stores the TPH values under memory_lock. This keeps the
> > existing VFIO_DEVICE_FEATURE_DMA_BUF uAPI completely unchanged.
> >
> > The user sequences setting TPH on the dma-buf before the importer
> > consumes it.
> >
> > Add an st_width parameter to get_tph() so the exporter can reject
> > steering tags that exceed the consumer's supported width (8 vs 16 bit).
> > When no TPH metadata was supplied, get_tph() returns -EOPNOTSUPP.
> >
> > Signed-off-by: Zhiping Zhang <zhipingz@meta.com>
>
> The uAPI is better, but sashiko has some review comments[1] for you.
>
> Please also copy the kvm list for vfio related development.  Thanks,
>
> Alex

Got it, thanks Alex. let me check sashiko's comments and post a new
revision. i also copied kvm@vger.kernel.org and will include in future
revisions.

Zhiping

>
> [1]https://urldefense.com/v3/__https://sashiko.dev/*/patchset/20260430200704.352228-1-zhipingz@meta.com__;Iw!!Bt8RZUm9aw!7glmqoMRhcdDwOgCAQuuEVqlhFJrh9bAYHXvicXPAO2M-k-NPwE_wFeUjVhe7EXbkXMd6g7eOe13$
>
> > diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
> > --- a/drivers/vfio/pci/vfio_pci_core.c
> > +++ b/drivers/vfio/pci/vfio_pci_core.c
> > @@ -1534,6 +1534,9 @@ int vfio_pci_core_ioctl_feature(struct vfio_device *device, u32 flags,
> >               return vfio_pci_core_feature_token(vdev, flags, arg, argsz);
> >       case VFIO_DEVICE_FEATURE_DMA_BUF:
> >               return vfio_pci_core_feature_dma_buf(vdev, flags, arg, argsz);
> > +     case VFIO_DEVICE_FEATURE_DMA_BUF_TPH:
> > +             return vfio_pci_core_feature_dma_buf_tph(vdev, flags, arg,
> > +                                                      argsz);
> >       default:
> >               return -ENOTTY;
> >       }
> > diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
> > --- a/drivers/vfio/pci/vfio_pci_dmabuf.c
> > +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
> > @@ -19,6 +19,9 @@ struct vfio_pci_dma_buf {
> >       u32 nr_ranges;
> >       struct kref kref;
> >       struct completion comp;
> > +     u16 steering_tag;
> > +     u8 ph;
> > +     u8 tph_present : 1;
> >       u8 revoked : 1;
> >  };
> >
> > @@ -69,6 +72,22 @@ vfio_pci_dma_buf_map(struct dma_buf_attachment *attachment,
> >       return ret;
> >  }
> >
> > +static int vfio_pci_dma_buf_get_tph(struct dma_buf *dmabuf, u16 *steering_tag,
> > +                                 u8 *ph, u8 st_width)
> > +{
> > +     struct vfio_pci_dma_buf *priv = dmabuf->priv;
> > +
> > +     if (!priv->tph_present)
> > +             return -EOPNOTSUPP;
> > +
> > +     if (st_width < 16 && priv->steering_tag > ((1U << st_width) - 1))
> > +             return -EINVAL;
> > +
> > +     *steering_tag = priv->steering_tag;
> > +     *ph = priv->ph;
> > +     return 0;
> > +}
> > +
> >  static void vfio_pci_dma_buf_unmap(struct dma_buf_attachment *attachment,
> >                                  struct sg_table *sgt,
> >                                  enum dma_data_direction dir)
> > @@ -101,6 +120,7 @@ static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf)
> >
> >  static const struct dma_buf_ops vfio_pci_dmabuf_ops = {
> >       .attach = vfio_pci_dma_buf_attach,
> > +     .get_tph = vfio_pci_dma_buf_get_tph,
> >       .map_dma_buf = vfio_pci_dma_buf_map,
> >       .unmap_dma_buf = vfio_pci_dma_buf_unmap,
> >       .release = vfio_pci_dma_buf_release,
> > @@ -331,6 +351,55 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
> >       return ret;
> >  }
> >
> > +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev,
> > +                                   u32 flags,
> > +                                   struct vfio_device_feature_dma_buf_tph __user *arg,
> > +                                   size_t argsz)
> > +{
> > +     struct vfio_device_feature_dma_buf_tph set_tph;
> > +     struct vfio_pci_dma_buf *priv;
> > +     struct dma_buf *dmabuf;
> > +     int ret;
> > +
> > +     ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET,
> > +                              sizeof(set_tph));
> > +     if (ret != 1)
> > +             return ret;
> > +
> > +     if (copy_from_user(&set_tph, arg, sizeof(set_tph)))
> > +             return -EFAULT;
> > +
> > +     if (set_tph.reserved)
> > +             return -EINVAL;
> > +
> > +     dmabuf = dma_buf_get(set_tph.dmabuf_fd);
> > +     if (IS_ERR(dmabuf))
> > +             return PTR_ERR(dmabuf);
> > +
> > +     if (dmabuf->ops != &vfio_pci_dmabuf_ops) {
> > +             ret = -EINVAL;
> > +             goto out_put;
> > +     }
> > +
> > +     priv = dmabuf->priv;
> > +     down_write(&vdev->memory_lock);
> > +     if (priv->vdev != vdev) {
> > +             ret = -EINVAL;
> > +             goto out_unlock;
> > +     }
> > +
> > +     priv->steering_tag = set_tph.steering_tag;
> > +     priv->ph = set_tph.ph;
> > +     priv->tph_present = 1;
> > +     ret = 0;
> > +
> > +out_unlock:
> > +     up_write(&vdev->memory_lock);
> > +out_put:
> > +     dma_buf_put(dmabuf);
> > +     return ret;
> > +}
> > +
> >  void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked)
> >  {
> >       struct vfio_pci_dma_buf *priv;
> > diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h
> > --- a/drivers/vfio/pci/vfio_pci_priv.h
> > +++ b/drivers/vfio/pci/vfio_pci_priv.h
> > @@ -118,6 +118,10 @@ static inline bool vfio_pci_is_vga(struct pci_dev *pdev)
> >  int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
> >                                 struct vfio_device_feature_dma_buf __user *arg,
> >                                 size_t argsz);
> > +int vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev,
> > +                                   u32 flags,
> > +                                   struct vfio_device_feature_dma_buf_tph __user *arg,
> > +                                   size_t argsz);
> >  void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev);
> >  void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked);
> >  #else
> > @@ -128,6 +132,13 @@ vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
> >  {
> >       return -ENOTTY;
> >  }
> > +static inline int
> > +vfio_pci_core_feature_dma_buf_tph(struct vfio_pci_core_device *vdev, u32 flags,
> > +                               struct vfio_device_feature_dma_buf_tph __user *arg,
> > +                               size_t argsz)
> > +{
> > +     return -ENOTTY;
> > +}
> >  static inline void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev)
> >  {
> >  }
> > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> > --- a/include/linux/dma-buf.h
> > +++ b/include/linux/dma-buf.h
> > @@ -113,6 +113,23 @@ struct dma_buf_ops {
> >        */
> >       void (*unpin)(struct dma_buf_attachment *attach);
> >
> > +     /**
> > +      * @get_tph:
> > +      * @dmabuf: DMA buffer for which to retrieve TPH metadata
> > +      * @steering_tag: Returns the raw TPH steering tag
> > +      * @ph: Returns the TPH processing hint
> > +      * @st_width: Consumer's supported steering tag width in bits (8 or 16)
> > +      *
> > +      * Return the TPH (TLP Processing Hints) metadata associated with this
> > +      * DMA buffer. Exporters that do not provide TPH metadata should return
> > +      * -EOPNOTSUPP. If the steering tag exceeds @st_width bits, return
> > +      * -EINVAL.
> > +      *
> > +      * This callback is optional.
> > +      */
> > +     int (*get_tph)(struct dma_buf *dmabuf, u16 *steering_tag, u8 *ph,
> > +                    u8 st_width);
> > +
> >       /**
> >        * @map_dma_buf:
> >        *
> > diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
> > --- a/include/uapi/linux/vfio.h
> > +++ b/include/uapi/linux/vfio.h
> > @@ -1534,6 +1534,28 @@ struct vfio_device_feature_dma_buf {
> >   */
> >  #define VFIO_DEVICE_FEATURE_MIG_PRECOPY_INFOv2  12
> >
> > +/**
> > + * Upon VFIO_DEVICE_FEATURE_SET associate TPH (TLP Processing Hints) metadata
> > + * with a vfio-exported dma-buf. The dma-buf must have been created by
> > + * VFIO_DEVICE_FEATURE_DMA_BUF on this device.
> > + *
> > + * dmabuf_fd is the file descriptor returned by VFIO_DEVICE_FEATURE_DMA_BUF.
> > + * steering_tag and ph are the raw TPH values that importing drivers should use
> > + * when accessing the buffer.
> > + *
> > + * The user must set TPH on the dma-buf before the importer consumes it.
> > + *
> > + * Return: 0 on success, -errno on failure.
> > + */
> > +#define VFIO_DEVICE_FEATURE_DMA_BUF_TPH 13
> > +
> > +struct vfio_device_feature_dma_buf_tph {
> > +     __s32   dmabuf_fd;
> > +     __u16   steering_tag;
> > +     __u8    ph;
> > +     __u8    reserved;
> > +};
> > +
> >  /* -------- API for Type1 VFIO IOMMU -------- */
> >
> >  /**
>

^ permalink raw reply

* Re: [PATCH batadv 0/8] batman-adv: follow up fixes
From: Sven Eckelmann @ 2026-05-05  7:20 UTC (permalink / raw)
  Cc: Jakub Kicinski, Konstantin Ryabitsev, Paolo Abeni, netdev,
	linux-kernel, Ao Zhou, Haoze Xie, Jiexun Wang, Juefei Pu,
	Luxing Yin, Ruide Cao, Xin Liu, Yifan Wu, Yuan Tan, Joe Perches
In-Reply-To: <c75c7d50-36b2-4397-8355-891c83d663c9@kernel.org>

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

On Tuesday, 5 May 2026 07:21:13 CEST Matthieu Baerts wrote:
[...]
> >>> Are you CCing netdev to get this reviewed by Sashiko?
> >>> Please don't..
> >>> We delegate code to sub-sub-systems to lower the patch volume :(
> >>>
> >>
> >> Because of `b4 prep --auto-to-cc`. Will now manually remove you.
> >
> > To speed up the discussion: @Konstantin, is there a way in b4 to say "stop at
> > the sub-sub-systems" when doing `b4 prep --auto-to-cc`? I am just trying to get the
> > `b4` workflow somehow working with the netdev requirements.
> 
> Maybe a new option could be added, but that seems difficult to guess
> where to stop, and to which subsystems to apply this.
> 
> Can you not simply omit using `b4 prep --auto-to-cc` when working
> with "internal" patches?

Yes, no, maybe :)
I will for the moment ignore the .b4-config part and talk about it at the end 
of the mail.

b4 is trying to (afaik) to have a good common work flow for kernel related 
projects (and more). Independent of my role (if I am the maintainer or just 
another contributor), it will nag before a send: "Hey, please run 
--auto-to-cc, --check, --check-deps before you submit this patch(set) - you 
know how embarrassing it is when you notice some obvious problem 2 seconds 
after the SMTP server accepted your mail."

And I agree with this and also try to convince people to try b4 because I 
think it is really helpful. Or at least ask them to use
`./scripts/get_maintainer.pl` and NOT send patches with the prefix "net" or 
"net-next" when it actually targets our tree. But as it turns out, these 
recommendation seem to have been wrong and I am sorry about this.

And I know, b4 is a good tool but adding a bazillion options just for every 
special case doesn't make a lot of sense and might make it a worse tool. I was 
therefore more thinking about `scripts/get_maintainer.pl`  (see `b4.send-auto-
cc-cmd`) which also called by b4 with various options to avoid adding too many 
people.

I don't say that any of these tools need to change. I am guessing more that I 
have to adjust something (MAINTAINERS, ...) to avoid that people are sending 
batman-adv sub-sub-system patches directly to netdev. I am just not aware of 
what this should be. But it sounds to me like there is at least a need for it 
(from the netdev maintainers perspective).

> On my side, that's what I'm doing. I added a .b4-config file with this
> content, not to have to specify --set-prefix nor --to:

Regarding the .b4-config - yes, this is helpful and I should add it to 
batctl.git. I was more thinking about the normal contributor to 
net/batman-adv/. Regardless of this person taking as base net/net-next.git or 
our repo.

The fixes from Ren Wei (and associates) and some other people were sent with 
"net" in the prefix, were Cc'ing netdev and didn't seem to use our tree as 
base. This is of course not correct and they should have targeted our tree 
instead. I didn't complain because the fix was otherwise extremely helpful and 
I though that there was no harm done. As it looks now, I should have and I am 
sorry for not communicating this.

And I am at the moment not sure how to fix this without overloading 
contributers with "when you are contributing to some sub-subsystem of netdev 
..., but when you are contributing to ext4, other rules apply .... don't 
forget about i2c rules for patch submission, ...".

But maybe I am just ignorant and this is already quite simple (and there are 
no special "netdev" rules) - I am just not aware of it. In this case, please 
point me in the right direction, just to avoid reproducing wrong 
recommendations to other people.

Regards,
	Sven

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* [PATCH net v7 0/2] ipv6: flowlabel: per-netns budget for unprivileged callers
From: Maoyi Xie @ 2026-05-05  7:20 UTC (permalink / raw)
  To: David S . Miller
  Cc: Jakub Kicinski, Paolo Abeni, Eric Dumazet, David Ahern,
	Alexey Kuznetsov, Willem de Bruijn, Willem de Bruijn, netdev,
	linux-kernel, stable

This series fixes the cross-tenant DoS in net/ipv6/ip6_flowlabel.c.
v1 through v6 were single-patch postings, each in its own thread.
v6 review pointed out that the existing fl_size read in
mem_check() and the corresponding write in fl_intern() are not in
the same critical section. v7 splits the work into 2 patches.

Patch 1/2 is a prerequisite. It moves spin_lock_bh(&ip6_fl_lock)
and the matching unlock from fl_intern() into its only caller
ipv6_flowlabel_get(), so the mem_check() call runs under the same
critical section as the fl_intern() insert. With all writers and
the read of fl_size under the lock, fl_size is converted from
atomic_t to plain int. This is independent of the per-netns
budget. It also makes 2/2 backportable without conflicts.

Patch 2/2 is the v6 patch, rebased on 1/2.

  - flowlabel_count is plain int rather than atomic_t, since the
    previous patch put all writers and readers under ip6_fl_lock.
  - In ip6_fl_gc(), fl_free() is now placed below the fl_size
    and flowlabel_count decrements, removing the v6 cache of
    fl->fl_net.
  - In ip6_fl_purge(), fl_free() stays in its original position.
    The function argument net is used for flowlabel_count.
  - mem_check() uses spaces around the / operator on all four
    expressions, addressing the checkpatch note in v6 review.

Numeric budget (preserved from v6):

  pre-patch:
    global non-CAP_NET_ADMIN budget = FL_MAX_SIZE - FL_MAX_SIZE/4
                                    = 4096 - 1024 = 3072
    per-actor reach                 = 3072

  post-patch:
    FL_MAX_SIZE doubled to 8192
    global non-CAP_NET_ADMIN budget = 8192 - 2048 = 6144
    per-netns ceiling               = 6144 / 2 = 3072
    per-actor reach                 = 3072 (preserved)

CAP_NET_ADMIN against init_user_ns still bypasses both caps.

Reproducer (KASAN VM, 4 cores, qemu): unprivileged netns A holds
3072 flowlabels via 100 procs. Fresh unprivileged netns B then
allocates 32 flowlabels (the FL_MAX_PER_SOCK ceiling for one
socket), the same as a clean baseline. Without the per-netns
ceiling, netns A could push fl_size past FL_MAX_SIZE - FL_MAX_SIZE
/ 4 and netns B would see allocations denied.

v7:
  - 2-patch series: 1/2 (lock prep) and 2/2 (v6 rebased on 1/2).
  - 2/2: flowlabel_count int, fl_free() reorder removed in
    ip6_fl_purge(), checkpatch / spacing in mem_check() fixed.
v6: rebased onto current net (resolves the conflict on
    include/net/netns/ipv6.h that v5 hit). fl_free() restored
    to its pre-series position, with fl->fl_net cached locally
    in ip6_fl_gc().
v5: replaced the per-netns ceiling FL_MAX_SIZE/8 with the
    computed unpriv_user_limit = (FL_MAX_SIZE - FL_MAX_SIZE/4)/2,
    which evaluates to 3072.
v4: addressed Willem's v3 review on netdev. Dropped the
    flowlabel_has_excl cacheline argument in favour of "fills
    the existing 4-byte hole after ipmr_seq".
v3: addressed Willem's review on the private security@ thread.
    Merged FL_MAX_SIZE doubling, dropped test data, moved
    flowlabel_count near ipmr_seq, inlined fl->fl_net in
    ip6_fl_gc().
v2: per-netns counter + cap, sent to security@ as a 2-patch
    series.
v1: fix-shape sketch in original disclosure.

Maoyi Xie (2):
  ipv6: flowlabel: take ip6_fl_lock across mem_check and fl_intern
  ipv6: flowlabel: enforce per-netns limit for unprivileged callers

 include/net/netns/ipv6.h |  1 +
 net/ipv6/ip6_flowlabel.c | 45 ++++++++++++++++++++++++++++++---------------
 2 files changed, 31 insertions(+), 15 deletions(-)


base-commit: ebb639024ebd47a13a511cce6ae630c15e4b3126
-- 
2.34.1


^ permalink raw reply

* [PATCH net v7 1/2] ipv6: flowlabel: take ip6_fl_lock across mem_check and fl_intern
From: Maoyi Xie @ 2026-05-05  7:20 UTC (permalink / raw)
  To: David S . Miller
  Cc: Jakub Kicinski, Paolo Abeni, Eric Dumazet, David Ahern,
	Alexey Kuznetsov, Willem de Bruijn, Willem de Bruijn, netdev,
	linux-kernel, stable
In-Reply-To: <20260505072015.1672730-1-maoyi.xie@ntu.edu.sg>

mem_check() in net/ipv6/ip6_flowlabel.c reads fl_size without
holding ip6_fl_lock. fl_intern() takes the lock immediately
afterwards. The two checks therefore race against concurrent
fl_intern, ip6_fl_gc and ip6_fl_purge writers, which makes the
mem_check budget check approximate.

Move spin_lock_bh(&ip6_fl_lock) and the matching unlock from
fl_intern() into its only caller ipv6_flowlabel_get(). The
mem_check() call now runs under the same critical section as the
fl_intern() insert, so the budget check is exact.

With all writers and the read of fl_size under ip6_fl_lock,
convert fl_size from atomic_t to plain int. The four sites that
update or read fl_size are fl_intern (insert path), ip6_fl_gc
(garbage collector, the !sched check and the per-entry decrement),
ip6_fl_purge (per-netns purge), and mem_check (budget check), and
all four now run under ip6_fl_lock.

This is a prerequisite for adding a per-netns budget alongside
fl_size. The follow-up patch adds netns_ipv6::flowlabel_count and
folds it into mem_check().

Suggested-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Maoyi Xie <maoyi.xie@ntu.edu.sg>
---
 net/ipv6/ip6_flowlabel.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index c92f98c6f..43b5e9ce9 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -40,7 +40,7 @@
 #define FL_HASH_MASK	255
 #define FL_HASH(l)	(ntohl(l)&FL_HASH_MASK)
 
-static atomic_t fl_size = ATOMIC_INIT(0);
+static int fl_size;
 static struct ip6_flowlabel __rcu *fl_ht[FL_HASH_MASK+1];
 
 static void ip6_fl_gc(struct timer_list *unused);
@@ -163,7 +163,7 @@ static void ip6_fl_gc(struct timer_list *unused)
 				if (time_after_eq(now, ttd)) {
 					*flp = fl->next;
 					fl_free(fl);
-					atomic_dec(&fl_size);
+					fl_size--;
 					continue;
 				}
 				if (!sched || time_before(ttd, sched))
@@ -172,7 +172,7 @@ static void ip6_fl_gc(struct timer_list *unused)
 			flp = &fl->next;
 		}
 	}
-	if (!sched && atomic_read(&fl_size))
+	if (!sched && fl_size)
 		sched = now + FL_MAX_LINGER;
 	if (sched) {
 		mod_timer(&ip6_fl_gc_timer, sched);
@@ -196,7 +196,7 @@ static void __net_exit ip6_fl_purge(struct net *net)
 			    atomic_read(&fl->users) == 0) {
 				*flp = fl->next;
 				fl_free(fl);
-				atomic_dec(&fl_size);
+				fl_size--;
 				continue;
 			}
 			flp = &fl->next;
@@ -205,6 +205,7 @@ static void __net_exit ip6_fl_purge(struct net *net)
 	spin_unlock_bh(&ip6_fl_lock);
 }
 
+/* Caller must hold ip6_fl_lock. */
 static struct ip6_flowlabel *fl_intern(struct net *net,
 				       struct ip6_flowlabel *fl, __be32 label)
 {
@@ -212,8 +213,6 @@ static struct ip6_flowlabel *fl_intern(struct net *net,
 
 	fl->label = label & IPV6_FLOWLABEL_MASK;
 
-	rcu_read_lock();
-	spin_lock_bh(&ip6_fl_lock);
 	if (label == 0) {
 		for (;;) {
 			fl->label = htonl(get_random_u32())&IPV6_FLOWLABEL_MASK;
@@ -235,8 +234,6 @@ static struct ip6_flowlabel *fl_intern(struct net *net,
 		lfl = __fl_lookup(net, fl->label);
 		if (lfl) {
 			atomic_inc(&lfl->users);
-			spin_unlock_bh(&ip6_fl_lock);
-			rcu_read_unlock();
 			return lfl;
 		}
 	}
@@ -244,9 +241,7 @@ static struct ip6_flowlabel *fl_intern(struct net *net,
 	fl->lastuse = jiffies;
 	fl->next = fl_ht[FL_HASH(fl->label)];
 	rcu_assign_pointer(fl_ht[FL_HASH(fl->label)], fl);
-	atomic_inc(&fl_size);
-	spin_unlock_bh(&ip6_fl_lock);
-	rcu_read_unlock();
+	fl_size++;
 	return NULL;
 }
 
@@ -464,10 +459,14 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
 
 static int mem_check(struct sock *sk)
 {
-	int room = FL_MAX_SIZE - atomic_read(&fl_size);
+	int room;
 	struct ipv6_fl_socklist *sfl;
 	int count = 0;
 
+	lockdep_assert_held(&ip6_fl_lock);
+
+	room = FL_MAX_SIZE - fl_size;
+
 	if (room > FL_MAX_SIZE - FL_MAX_PER_SOCK)
 		return 0;
 
@@ -692,11 +691,19 @@ static int ipv6_flowlabel_get(struct sock *sk, struct in6_flowlabel_req *freq,
 	if (!sfl1)
 		goto done;
 
+	rcu_read_lock();
+	spin_lock_bh(&ip6_fl_lock);
 	err = mem_check(sk);
+	if (err == 0)
+		fl1 = fl_intern(net, fl, freq->flr_label);
+	else
+		fl1 = NULL;
+	spin_unlock_bh(&ip6_fl_lock);
+	rcu_read_unlock();
+
 	if (err != 0)
 		goto done;
 
-	fl1 = fl_intern(net, fl, freq->flr_label);
 	if (fl1)
 		goto recheck;
 

base-commit: ebb639024ebd47a13a511cce6ae630c15e4b3126
-- 
2.34.1


^ permalink raw reply related

* [PATCH net v7 2/2] ipv6: flowlabel: enforce per-netns limit for unprivileged callers
From: Maoyi Xie @ 2026-05-05  7:20 UTC (permalink / raw)
  To: David S . Miller
  Cc: Jakub Kicinski, Paolo Abeni, Eric Dumazet, David Ahern,
	Alexey Kuznetsov, Willem de Bruijn, Willem de Bruijn, netdev,
	linux-kernel, stable
In-Reply-To: <20260505072015.1672730-1-maoyi.xie@ntu.edu.sg>

fl_size, fl_ht and ip6_fl_lock in net/ipv6/ip6_flowlabel.c are
file scope and shared across netns. mem_check() reads fl_size to
decide whether to deny non-CAP_NET_ADMIN callers. capable() runs
against init_user_ns, so an unprivileged user in any non-init
userns can push fl_size past FL_MAX_SIZE - FL_MAX_SIZE / 4 and
starve every other unprivileged userns on the host.

Add struct netns_ipv6::flowlabel_count, bumped and decremented
next to fl_size in fl_intern, ip6_fl_gc and ip6_fl_purge. The new
field fills the existing 4-byte hole after ipmr_seq, so struct
netns_ipv6 stays the same size on 64-bit builds.

Bump FL_MAX_SIZE from 4096 to 8192. It has been 4096 since the
file was added. Machines and connection counts have grown.

mem_check() folds an extra per-netns ceiling into the existing
non-CAP_NET_ADMIN conditional. The ceiling is half of the total
budget that unprivileged callers have ever been able to use, i.e.
(FL_MAX_SIZE - FL_MAX_SIZE / 4) / 2 = 3072 entries. With
FL_MAX_SIZE doubled, this preserves the original per-user reach
of 3K (what an unprivileged caller could already obtain before
this change), while forcing an attacker to spread allocations
across at least two netns to exhaust the global non-CAP_NET_ADMIN
budget.

CAP_NET_ADMIN against init_user_ns still bypasses both caps.

The previous patch took ip6_fl_lock across mem_check and
fl_intern, so the new flowlabel_count read in mem_check and the
new flowlabel_count++ in fl_intern run under the same critical
section. flowlabel_count is therefore plain int, like fl_size.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Suggested-by: Willem de Bruijn <willemb@google.com>
Cc: stable@vger.kernel.org # v5.15+
Signed-off-by: Maoyi Xie <maoyi.xie@ntu.edu.sg>
---
 include/net/netns/ipv6.h |  1 +
 net/ipv6/ip6_flowlabel.c | 14 +++++++++++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 499e42881..875916d60 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -119,6 +119,7 @@ struct netns_ipv6 {
 	struct fib_notifier_ops	*notifier_ops;
 	struct fib_notifier_ops	*ip6mr_notifier_ops;
 	atomic_t		ipmr_seq;
+	int			flowlabel_count;
 	struct {
 		struct hlist_head head;
 		spinlock_t	lock;
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 43b5e9ce9..e1b2460f9 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -36,7 +36,7 @@
 /* FL hash table */
 
 #define FL_MAX_PER_SOCK	32
-#define FL_MAX_SIZE	4096
+#define FL_MAX_SIZE	8192
 #define FL_HASH_MASK	255
 #define FL_HASH(l)	(ntohl(l)&FL_HASH_MASK)
 
@@ -162,8 +162,9 @@ static void ip6_fl_gc(struct timer_list *unused)
 				ttd = fl->expires;
 				if (time_after_eq(now, ttd)) {
 					*flp = fl->next;
-					fl_free(fl);
 					fl_size--;
+					fl->fl_net->ipv6.flowlabel_count--;
+					fl_free(fl);
 					continue;
 				}
 				if (!sched || time_before(ttd, sched))
@@ -197,6 +198,7 @@ static void __net_exit ip6_fl_purge(struct net *net)
 				*flp = fl->next;
 				fl_free(fl);
 				fl_size--;
+				net->ipv6.flowlabel_count--;
 				continue;
 			}
 			flp = &fl->next;
@@ -242,6 +244,7 @@ static struct ip6_flowlabel *fl_intern(struct net *net,
 	fl->next = fl_ht[FL_HASH(fl->label)];
 	rcu_assign_pointer(fl_ht[FL_HASH(fl->label)], fl);
 	fl_size++;
+	net->ipv6.flowlabel_count++;
 	return NULL;
 }
 
@@ -459,6 +462,9 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
 
 static int mem_check(struct sock *sk)
 {
+	const int unpriv_total_limit = FL_MAX_SIZE - (FL_MAX_SIZE / 4);
+	const int unpriv_user_limit = unpriv_total_limit / 2;
+	struct net *net = sock_net(sk);
 	int room;
 	struct ipv6_fl_socklist *sfl;
 	int count = 0;
@@ -477,7 +483,9 @@ static int mem_check(struct sock *sk)
 
 	if (room <= 0 ||
 	    ((count >= FL_MAX_PER_SOCK ||
-	      (count > 0 && room < FL_MAX_SIZE/2) || room < FL_MAX_SIZE/4) &&
+	      (count > 0 && room < FL_MAX_SIZE / 2) ||
+	      room < FL_MAX_SIZE / 4 ||
+	      net->ipv6.flowlabel_count >= unpriv_user_limit) &&
 	     !capable(CAP_NET_ADMIN)))
 		return -ENOBUFS;
 
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH net-next v2] declance: Remove IRQF_ONESHOT
From: Sebastian Andrzej Siewior @ 2026-05-05  7:29 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: netdev, linux-mips, Jakub Kicinski, Andrew Lunn, David S. Miller,
	Eric Dumazet, Paolo Abeni
In-Reply-To: <alpine.DEB.2.21.2605042332070.46195@angie.orcam.me.uk>

On 2026-05-04 23:35:42 [+0100], Maciej W. Rozycki wrote:
> On Sun, 29 Mar 2026, Maciej W. Rozycki wrote:
> 
> >  I've now got back to it and while preparing the justification for the 
> > removal of the IRQF_ONESHOT recommendation and having looked through 
> > Documentation/core-api/real-time/differences.rst I became stumped and 
> > need a further clarification after all.
> > 
> >  I read in the document that:
> > 
> > "However, on a PREEMPT_RT system, interrupts are forced-threaded and no 
> > longer run in hard IRQ context."
> > 
> > and:
> > 
> > "All interrupts are forced-threaded in a PREEMPT_RT system. The exceptions 
> > are interrupts that are requested with the IRQF_NO_THREAD, IRQF_PERCPU, or 
> > IRQF_ONESHOT flags."
> > 
> > -- do I infer correctly that on a PREEMPT_RT system in the absence of any 
> > flags passed to request_irq() the handler requested such as one concerned 
> > here (i.e. lance_dma_merr_int()) will run with interrupts locally enabled 
> > on the CPU?
> 
>  No reply, but I've gone through irq_setup_forced_threading() now and my 
> inference was indeed correct, and the handler does need to be installed 
> with IRQF_NO_THREAD.  I'll send corrective patches shortly.

Sorry. I missed that previous email.
IRQF_NO_THREAD will not force-thread the interrupt handler so it will
run with interrupts disabled.

With force-threading enabled, the interrupt handler is masked in the
IRQ-chip until after the threaded-handler run. See the cond_unmask_irq()
in handle_level_irq() or the mask_irq() & cond_unmask_eoi_irq() in
handle_fasteoi_ack_irq(). That means the hw-IRQ is done, the thread is
running with interrupts enabled but the hw-IRQ will not trigger again.
The cited commit 5a4a4ad851dd8 ("MIPS: Mark cascade and low level
interrupts IRQF_NO_THREAD") is different as it acts on cascading
interrupts which is not what we have here.

If you request a threaded interrupt you must either provide two handler
and the primary must mask the interrupt so it does not fire again or you
pass a flag such as IRQF_ONESHOT and which point the IRQ subsystem will
mask the IRQ within the irqchip so it does not fire again.

>   Maciej

Sebastian

^ permalink raw reply

* Re: [PATCH v5 net-next 3/3] selftests:net: Implement ptp4l sync test using netdevsim
From: Maciek Machnikowski @ 2026-05-05  7:36 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: netdev, richardcochran, milena.olech, willemdebruijn.kernel,
	andrew, vadim.fedorenko, horms
In-Reply-To: <20260504100753.7cc193cc@kernel.org>



On 04/05/2026 19:07, Jakub Kicinski wrote:
> On Sun,  3 May 2026 09:47:47 +0200 Maciek Machnikowski wrote:
>> Add PTP synchronization test using ptp4l and netdevsim.
>>
>> The test creates two netdevsim adapters, links them together
>> and runs the ptp4l leader and ptp4l follower on two ends
>> of the netdevsim link and waits for the follower to report the
>> synchronized state (s2) in its output log.
>>
>> This implementation runs the test runs over IPv4 link.
> 
> Doesn't seem to pass on netdevsim for us:
> 
> # 41.13 [+40.95] # ptp4l follower did not reach locked state (s2) within 40s
> # 41.13 [+0.00] # Follower log (last 10 lines): ptp4l[2179.605]: ioctl SIOCETHTOOL failed: Operation not supported | ptp4l[2179.607]: interface 'eth0' does not support requested timestamping mode | failed to create a clock
> # 41.15 [+0.02] # Check| At /srv/vmksft/testing/wt-2/tools/testing/selftests/net/./ptp.py, line 173, in ptp_sync_test:
> # 41.15 [+0.01] # Check|     _run_ptp4l_wait_sync(nsimsv.ifname, nsimcl.ifname, nssv.name, nscl.name)
> # 41.16 [+0.01] # Check| At /srv/vmksft/testing/wt-2/tools/testing/selftests/net/./ptp.py, line 99, in _run_ptp4l_wait_sync:
> # 41.17 [+0.01] # Check|     ksft_true(False, "PTP sync timeout")
> # 41.17 [+0.00] # Check failed False does not eval to True PTP sync timeout
> # 41.32 [+0.16] not ok 1 ptp.ptp_sync_test
> # 41.33 [+0.00] # Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0
> 
> Anything we need to do?

Can you share the config file you used? Seems the PTP clock was not
found which may lead to PTP_1588_CLOCK_MOCK not being enabled?


^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH v7 net-next 1/8] dpll: add generic DPLL type
From: Nitka, Grzegorz @ 2026-05-05  7:43 UTC (permalink / raw)
  To: Loktionov, Aleksandr, netdev@vger.kernel.org
  Cc: Vecera, Ivan, vadim.fedorenko@linux.dev, kuba@kernel.org,
	jiri@resnulli.us, edumazet@google.com, Kitszel, Przemyslaw,
	richardcochran@gmail.com, donald.hunter@gmail.com,
	linux-kernel@vger.kernel.org, Kubalewski, Arkadiusz,
	andrew+netdev@lunn.ch, intel-wired-lan@lists.osuosl.org,
	horms@kernel.org, Prathosh.Satish@microchip.com,
	Nguyen, Anthony L, pabeni@redhat.com, davem@davemloft.net
In-Reply-To: <IA3PR11MB89864B070906C21C67EF0886E5352@IA3PR11MB8986.namprd11.prod.outlook.com>



> -----Original Message-----
> From: Loktionov, Aleksandr <aleksandr.loktionov@intel.com>
> Sent: Thursday, April 30, 2026 1:49 PM
> To: Nitka, Grzegorz <grzegorz.nitka@intel.com>; netdev@vger.kernel.org
> Cc: Vecera, Ivan <ivecera@redhat.com>; vadim.fedorenko@linux.dev;
> kuba@kernel.org; jiri@resnulli.us; edumazet@google.com; Kitszel,
> Przemyslaw <przemyslaw.kitszel@intel.com>; richardcochran@gmail.com;
> donald.hunter@gmail.com; linux-kernel@vger.kernel.org; Kubalewski,
> Arkadiusz <arkadiusz.kubalewski@intel.com>; andrew+netdev@lunn.ch;
> intel-wired-lan@lists.osuosl.org; horms@kernel.org;
> Prathosh.Satish@microchip.com; Nguyen, Anthony L
> <anthony.l.nguyen@intel.com>; pabeni@redhat.com;
> davem@davemloft.net
> Subject: RE: [Intel-wired-lan] [PATCH v7 net-next 1/8] dpll: add generic DPLL
> type
> 
> 
> 
> > -----Original Message-----
> > From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> > Of Grzegorz Nitka
> > Sent: Thursday, April 30, 2026 11:43 AM
> > To: netdev@vger.kernel.org
> > Cc: Vecera, Ivan <ivecera@redhat.com>; vadim.fedorenko@linux.dev;
> > kuba@kernel.org; jiri@resnulli.us; edumazet@google.com; Kitszel,
> > Przemyslaw <przemyslaw.kitszel@intel.com>; richardcochran@gmail.com;
> > donald.hunter@gmail.com; linux-kernel@vger.kernel.org; Kubalewski,
> > Arkadiusz <arkadiusz.kubalewski@intel.com>; andrew+netdev@lunn.ch;
> > intel-wired-lan@lists.osuosl.org; horms@kernel.org;
> > Prathosh.Satish@microchip.com; Nguyen, Anthony L
> > <anthony.l.nguyen@intel.com>; pabeni@redhat.com;
> davem@davemloft.net
> > Subject: [Intel-wired-lan] [PATCH v7 net-next 1/8] dpll: add generic
> > DPLL type
> >
> > Add DPLL_TYPE_GENERIC to represent DPLL devices which do not fit the
> > existing PPS or EEC classes.
> >
> > The UAPI type is intentionally generic. During netdev discussion,
> > maintainers pointed out that introducing identifiers tied to a
> > specific placement or single design does not scale across ASICs and
> > vendors.
> > The role of a DPLL is already inferable from the spawning driver, bus
> > device, and pin topology, without encoding additional purpose-specific
> > taxonomy in the type name.
> >
> > Using a generic type keeps the UAPI extensible and avoids premature
> > naming that may become incorrect as new hardware topologies are
> > exposed through the DPLL subsystem.
> >
> > Expose the new type through UAPI and netlink specification as
> > "generic".
> >
> > Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
> > ---
> >  Documentation/netlink/specs/dpll.yaml | 3 +++
> >  drivers/dpll/dpll_nl.c                | 2 +-
> >  include/uapi/linux/dpll.h             | 2 ++
> >  3 files changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/netlink/specs/dpll.yaml
> > b/Documentation/netlink/specs/dpll.yaml
> > index 40465a3d7fc2..572cf7ae5f36 100644
> > --- a/Documentation/netlink/specs/dpll.yaml
> > +++ b/Documentation/netlink/specs/dpll.yaml
> > @@ -138,6 +138,9 @@ definitions:
> >        -
> >          name: eec
> >          doc: dpll drives the Ethernet Equipment Clock
> > +      -
> > +        name: generic
> > +        doc: generic dpll type for devices outside PPS/EEC classes
> >      render-max: true
> >    -
> >      type: enum
> > diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c index
> > 1e652340a5d7..9a3b70ea3ae0 100644
> > --- a/drivers/dpll/dpll_nl.c
> > +++ b/drivers/dpll/dpll_nl.c
> > @@ -34,7 +34,7 @@ const struct nla_policy
> > dpll_reference_sync_nl_policy[DPLL_A_PIN_STATE + 1] = {  static const
> > struct nla_policy dpll_device_id_get_nl_policy[DPLL_A_TYPE + 1] = {
> >  	[DPLL_A_MODULE_NAME] = { .type = NLA_NUL_STRING, },
> >  	[DPLL_A_CLOCK_ID] = { .type = NLA_U64, },
> > -	[DPLL_A_TYPE] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
> > +	[DPLL_A_TYPE] = NLA_POLICY_RANGE(NLA_U32, 1, 3),
> 
> I think you need especial note if you manually edit "do not edit directly" file.
> Isn't it ?
> 

This is not manual edit. This file is generated by ynl-regen.sh script.
And attached to this commit.
I believe this is the way how it should be processed.

Thanks!

Grzegorz

> >  };
> >
> >  /* DPLL_CMD_DEVICE_GET - do */
> > diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
> > index 871685f7c353..648553053cd8 100644
> > --- a/include/uapi/linux/dpll.h
> > +++ b/include/uapi/linux/dpll.h
> > @@ -109,10 +109,12 @@ enum dpll_clock_quality_level {
> >   * enum dpll_type - type of dpll, valid values for DPLL_A_TYPE
> > attribute
> >   * @DPLL_TYPE_PPS: dpll produces Pulse-Per-Second signal
> >   * @DPLL_TYPE_EEC: dpll drives the Ethernet Equipment Clock
> > + * @DPLL_TYPE_GENERIC: generic dpll type for devices outside PPS/EEC
> > + classes
> >   */
> >  enum dpll_type {
> >  	DPLL_TYPE_PPS = 1,
> >  	DPLL_TYPE_EEC,
> > +	DPLL_TYPE_GENERIC,
> >
> >  	/* private: */
> >  	__DPLL_TYPE_MAX,
> > --
> > 2.39.3


^ permalink raw reply

* Re: [PATCH net] net: rtsn: fix mdio_node leak in rtsn_mdio_alloc()
From: Geert Uytterhoeven @ 2026-05-05  7:43 UTC (permalink / raw)
  To: Shitalkumar Gandhi
  Cc: Niklas Söderlund, Jakub Kicinski, David S . Miller,
	Eric Dumazet, Paolo Abeni, Andrew Lunn, Simon Horman, netdev,
	linux-renesas-soc, linux-kernel, Shitalkumar Gandhi
In-Reply-To: <20260504200356.3529873-1-shitalkumar.gandhi@cambiumnetworks.com>

Hi Shitalkumar,

On Mon, 4 May 2026 at 22:05, Shitalkumar Gandhi
<shital.gandhi45@gmail.com> wrote:
> of_get_child_by_name() takes a reference. The rtsn_reset() and
> rtsn_change_mode() failure paths jump to out_free_bus and leak
> mdio_node.
>
> Add out_put_node to drop it before falling through.
>
> Fixes: b0d3969d2b4d ("net: ethernet: rtsn: Add support for Renesas Ethernet-TSN")
> Signed-off-by: Shitalkumar Gandhi <shitalkumar.gandhi@cambiumnetworks.com>

Thanks for your patch!

> --- a/drivers/net/ethernet/renesas/rtsn.c
> +++ b/drivers/net/ethernet/renesas/rtsn.c
> @@ -797,11 +797,11 @@ static int rtsn_mdio_alloc(struct rtsn_private *priv)
>         /* Enter config mode before registering the MDIO bus */
>         ret = rtsn_reset(priv);
>         if (ret)
> -               goto out_free_bus;
> +               goto out_put_node;
>
>         ret = rtsn_change_mode(priv, OCR_OPC_CONFIG);
>         if (ret)
> -               goto out_free_bus;
> +               goto out_put_node;
>
>         rtsn_modify(priv, MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK,
>                     MPIC_PSMCS_DEFAULT | MPIC_PSMHT_DEFAULT);
> @@ -823,7 +823,8 @@ static int rtsn_mdio_alloc(struct rtsn_private *priv)
>         priv->mii = mii;
>
>         return 0;
> -

Please keep this blank line, as it serves as a clear separation between
success and failure paths.

> +out_put_node:
> +       of_node_put(mdio_node);
>  out_free_bus:
>         mdiobus_free(mii);
>         return ret;

For the logical change:
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

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

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

^ permalink raw reply

* [PATCH net-next v2] net: bridge: replace simple_strtoul with kstrtoul
From: Aadarsh Chandra @ 2026-05-05  7:45 UTC (permalink / raw)
  To: razor, idosch; +Cc: davem, kuba, netdev, bridge, linux-kernel, Aadarsh Chandra

The simple_strtoul() function is deprecated. It does not handle
errors or overflows correctly. Replace it with kstrtoul() in
brport_store() to ensure that invalid user input is caught and
returned as an error.

v2: target net-next and simplify by reusing the ret variable as
    suggested by Nikolay Aleksandrov.

Signed-off-by: Aadarsh Chandra <aadarsh.official.xz@gmail.com>
---
 net/bridge/br_sysfs_if.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 1f57c36a7fc0..cdecc7d1260c 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -318,7 +318,6 @@ static ssize_t brport_store(struct kobject *kobj,
 	struct net_bridge_port *p = kobj_to_brport(kobj);
 	ssize_t ret = -EINVAL;
 	unsigned long val;
-	char *endp;
 
 	if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN))
 		return -EPERM;
@@ -339,8 +338,8 @@ static ssize_t brport_store(struct kobject *kobj,
 		spin_unlock_bh(&p->br->lock);
 		kfree(buf_copy);
 	} else if (brport_attr->store) {
-		val = simple_strtoul(buf, &endp, 0);
-		if (endp == buf)
+		ret = kstrtoul(buf, 0, &val);
+		if (ret)
 			goto out_unlock;
 		spin_lock_bh(&p->br->lock);
 		ret = brport_attr->store(p, val);
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH net-next v2] net: bridge: replace simple_strtoul with kstrtoul
From: Nikolay Aleksandrov @ 2026-05-05  7:54 UTC (permalink / raw)
  To: Aadarsh Chandra, idosch; +Cc: davem, kuba, netdev, bridge, linux-kernel
In-Reply-To: <20260505074515.636244-1-aadarsh.official.xz@gmail.com>

On 05/05/2026 10:45, Aadarsh Chandra wrote:
> The simple_strtoul() function is deprecated. It does not handle
> errors or overflows correctly. Replace it with kstrtoul() in
> brport_store() to ensure that invalid user input is caught and
> returned as an error.
> 
> v2: target net-next and simplify by reusing the ret variable as
>      suggested by Nikolay Aleksandrov.
> 

Nice that you've given us the changes, but it should be below...


> Signed-off-by: Aadarsh Chandra <aadarsh.official.xz@gmail.com>
> ---

... here, so it's not included in the commit message.

>   net/bridge/br_sysfs_if.c | 5 ++---
>   1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
> index 1f57c36a7fc0..cdecc7d1260c 100644
> --- a/net/bridge/br_sysfs_if.c
> +++ b/net/bridge/br_sysfs_if.c
> @@ -318,7 +318,6 @@ static ssize_t brport_store(struct kobject *kobj,
>   	struct net_bridge_port *p = kobj_to_brport(kobj);
>   	ssize_t ret = -EINVAL;
>   	unsigned long val;
> -	char *endp;
>   
>   	if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN))
>   		return -EPERM;
> @@ -339,8 +338,8 @@ static ssize_t brport_store(struct kobject *kobj,
>   		spin_unlock_bh(&p->br->lock);
>   		kfree(buf_copy);
>   	} else if (brport_attr->store) {
> -		val = simple_strtoul(buf, &endp, 0);
> -		if (endp == buf)
> +		ret = kstrtoul(buf, 0, &val);
> +		if (ret)
>   			goto out_unlock;
>   		spin_lock_bh(&p->br->lock);
>   		ret = brport_attr->store(p, val);

You should wait 24 hours before posting a new version.
The patch looks good to me, if there's a need for v3
please add my:

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>

Cheers,
  Nik




^ permalink raw reply

* [PATCH v2] net: stmmac: Use interrupt mode INTM=1 for per channel irq
From: muhammad.nazim.amirul.nazle.asmade @ 2026-05-05  8:03 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, andrew+netdev, linux-kernel

From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>

commit 6ccf12ae111e ("net: stmmac: use interrupt mode INTM=1 for
multi-MSI") introduced INTM=1 interrupt mode for platforms using MSI.

Apply a similar approach to enable per-channel interrupts using shared
peripheral interrupt (SPI), so that only per-channel TX and RX
interrupts (TI/RI) are handled by the TX/RX ISR without invoking the
common interrupt ISR.

Signed-off-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
---
Changes in v2:
- Rename macros to use XGMAC_ prefix to match dwxgmac2.h convention.
- Drop DMA_MODE_INTM_SHIFT and use FIELD_PREP() instead.
- Wire up multi_irq_en via STMMAC_FLAG_MULTI_IRQ_EN in stmmac_main.c
  so the feature is reachable by platform drivers.
- Drop unused plat_stmmacenet_data fields (ext_snapshot_num,
  int_snapshot_en, ext_snapshot_en, multi_msi_en, multi_irq_en)
  which duplicate existing flags bits.
- Remove misleading commit message paragraph about ISR decoupling
  (dwxgmac2_dma_interrupt() already handles TI/RI independently of NIS).
---
 drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h     | 2 ++
 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 9 +++++++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 2 ++
 include/linux/stmmac.h                             | 2 ++
 4 files changed, 15 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
index 51943705a2b0..544541e0e2a5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -320,6 +320,8 @@
 /* DMA Registers */
 #define XGMAC_DMA_MODE			0x00003000
 #define XGMAC_SWR			BIT(0)
+#define XGMAC_DMA_MODE_INTM_MASK	GENMASK(13, 12)
+#define XGMAC_DMA_MODE_INTM_MODE1	0x1
 #define XGMAC_DMA_SYSBUS_MODE		0x00003004
 #define XGMAC_WR_OSR_LMT		GENMASK(29, 24)
 #define XGMAC_RD_OSR_LMT		GENMASK(21, 16)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index 03437f1cf3df..59fe488933d3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -4,6 +4,7 @@
  * stmmac XGMAC support.
  */
 
+#include <linux/bitfield.h>
 #include <linux/iopoll.h>
 #include "stmmac.h"
 #include "dwxgmac2.h"
@@ -31,6 +32,14 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
 		value |= XGMAC_EAME;
 
 	writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE);
+
+	if (dma_cfg->multi_irq_en) {
+		value = readl(ioaddr + XGMAC_DMA_MODE);
+		value &= ~XGMAC_DMA_MODE_INTM_MASK;
+		value |= FIELD_PREP(XGMAC_DMA_MODE_INTM_MASK,
+				    XGMAC_DMA_MODE_INTM_MODE1);
+		writel(value, ioaddr + XGMAC_DMA_MODE);
+	}
 }
 
 static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ca68248dbc78..ac258641f5a1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7831,6 +7831,8 @@ static int __stmmac_dvr_probe(struct device *device,
 	priv->dev->base_addr = (unsigned long)res->addr;
 	priv->plat->dma_cfg->multi_msi_en =
 		(priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN);
+	priv->plat->dma_cfg->multi_irq_en =
+		(priv->plat->flags & STMMAC_FLAG_MULTI_IRQ_EN);
 
 	priv->dev->irq = res->irq;
 	priv->wol_irq = res->wol_irq;
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 4430b967abde..2823ac3cb7a4 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -122,6 +122,7 @@ struct stmmac_dma_cfg {
 	bool eame;
 	/* multi_msi_en: stmmac core internal */
 	bool multi_msi_en;
+	bool multi_irq_en;
 	/* atds: stmmac core internal */
 	bool atds;
 };
@@ -202,6 +203,7 @@ enum dwmac_core_type {
 #define STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP	BIT(5)
 #define STMMAC_FLAG_VLAN_FAIL_Q_EN		BIT(6)
 #define STMMAC_FLAG_MULTI_MSI_EN		BIT(7)
+#define STMMAC_FLAG_MULTI_IRQ_EN		BIT(17)
 #define STMMAC_FLAG_EXT_SNAPSHOT_EN		BIT(8)
 #define STMMAC_FLAG_INT_SNAPSHOT_EN		BIT(9)
 #define STMMAC_FLAG_EEE_DISABLE			BIT(10)
-- 
2.43.7


^ permalink raw reply related

* Re: [PATCH] net: stmmac: Use interrupt mode INTM=1 for per channel irq
From: Nazle Asmade, Muhammad Nazim Amirul @ 2026-05-05  8:05 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: netdev@vger.kernel.org, davem@davemloft.net, pabeni@redhat.com,
	edumazet@google.com, andrew+netdev@lunn.ch,
	linux-kernel@vger.kernel.org
In-Reply-To: <20260501003735.3120766-1-kuba@kernel.org>

On 1/5/2026 8:37 am, Jakub Kicinski wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> net: stmmac: Use interrupt mode INTM=1 for per channel irq
> 
> This commit adds programming of the XGMAC DMA_MODE.INTM=1 bit on xgmac2
> to deliver per-channel TX/RX interrupts via shared peripheral interrupts
> (SPI), mirroring the approach of the earlier MSI-oriented commit
> 6ccf12ae111e. New fields are added to stmmac_dma_cfg and
> plat_stmmacenet_data to drive the new path.
> 
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
>> index 51943705a2b0..94cbf24b3118 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
>> @@ -320,6 +320,9 @@
>>   /* DMA Registers */
>>   #define XGMAC_DMA_MODE			0x00003000
>>   #define XGMAC_SWR			BIT(0)
>> +#define DMA_MODE_INTM_MASK		GENMASK(13, 12)
>> +#define DMA_MODE_INTM_SHIFT		12
>> +#define DMA_MODE_INTM_MODE1		0x1
> 
> Should these three macros carry the XGMAC_ prefix used by every other
> symbol in dwxgmac2.h (XGMAC_DMA_MODE, XGMAC_SWR, XGMAC_DMA_SYSBUS_MODE,
> and so on)?  The dwmac4 sibling header defines analogous symbols as
> DMA_BUS_MODE_INTM_MASK / DMA_BUS_MODE_INTM_MODE1, but within dwxgmac2.h
> the established convention appears to be XGMAC_*.
> 
> The referenced precedent commit 6ccf12ae111e uses FIELD_PREP() /
> u32_replace_bits() rather than a hand-rolled SHIFT constant.  Would it
> be cleaner to drop DMA_MODE_INTM_SHIFT and use FIELD_PREP() here too?
> 
>>   #define XGMAC_DMA_SYSBUS_MODE		0x00003004
>>   #define XGMAC_WR_OSR_LMT		GENMASK(29, 24)
>>   #define XGMAC_RD_OSR_LMT		GENMASK(21, 16)
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>> index 03437f1cf3df..3789b62cd2e3 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
>> @@ -31,6 +31,13 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
>>   		value |= XGMAC_EAME;
>>   
>>   	writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE);
>> +
>> +	if (dma_cfg->multi_irq_en) {
>> +		value = readl(ioaddr + XGMAC_DMA_MODE);
>> +		value &= ~DMA_MODE_INTM_MASK;
>> +		value |= (DMA_MODE_INTM_MODE1 << DMA_MODE_INTM_SHIFT);
>> +		writel(value, ioaddr + XGMAC_DMA_MODE);
>> +	}
>>   }
> 
> Is this new block reachable on any platform?
> 
> A tree-wide search for multi_irq_en returns only three references: this
> read site and the two struct declarations added below.  Nothing assigns
> dma_cfg->multi_irq_en anywhere, so the condition appears to always be
> false and INTM=1 would never be programmed.
> 
> For comparison, the analogous multi_msi_en is set up in stmmac_main.c:
> 
>      priv->plat->dma_cfg->multi_msi_en =
>              (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN);
> 
> and is consumed from glue drivers such as dwmac-intel.c, dwmac-loongson.c,
> and dwmac-s32.c.  Should an equivalent assignment and a corresponding
> plat flag (or the new plat->multi_irq_en field) be wired up in this
> patch so the feature actually takes effect?
> 
> The commit message also states:
> 
>      The TX/RX NORMAL interrupt check is decoupled since the NIS bit is
>      not asserted for TI/RI events when INTM=1.
> 
> but the diff touches only dwxgmac2_dma_init() and does not modify
> dwxgmac2_dma_interrupt() or any other ISR/interrupt-status path.  The
> existing dwxgmac2_dma_interrupt() already tests XGMAC_RI and
> XGMAC_TI | XGMAC_TBU independently of XGMAC_NIS:
> 
>      if (likely(intr_status & XGMAC_RI)) {
>              ...
>      }
>      if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {
>              ...
>      }
> 
> Is this paragraph carried over from the earlier dwmac4 commit
> 6ccf12ae111e, or is a companion hunk missing from this patch?
> 
>>   static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
>> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
>> index 4430b967abde..5deaa1a797a5 100644
>> --- a/include/linux/stmmac.h
>> +++ b/include/linux/stmmac.h
>> @@ -122,6 +122,7 @@ struct stmmac_dma_cfg {
>>   	bool eame;
>>   	/* multi_msi_en: stmmac core internal */
>>   	bool multi_msi_en;
>> +	bool multi_irq_en;
>>   	/* atds: stmmac core internal */
>>   	bool atds;
>>   };
>> @@ -349,6 +350,11 @@ struct plat_stmmacenet_data {
>>   	u8 vlan_fail_q;
>>   	bool provide_bus_info;
>>   	int int_snapshot_num;
>> +	int ext_snapshot_num;
>> +	bool int_snapshot_en;
>> +	bool ext_snapshot_en;
>> +	bool multi_msi_en;
>> +	bool multi_irq_en;
>>   	int msi_mac_vec;
>>   	int msi_wol_vec;
>>   	int msi_sfty_ce_vec;
> 
> Are these five new plat_stmmacenet_data fields used by anything?
> 
> A tree-wide search finds no reader or writer for ext_snapshot_num,
> int_snapshot_en, ext_snapshot_en, plat->multi_msi_en, or
> plat->multi_irq_en, and they are not mentioned in the commit message.
> The commit message scope is limited to enabling INTM=1 per-channel SPI
> IRQs, which would only require stmmac_dma_cfg::multi_irq_en.
> 
> The same concepts already appear to be represented via plat->flags bits
> (STMMAC_FLAG_MULTI_MSI_EN, STMMAC_FLAG_INT_SNAPSHOT_EN,
> STMMAC_FLAG_EXT_SNAPSHOT_EN) and the existing int_snapshot_num member.
> Could the four unrelated fields be dropped from this patch and, if
> still needed, be introduced in a separate series that actually wires
> them up?  Having both a flags bit and a bool for the same concept
> risks future drift about which representation is authoritative.
All comments have been addressed and updated in v2

https://lore.kernel.org/all/20260505080311.17405-1-muhammad.nazim.amirul.nazle.asmade@altera.com/

Nazim


^ permalink raw reply

* Re: [RFC net] ovpn: fix race between deleting interface and adding new peer
From: Roman Gushchin @ 2026-05-05  8:07 UTC (permalink / raw)
  To: Antonio Quartulli
  Cc: Jakub Kicinski, netdev, ralf, Hyunwoo Kim, Sabrina Dubroca
In-Reply-To: <33639813-1de3-4a82-966f-7a0daab25433@openvpn.net>

Antonio Quartulli <antonio@openvpn.net> writes:

> On 05/05/2026 01:54, Jakub Kicinski wrote:
>> On Mon,  4 May 2026 16:20:33 +0200 Antonio Quartulli wrote:
>>> This patch is sent as RFC to give the AI a chance to review it once
>>> again, since it was able to spot a new race condition in its
>>> previous version.
>> FWIW I think you can just ask for Sashiko to track the openvpn
>> mailing
>> list?
>
> Yes, indeed.
> I just went through this discussion for the batman-adv kernel module.
>
> @Roman: is it possible for Sashiko to consider certain patches only?
> On the openvpn-devel mailing list there are also patches for the
> openvpn userspace program flying around.

Sashiko ignores all patches which it can't apply successfully to the
kernel tree, so it's likely not a problem.

If it will be a problem, I'll master something.

Thanks

>
>
> Regards,

^ permalink raw reply

* Re: [PATCH net-next v5 3/3] gve: implement PTP gettimex64
From: Paolo Abeni @ 2026-05-05  8:08 UTC (permalink / raw)
  To: Harshitha Ramamurthy, netdev
  Cc: joshwash, andrew+netdev, davem, edumazet, kuba, richardcochran,
	jstultz, tglx, sboyd, willemb, nktgrg, jfraker, ziweixiao,
	maolson, jordanrhee, thostet, alok.a.tiwari, pkaligineedi, horms,
	dwmw2, jacob.e.keller, yyd, linux-kernel, Naman Gulati
In-Reply-To: <20260429012819.3102675-4-hramamurthy@google.com>

On 4/29/26 3:28 AM, Harshitha Ramamurthy wrote:
> From: Jordan Rhee <jordanrhee@google.com>
> 
> Enable chrony and phc2sys to synchronize system clock to NIC clock.
> 
> The system cycle counters are sampled by the device to minimize the
> uncertainty window. If the system times are sampled in the host, the
> delta between pre and post readings is 100us or more due to AQ command
> latency. The system times returned by the device have a delta of ~1us,
> which enables significantly more accurate clock synchronization.
> 
> Reviewed-by: Willem de Bruijn <willemb@google.com>
> Reviewed-by: Kevin Yang <yyd@google.com>
> Reviewed-by: Naman Gulati <namangulati@google.com>
> Signed-off-by: Jordan Rhee <jordanrhee@google.com>
> Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
> ---
> Changes in v5:
> - Reformulate retry loop in terms of total timeout (Jakub Kicinski)
> 
> Changes in v3:
> - Take system time snapshot inside the mutex
> - Return -EOPNOTSUPP if cross-timestamp is requested on an arch other
>   than x86 or arm64
> 
> Changes in v2:
>  - fix compilation warning on ARM by casting cycles_t to u64
> ---
>  drivers/net/ethernet/google/gve/gve_adminq.h |   4 +-
>  drivers/net/ethernet/google/gve/gve_ptp.c    | 196 ++++++++++++++++++-
>  2 files changed, 191 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h
> index 22a74b6aa17e..e6dcf6da9091 100644
> --- a/drivers/net/ethernet/google/gve/gve_adminq.h
> +++ b/drivers/net/ethernet/google/gve/gve_adminq.h
> @@ -411,8 +411,8 @@ static_assert(sizeof(struct gve_adminq_report_nic_ts) == 16);
>  
>  struct gve_nic_ts_report {
>  	__be64 nic_timestamp; /* NIC clock in nanoseconds */
> -	__be64 reserved1;
> -	__be64 reserved2;
> +	__be64 pre_cycles; /* System cycle counter before NIC clock read */
> +	__be64 post_cycles; /* System cycle counter after NIC clock read */
>  	__be64 reserved3;
>  	__be64 reserved4;
>  };
> diff --git a/drivers/net/ethernet/google/gve/gve_ptp.c b/drivers/net/ethernet/google/gve/gve_ptp.c
> index ad15f1209a83..c6c98ef825aa 100644
> --- a/drivers/net/ethernet/google/gve/gve_ptp.c
> +++ b/drivers/net/ethernet/google/gve/gve_ptp.c
> @@ -10,28 +10,210 @@
>  /* Interval to schedule a nic timestamp calibration, 250ms. */
>  #define GVE_NIC_TS_SYNC_INTERVAL_MS 250
>  
> +/*
> + * Stores cycle counter samples in get_cycles() units from a
> + * sandwiched NIC clock read
> + */
> +struct gve_sysclock_sample {
> +	/* system time snapshot taken just before issuing AdminQ command */
> +	struct system_time_snapshot snapshot;
> +	/* Cycle counter from NIC before clock read */
> +	u64 nic_pre_cycles;
> +	/* Cycle counter from NIC after clock read */
> +	u64 nic_post_cycles;
> +	/* Cycle counter from host before issuing AQ command */
> +	cycles_t host_pre_cycles;
> +	/* Cycle counter from host after AQ command returns */
> +	cycles_t host_post_cycles;
> +};
> +
> +/*
> + * Read NIC clock by issuing the AQ command. The command is subject to
> + * rate limiting and may need to be retried. Requires nic_ts_read_lock
> + * to be held.
> + */
> +static int gve_ptp_read_timestamp(struct gve_ptp *ptp, cycles_t *pre_cycles,
> +				  cycles_t *post_cycles,
> +				  struct system_time_snapshot *snap)
> +{
> +	unsigned long deadline = jiffies + msecs_to_jiffies(100);
> +	unsigned long delay_us = 1000;
> +	int err;
> +
> +	lockdep_assert_held(&ptp->nic_ts_read_lock);
> +
> +	do {
> +		if (snap)
> +			ktime_get_snapshot(snap);
> +
> +		*pre_cycles = get_cycles();
> +		err = gve_adminq_report_nic_ts(ptp->priv,
> +					       ptp->nic_ts_report_bus);
> +
> +		/* Prevent get_cycles() from being speculatively executed
> +		 * before the AdminQ command
> +		 */
> +		rmb();
> +		*post_cycles = get_cycles();
> +		if (likely(err != -EAGAIN))
> +			return err;
> +
> +		fsleep(delay_us);
> +
> +		/* Exponential backoff */
> +		delay_us *= 2;
> +	} while (time_before(jiffies, deadline));
> +
> +	return -ETIMEDOUT;
> +}
> +
>  /* Read the nic timestamp from hardware via the admin queue. */
> -static int gve_clock_nic_ts_read(struct gve_ptp *ptp, u64 *nic_raw)
> +static int gve_clock_nic_ts_read(struct gve_ptp *ptp, u64 *nic_raw,
> +				 struct gve_sysclock_sample *sysclock)
>  {
> +	cycles_t host_pre_cycles, host_post_cycles;
> +	struct gve_nic_ts_report *ts_report;
>  	int err;
>  
>  	mutex_lock(&ptp->nic_ts_read_lock);
> -	err = gve_adminq_report_nic_ts(ptp->priv, ptp->nic_ts_report_bus);
> -	if (err)
> +	err = gve_ptp_read_timestamp(ptp, &host_pre_cycles, &host_post_cycles,
> +				     sysclock ? &sysclock->snapshot : NULL);
> +	if (err) {
> +		dev_err_ratelimited(&ptp->priv->pdev->dev,
> +				    "AdminQ timestamp read failed: %d\n", err);
>  		goto out;
> +	}
>  
> -	*nic_raw = be64_to_cpu(ptp->nic_ts_report->nic_timestamp);
> +	ts_report = ptp->nic_ts_report;
> +	*nic_raw = be64_to_cpu(ts_report->nic_timestamp);
> +
> +	if (sysclock) {
> +		sysclock->nic_pre_cycles = be64_to_cpu(ts_report->pre_cycles);
> +		sysclock->nic_post_cycles = be64_to_cpu(ts_report->post_cycles);
> +		sysclock->host_pre_cycles = host_pre_cycles;
> +		sysclock->host_post_cycles = host_post_cycles;
> +	}
>  
>  out:
>  	mutex_unlock(&ptp->nic_ts_read_lock);
>  	return err;
>  }
>  
> +struct gve_cycles_to_clock_callback_ctx {
> +	u64 cycles;
> +};
> +
> +static int gve_cycles_to_clock_fn(ktime_t *device_time,
> +				  struct system_counterval_t *system_counterval,
> +				  void *ctx)
> +{
> +	struct gve_cycles_to_clock_callback_ctx *context = ctx;
> +
> +	*device_time = 0;
> +
> +	system_counterval->cycles = context->cycles;
> +	system_counterval->use_nsecs = false;
> +
> +	if (IS_ENABLED(CONFIG_X86))
> +		system_counterval->cs_id = CSID_X86_TSC;
> +	else if (IS_ENABLED(CONFIG_ARM64))
> +		system_counterval->cs_id = CSID_ARM_ARCH_COUNTER;
> +	else
> +		return -EOPNOTSUPP;
> +
> +	return 0;
> +}
> +
> +/*
> + * Convert a raw cycle count (e.g. from get_cycles()) to the system clock
> + * type specified by clockid. The system_time_snapshot must be taken before
> + * the cycle counter is sampled.
> + */
> +static int gve_cycles_to_timespec64(struct gve_priv *priv, clockid_t clockid,
> +				    struct system_time_snapshot *snap,
> +				    u64 cycles, struct timespec64 *ts)
> +{
> +	struct gve_cycles_to_clock_callback_ctx ctx = {0};
> +	struct system_device_crosststamp xtstamp;
> +	int err;
> +
> +	ctx.cycles = cycles;
> +	err = get_device_system_crosststamp(gve_cycles_to_clock_fn, &ctx, snap,
> +					    &xtstamp);
> +	if (err) {
> +		dev_err_ratelimited(&priv->pdev->dev,
> +				    "get_device_system_crosststamp() failed to convert %lld cycles to system time: %d\n",
> +				    cycles,
> +				    err);
> +		return err;
> +	}
> +
> +	switch (clockid) {
> +	case CLOCK_REALTIME:
> +		*ts = ktime_to_timespec64(xtstamp.sys_realtime);
> +		break;
> +	case CLOCK_MONOTONIC_RAW:
> +		*ts = ktime_to_timespec64(xtstamp.sys_monoraw);
> +		break;
> +	default:
> +		dev_err_ratelimited(&priv->pdev->dev,
> +				    "Cycle count conversion to clockid %d not supported\n",
> +				    clockid);
> +		return -EOPNOTSUPP;
> +	}
> +
> +	return 0;
> +}
> +
>  static int gve_ptp_gettimex64(struct ptp_clock_info *info,
>  			      struct timespec64 *ts,
>  			      struct ptp_system_timestamp *sts)
>  {
> -	return -EOPNOTSUPP;
> +	struct gve_ptp *ptp = container_of(info, struct gve_ptp, info);
> +	struct gve_sysclock_sample sysclock = {0};
> +	struct gve_priv *priv = ptp->priv;
> +	u64 nic_ts;
> +	int err;
> +
> +	if (sts && !(IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_ARM64)))
> +		return -EOPNOTSUPP;
> +
> +	err = gve_clock_nic_ts_read(ptp, &nic_ts, sts ? &sysclock : NULL);
> +	if (err)
> +		return err;
> +
> +	if (sts) {
> +		/* Reject samples with out of order system clock values */
> +		if (!(sysclock.host_pre_cycles <= sysclock.nic_pre_cycles &&
> +		      sysclock.nic_pre_cycles  <= sysclock.nic_post_cycles &&
> +		      sysclock.nic_post_cycles <= sysclock.host_post_cycles)) {
> +			dev_err_ratelimited(&priv->pdev->dev,
> +					    "AdminQ system clock cycle counts out of order. Expecting %llu <= %llu <= %llu <= %llu\n",
> +					    (u64)sysclock.host_pre_cycles,
> +					    sysclock.nic_pre_cycles,
> +					    sysclock.nic_post_cycles,
> +					    (u64)sysclock.host_post_cycles);
> +			return -EBADMSG;

Sashiko/gemini is reporting the following:

---
If older firmware does not support this feature and returns 0 for the
pre_cycles and post_cycles fields, won't host_pre_cycles <=
nic_pre_cycles evaluate to false since get_cycles() will be greater than
0? If this occurs, the driver returns -EBADMSG instead of -EOPNOTSUPP.
Does returning -EBADMSG prevent userspace tools from gracefully falling
back to legacy PTP ioctls like PTP_SYS_OFFSET, causing PTP
synchronization to fail completely on older firmwares?
---

which looks legit to me, or am I missing something? Note that
proactively triaging sashiko comments would help maintainers a lot.

Thanks,

Paolo


^ permalink raw reply

* RE: [PATCH net] net: wan: fsl_uhdlc_hdlc: fix dma_rmb usage in hdlc_rx_done
From: Holger Brunck @ 2026-05-05  8:14 UTC (permalink / raw)
  To: Christophe Leroy (CS GROUP), netdev@vger.kernel.org
  Cc: linuxppc-dev@lists.ozlabs.org, andrew+netdev@lunn.ch,
	qiang.zhao@nxp.com, horms@kernel.org
In-Reply-To: <d6957853-9d24-4f35-8ea7-ef4376de991e@kernel.org>

> 
> Le 04/05/2026 à 17:56, Holger Brunck a écrit :
> > If dma_rmb is used it has to be done after reading bd_status and
> > checking if R_E_S is zero. Therefore we need to move it into the while loop.
> 
> Can you give more details ? Why does dma_rmb() has to be done after reading
> bd_status and checking if R_E_S is zero ?
> 

when R_E_S is zero in the status of the buffer descriptor it means the buffer is
filled with data from the device.  Now the CPU owns the descriptor. Now we
should execute the dma_rmb to be sure that we read the data correctly. 
And this we need to redo for each buffer descriptor which is filled with data,
that’s why it must be done within the for loop and not before and after.

This is also consistent with the example in Documentation/memory-barriers.txt

Best regards
Holger

^ permalink raw reply

* RE: [PATCH net] net: wan: fsl_ucc_hdlc: fix indentation error
From: Holger Brunck @ 2026-05-05  8:16 UTC (permalink / raw)
  To: Christophe Leroy (CS GROUP), netdev@vger.kernel.org
  Cc: linuxppc-dev@lists.ozlabs.org, andrew+netdev@lunn.ch,
	qiang.zhao@nxp.com, horms@kernel.org
In-Reply-To: <e3abfd12-6537-42b1-b35e-c79a06f87172@kernel.org>

> 
> Le 04/05/2026 à 18:07, Holger Brunck a écrit :
> > Remove the whitespace to fix the indentation.
> 
> Do we really need a patch for that ? What's the added value of doing this change
> compared to the cost of doing it ?
> 

no not mandatory needed. I just saw that and thought that also such minor issues
should be fixed. Can be abandoned.

Best regards
Holger


^ permalink raw reply

* [PATCH net-next v2 0/3] net: Fix protodown with macvlan
From: Ido Schimmel @ 2026-05-05  8:16 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, horms, petrm, Ido Schimmel

When protodown is enabled on a macvlan, two bugs cause the macvlan to
incorrectly report an UP operational state:

1. Toggling the lower device's carrier while protodown is enabled on the
macvlan causes the macvlan to inherit the UP operational state,
effectively bypassing the protodown mechanism.

2. Toggling protodown on and then off on the macvlan while the lower
device has no carrier causes the macvlan to report UP instead of
LOWERLAYERDOWN, since netif_change_proto_down() unconditionally turns
the carrier on.

Patch #1 solves the first problem by making
netif_stacked_transfer_operstate() return early when protodown is on.

Patch #2 solves the second problem by calling
netif_stacked_transfer_operstate() instead of netif_carrier_on() when
protodown is disabled on a net device that has a linked net device.

Patch #3 adds a selftest covering both bugs and the basic protodown
functionality.

Targeting at net-next since these are not regressions (i.e., never
worked).

Note that while these changes are in the core, they should only affect
macvlan as protodown is only supported by macvlan and vxlan and only the
former has a linked net device.

v2:
- Move protodown handling away from drivers to the core (Jakub).
- Add a new test case for vxlan.
v1: https://lore.kernel.org/netdev/20260429124624.835335-1-idosch@nvidia.com/

Ido Schimmel (3):
  net: Do not inherit operational state when protodown is on
  net: Do not unconditionally turn on carrier when turning off protodown
  selftests: net: Add protodown tests

 net/core/dev.c                           |  28 +++-
 tools/testing/selftests/net/Makefile     |   1 +
 tools/testing/selftests/net/protodown.sh | 182 +++++++++++++++++++++++
 3 files changed, 209 insertions(+), 2 deletions(-)
 create mode 100755 tools/testing/selftests/net/protodown.sh

-- 
2.54.0


^ permalink raw reply

* [PATCH net-next v2 1/3] net: Do not inherit operational state when protodown is on
From: Ido Schimmel @ 2026-05-05  8:16 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, horms, petrm, Ido Schimmel
In-Reply-To: <20260505081656.463158-1-idosch@nvidia.com>

The protodown functionality allows user space to turn off the carrier of
a net device:

 # ip link add name dummy1 up type dummy
 # ip link add name macvlan1 up link dummy1 type macvlan mode bridge
 # ip link set dev macvlan1 protodown on
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  DOWN           0a:5c:a3:05:c7:86 <NO-CARRIER,BROADCAST,MULTICAST,UP>

Different applications can set different protodown reasons, which
prevents an application from turning on the carrier of a net device as
long as others want it down:

 # ip link set dev macvlan1 protodown_reason 1 on
 # ip link set dev macvlan1 protodown_reason 2 on
 # ip link set dev macvlan1 protodown off
 Error: Cannot clear protodown, active reasons.
 # ip link set dev macvlan1 protodown_reason 2 off
 # ip link set dev macvlan1 protodown off
 Error: Cannot clear protodown, active reasons.
 # ip link set dev macvlan1 protodown_reason 1 off
 # ip link set dev macvlan1 protodown off
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  UP             0a:5c:a3:05:c7:86 <BROADCAST,MULTICAST,UP,LOWER_UP>

Unfortunately, this mechanism is not very useful when the carrier of a
net device can be toggled by toggling the carrier of its lower device:

 # ip link set dev macvlan1 protodown on
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  DOWN           0a:5c:a3:05:c7:86 <NO-CARRIER,BROADCAST,MULTICAST,UP>
 # ip link set dev dummy1 carrier off
 # ip link set dev dummy1 carrier on
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  UP             0a:5c:a3:05:c7:86 <BROADCAST,MULTICAST,UP,LOWER_UP>

Obviously, this is not the intended behavior and it is unlikely to be
relied on by anyone. In fact, it is a problem for applications like FRR
that use protodown with macvlan on top of a bridge as part of Virtual
Router Redundancy Protocol (VRRP).

Solve this by preventing a net device configured with protodown on from
inheriting the operational state of its lower device. Note that
READ_ONCE() is not needed as RTNL is held.

Output with the patch:

 # ip link add name dummy1 up type dummy
 # ip link add name macvlan1 up link dummy1 type macvlan mode bridge
 # ip link set dev macvlan1 protodown on
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  DOWN           0a:5c:a3:05:c7:86 <NO-CARRIER,BROADCAST,MULTICAST,UP>
 # ip link set dev dummy1 carrier off
 # ip link set dev dummy1 carrier on
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  DOWN           0a:5c:a3:05:c7:86 <NO-CARRIER,BROADCAST,MULTICAST,UP>
 # ip link set dev macvlan1 protodown off
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  UP             0a:5c:a3:05:c7:86 <BROADCAST,MULTICAST,UP,LOWER_UP>

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 net/core/dev.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/core/dev.c b/net/core/dev.c
index 06c195906231..bfb0f297b234 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11113,6 +11113,9 @@ EXPORT_SYMBOL(netdev_change_features);
 void netif_stacked_transfer_operstate(const struct net_device *rootdev,
 					struct net_device *dev)
 {
+	if (dev->proto_down)
+		return;
+
 	if (rootdev->operstate == IF_OPER_DORMANT)
 		netif_dormant_on(dev);
 	else
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v2 2/3] net: Do not unconditionally turn on carrier when turning off protodown
From: Ido Schimmel @ 2026-05-05  8:16 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, horms, petrm, Ido Schimmel
In-Reply-To: <20260505081656.463158-1-idosch@nvidia.com>

The protodown functionality allows user space to turn off the carrier of
a net device:

 # ip link add name dummy1 up type dummy
 # ip link add name macvlan1 up link dummy1 type macvlan mode bridge
 # ip link set dev macvlan1 protodown on
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  DOWN           0a:5c:a3:05:c7:86 <NO-CARRIER,BROADCAST,MULTICAST,UP>

When protodown is turned off, the core unconditionally turns on the
carrier of the net device:

 # ip link set dev macvlan1 protodown off
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  UP             0a:5c:a3:05:c7:86 <BROADCAST,MULTICAST,UP,LOWER_UP>

This is wrong as it means that a macvlan can end up with a carrier when
its lower device does not have a carrier:

 # ip link set dev dummy1 carrier off
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  LOWERLAYERDOWN 0a:5c:a3:05:c7:86 <NO-CARRIER,BROADCAST,MULTICAST,UP>
 # ip link set dev macvlan1 protodown on
 # ip link set dev macvlan1 protodown off
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  UP             0a:5c:a3:05:c7:86 <BROADCAST,MULTICAST,UP,LOWER_UP>

Solve this by resolving the linked net device and if one exists, inherit
its operational state when protodown is turned off. Otherwise, as
before, simply turn on the carrier. Set 'dev->proto_down' before calling
netif_stacked_transfer_operstate() as this function is a NOP when
protodown is turned on.

Resolve the linked net device using a new helper and have it return the
device itself (in a similar fashion to dev_get_iflink()) if the device
does not implement both ndo_get_iflink() and get_link_net(). If the
latter is not implemented, it is unclear in which network namespace we
should look up the linked net device. Currently, this helper is only
used for net devices that support protodown (macvlan and vxlan) and for
both it returns the correct result.

Output with the patch:

 # ip link add name dummy1 up type dummy
 # ip link add name macvlan1 up link dummy1 type macvlan mode bridge
 # ip link set dev dummy1 carrier off
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  LOWERLAYERDOWN 0a:5c:a3:05:c7:86 <NO-CARRIER,BROADCAST,MULTICAST,UP>
 # ip link set dev macvlan1 protodown on
 # ip link set dev macvlan1 protodown off
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  LOWERLAYERDOWN 0a:5c:a3:05:c7:86 <NO-CARRIER,BROADCAST,MULTICAST,UP>
 # ip link set dev dummy1 carrier on
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  UP             0a:5c:a3:05:c7:86 <BROADCAST,MULTICAST,UP,LOWER_UP>
 # ip link set dev macvlan1 protodown on
 # ip link set dev macvlan1 protodown off
 $ ip -br link show dev macvlan1
 macvlan1@dummy1  UP             0a:5c:a3:05:c7:86 <BROADCAST,MULTICAST,UP,LOWER_UP>

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 net/core/dev.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index bfb0f297b234..46f8a2efd982 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10141,17 +10141,38 @@ bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b)
 }
 EXPORT_SYMBOL(netdev_port_same_parent_id);
 
+static struct net_device *dev_get_iflink_dev(struct net_device *dev)
+{
+	struct net *net;
+
+	ASSERT_RTNL();
+
+	if (!dev->netdev_ops->ndo_get_iflink || !dev->rtnl_link_ops ||
+	    !dev->rtnl_link_ops->get_link_net)
+		return dev;
+
+	net = dev->rtnl_link_ops->get_link_net(dev);
+	return __dev_get_by_index(net, dev_get_iflink(dev));
+}
+
 int netif_change_proto_down(struct net_device *dev, bool proto_down)
 {
+	struct net_device *iflink_dev;
+
 	if (!dev->change_proto_down)
 		return -EOPNOTSUPP;
 	if (!netif_device_present(dev))
 		return -ENODEV;
+	iflink_dev = dev_get_iflink_dev(dev);
+	if (!iflink_dev)
+		return -ENODEV;
+	WRITE_ONCE(dev->proto_down, proto_down);
 	if (proto_down)
 		netif_carrier_off(dev);
-	else
+	else if (dev == iflink_dev)
 		netif_carrier_on(dev);
-	WRITE_ONCE(dev->proto_down, proto_down);
+	else
+		netif_stacked_transfer_operstate(iflink_dev, dev);
 	return 0;
 }
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v2 3/3] selftests: net: Add protodown tests
From: Ido Schimmel @ 2026-05-05  8:16 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, horms, petrm, Ido Schimmel
In-Reply-To: <20260505081656.463158-1-idosch@nvidia.com>

Add a selftest for the protodown mechanism.

Five test cases are included:

1. Basic protodown toggling: Verify that setting protodown on macvlan
   results in DOWN operational state and clearing it restores UP.

2. Same as the previous test case, but with vxlan.

3. Protodown reasons: Verify that protodown cannot be cleared while
   there are active protodown reasons, but can be cleared once all
   reasons are removed.

4. Operational state inheritance: Verify that toggling the lower
   device's carrier while protodown is on does not cause the macvlan to
   inherit the UP operational state.

5. Lower layer down: Verify that toggling protodown while the lower
   device has no carrier does not cause the macvlan to transition to UP
   operational state.

Note that the last two test cases fail without "net: Do not inherit
operational state when protodown is on" and "net: Do not unconditionally
turn on carrier when turning off protodown":

 # ./protodown.sh
 TEST: Basic protodown on/off with macvlan                           [ OK ]
 TEST: Basic protodown on/off with vxlan                             [ OK ]
 TEST: Protodown reasons                                             [ OK ]
 TEST: Inheriting operational state with protodown                   [FAIL]
         Macvlan operational state is not DOWN despite protodown
 TEST: Protodown with lower layer down                               [FAIL]
         Macvlan is not LOWERLAYERDOWN after clearing protodown

Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 tools/testing/selftests/net/Makefile     |   1 +
 tools/testing/selftests/net/protodown.sh | 182 +++++++++++++++++++++++
 2 files changed, 183 insertions(+)
 create mode 100755 tools/testing/selftests/net/protodown.sh

diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index baa30287cf22..c6ff7b504e97 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -69,6 +69,7 @@ TEST_PROGS := \
 	nl_netdev.py \
 	nl_nlctrl.py \
 	pmtu.sh \
+	protodown.sh \
 	psock_snd.sh \
 	reuseaddr_ports_exhausted.sh \
 	reuseport_addr_any.sh \
diff --git a/tools/testing/selftests/net/protodown.sh b/tools/testing/selftests/net/protodown.sh
new file mode 100755
index 000000000000..de6ab90c521a
--- /dev/null
+++ b/tools/testing/selftests/net/protodown.sh
@@ -0,0 +1,182 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test the "protodown" mechanism. Verify basic protodown toggling, protodown
+# reasons, operational state inheritance when the lower device carrier changes,
+# and correct operational state when the lower device has no carrier.
+
+# shellcheck disable=SC1091,SC2034,SC2154,SC2317
+source lib.sh
+
+require_command jq
+
+ALL_TESTS="
+	protodown_basic_macvlan
+	protodown_basic_vxlan
+	protodown_reasons
+	protodown_inherit_operstate
+	protodown_lower_layer_down
+"
+
+operstate_get()
+{
+	local ns=$1; shift
+	local dev=$1; shift
+
+	ip -n "$ns" -j link show dev "$dev" | jq -r '.[].operstate'
+}
+
+operstate_check()
+{
+	local ns=$1; shift
+	local dev=$1; shift
+	local expected=$1; shift
+
+	local current
+	current=$(operstate_get "$ns" "$dev")
+
+	[ "$current" = "$expected" ]
+}
+
+setup_prepare()
+{
+	setup_ns NS
+	defer cleanup_all_ns
+
+	ip -n "$NS" link add name dummy0 up type dummy
+
+	ip -n "$NS" link add name macvlan0 link dummy0 up type macvlan mode bridge
+
+	ip -n "$NS" link add name vxlan0 up type vxlan id 10010 dstport 4789
+}
+
+protodown_basic()
+{
+	local dev=$1; shift
+
+	ip -n "$NS" link set dev "$dev" protodown on
+	check_err $? "Failed to set protodown on"
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" "$dev" DOWN
+	check_err $? "Operational state is not DOWN after setting protodown"
+
+	ip -n "$NS" link set dev "$dev" protodown off
+	check_err $? "Failed to set protodown off"
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" "$dev" UP
+	check_err $? "Operational state is not UP after clearing protodown"
+}
+
+protodown_basic_macvlan()
+{
+	RET=0
+
+	protodown_basic macvlan0
+
+	log_test "Basic protodown on/off with macvlan"
+}
+
+protodown_basic_vxlan()
+{
+	RET=0
+
+	protodown_basic vxlan0
+
+	log_test "Basic protodown on/off with vxlan"
+}
+
+protodown_reasons()
+{
+	RET=0
+
+	ip -n "$NS" link set dev macvlan0 protodown on
+
+	ip -n "$NS" link set dev macvlan0 protodown_reason 0 on
+	check_err $? "Failed to set protodown reason bit 0"
+
+	# Cannot clear protodown while reasons are active.
+	ip -n "$NS" link set dev macvlan0 protodown off 2>/dev/null
+	check_fail $? "Clearing protodown succeeded with active reasons"
+
+	ip -n "$NS" link set dev macvlan0 protodown_reason 0 off
+	check_err $? "Failed to clear protodown reason bit 0"
+
+	# Can clear protodown when no reasons are active.
+	ip -n "$NS" link set dev macvlan0 protodown off
+	check_err $? "Failed to clear protodown with no active reasons"
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 UP
+	check_err $? "Operational state is not UP after clearing protodown"
+
+	log_test "Protodown reasons"
+}
+
+protodown_inherit_operstate()
+{
+	RET=0
+
+	ip -n "$NS" link set dev macvlan0 protodown on
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 DOWN
+	check_err $? "Operational state is not DOWN after setting protodown"
+
+	# Toggle carrier on the lower device. The macvlan should stay DOWN
+	# because protodown is on.
+	ip -n "$NS" link set dev dummy0 carrier off
+	ip -n "$NS" link set dev dummy0 carrier on
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" dummy0 UP
+	check_err $? "Lower device is not UP after carrier on"
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 DOWN
+	check_err $? "Macvlan operational state is not DOWN despite protodown"
+
+	# Clear protodown and verify the macvlan comes back up.
+	ip -n "$NS" link set dev macvlan0 protodown off
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 UP
+	check_err $? "Operational state is not UP after clearing protodown"
+
+	log_test "Inheriting operational state with protodown"
+}
+
+protodown_lower_layer_down()
+{
+	RET=0
+
+	# Bring the lower device carrier down first.
+	ip -n "$NS" link set dev dummy0 carrier off
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 LOWERLAYERDOWN
+	check_err $? "Macvlan is not LOWERLAYERDOWN with lower carrier off"
+
+	# Toggle protodown on and off while lower has no carrier. The macvlan
+	# should not transition to UP.
+	ip -n "$NS" link set dev macvlan0 protodown on
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 LOWERLAYERDOWN
+	check_err $? "Macvlan is not LOWERLAYERDOWN after setting protodown"
+
+	ip -n "$NS" link set dev macvlan0 protodown off
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 LOWERLAYERDOWN
+	check_err $? "Macvlan is not LOWERLAYERDOWN after clearing protodown"
+
+	# Bring the lower device carrier up. The macvlan should transition to
+	# UP.
+	ip -n "$NS" link set dev dummy0 carrier on
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" dummy0 UP
+	check_err $? "Lower device is not UP after carrier on"
+
+	busywait "$BUSYWAIT_TIMEOUT" operstate_check "$NS" macvlan0 UP
+	check_err $? "Macvlan is not UP after lower device is UP"
+
+	log_test "Protodown with lower layer down"
+}
+
+trap defer_scopes_cleanup EXIT
+setup_prepare
+tests_run
+
+exit "$EXIT_STATUS"
-- 
2.54.0


^ permalink raw reply related


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