Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [GIT PULL] ARM: dts: updates for ti/omap for v7.1
From: Arnd Bergmann @ 2026-04-02 21:48 UTC (permalink / raw)
  To: Kevin Hilman, soc; +Cc: Linux-OMAP, linux-arm-kernel
In-Reply-To: <7hqzoytlms.fsf@baylibre.com>

On Wed, Apr 1, 2026, at 23:29, Kevin Hilman wrote:
>
> ----------------------------------------------------------------
> ARM: dts: updates for ti/omap for v7.1
>

Hi Kevin,

I applied this one, but I noticed two problems:

There is no long form changelog text, please add
more information about what is in the branch in
the future. I've added a short paragraph while
applying.

> +-
>  arch/arm/boot/dts/ti/omap/omap4-samsung-espresso-common.dtsi     | 744 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  arch/arm/boot/dts/ti/omap/omap4-samsung-espresso10.dts           | 101 
> +++++++++++++++++++++
>  arch/arm/boot/dts/ti/omap/omap4-samsung-espresso7.dts            |  70 
> +++++++++++++++
>  arch/arm/boot/dts/ti/omap/omap5-l4.dtsi                          |   2 

Something went wrong with the overly long lines here.

      Arnd


^ permalink raw reply

* Re: [GIT PULL 1/2] arm64: dts: ti: K3 updates for v7.1
From: Arnd Bergmann @ 2026-04-02 22:00 UTC (permalink / raw)
  To: Vignesh Raghavendra, SoC, arm
  Cc: SoC list, linux-arm-kernel, linux-kernel, Tero Kristo,
	Nishanth Menon
In-Reply-To: <e724f95d-09d0-4ede-9ed4-0ce782d81058@ti.com>

On Wed, Apr 1, 2026, at 19:14, Vignesh Raghavendra wrote:

Hi Vignesh,

I've merged this now, but I see that there are a number of
patches that look like they should have been part of an
earlier pull request for 7.0 and possibly backports:

> Generic Fixes/Cleanups:
> - ti,min-output-impedance addition to all K3 board DT files
>
> AM69 Aquila:
> - Fix DP regulator enable GPIO
>
> AM62A7-SK:
> - Fix pin name in comment from M19 to N22
>
> AM62L3 EVM:
> - Disable MMC1 internal pulls on data pins
>
> AM62P:
> - SK: Disable MMC1 internal pulls on data pins and enable Main UART

Can you have a look to see if my intuition is right on these
ones, and make sure they get merged more quickly in the future?

    Arnd


^ permalink raw reply

* Re: [PATCH] iommu: Always fill in gather when unmapping
From: Jason Gunthorpe @ 2026-04-02 22:51 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Alexandre Ghiti, AngeloGioacchino Del Regno, Albert Ou, asahi,
	Baolin Wang, iommu, Janne Grunau, Jernej Skrabec, Joerg Roedel,
	Jean-Philippe Brucker, linux-arm-kernel, linux-mediatek,
	linux-riscv, linux-sunxi, Matthias Brugger, Neal Gompa,
	Orson Zhai, Palmer Dabbelt, Paul Walmsley, Samuel Holland,
	Sven Peter, virtualization, Chen-Yu Tsai, Will Deacon, Yong Wu,
	Chunyan Zhang, Lu Baolu, Janusz Krzysztofik, Joerg Roedel,
	Jon Hunter, patches, Samiullah Khawaja, stable, Vasant Hegde
In-Reply-To: <ec51ef14-e360-43a6-ae62-44a939ec8027@arm.com>

On Thu, Apr 02, 2026 at 07:11:13PM +0100, Robin Murphy wrote:
> > > @@ -2714,6 +2714,10 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
> > >   		pr_debug("unmapped: iova 0x%lx size 0x%zx\n",
> > >   			 iova, unmapped_page);
> > > +		/* If the driver itself isn't using the gather, mark it used */
> > > +		if (iotlb_gather->end <= iotlb_gather->start)
> > > +			iommu_iotlb_gather_add_range(&iotlb_gather, iova, unmapped_page);
> > 
> > The gathers can be joined across unmaps and now we are inviting subtly
> > ill-formed gathers as only the first unmap will get included.

> > We do have error cases where the gather is legitimately empty, and
> > this would squash that, it probably needs to check unmapped_page for 0
> > too, at least.
> 
> Maybe try looking at the rest of the code around these lines...

Okay, well lets do this one, do you want to send it since it is your
idea?

Jason


^ permalink raw reply

* Re: (subset) [PATCH v2 0/9] gpio: remove uneeded Kconfig dependencies on OF_GPIO
From: Sebastian Reichel @ 2026-04-02 22:54 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Andrew Lunn, Heiner Kallweit,
	Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Linus Walleij, Lee Jones, Pavel Machek,
	Wim Van Sebroeck, Guenter Roeck, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, Sebastian Reichel, Bartosz Golaszewski
  Cc: brgl, linux-arm-kernel, linux-kernel, netdev, linux-gpio,
	linux-leds, linux-watchdog, linux-media, linux-staging, linux-pm
In-Reply-To: <20260316-gpio-of-kconfig-v2-0-de2f4b00a0e4@oss.qualcomm.com>


On Mon, 16 Mar 2026 10:45:20 +0100, Bartosz Golaszewski wrote:
> NOTE: Each patch in this series can be picked up independently into
> maintainer trees.
> 
> CONFIG_OF_GPIO is a switch that enables the compilation of the gpiolib-of
> module. The module itself handles GPIO lookup via the OF-node tree and
> is automatically enabled on all OF systems. It does not export any
> public symbols to drivers. There is no reason for them to select or
> depend on it in Kconfig.
> 
> [...]

Applied, thanks!

[8/9] power: reset: drop unneeded dependencies on OF_GPIO
      commit: 0629c33fe1873a48e1e06078409de76c5a159fdb

Best regards,
-- 
Sebastian Reichel <sebastian.reichel@collabora.com>



^ permalink raw reply

* Re: (subset) [PATCH v3 0/2] dt-bindings: power: reset: cortina: Convert to DT schema and rename node
From: Sebastian Reichel @ 2026-04-02 22:54 UTC (permalink / raw)
  To: sre, robh, krzk+dt, conor+dt, ulli.kroll, linusw,
	Khushal Chitturi
  Cc: daniel.baluta, simona.toaca, d-gole, m-chawdhry, linux-pm,
	devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260330110135.10316-1-khushalchitturi@gmail.com>


On Mon, 30 Mar 2026 16:31:33 +0530, Khushal Chitturi wrote:
> Convert the Cortina Systems Gemini Poweroff Controller bindings to
> DT schema and update corresponding dtsi file with new node name
> 

Applied, thanks!

[1/2] dt-bindings: power: reset: cortina,gemini-power-controller: convert to DT schema
      commit: 64a97c98f93e344be00d4ff10fef4119973938bd

Best regards,
-- 
Sebastian Reichel <sebastian.reichel@collabora.com>



^ permalink raw reply

* Re: [PATCH 0/9] lib/crypto: arm64: Remove obsolete chunking logic
From: Eric Biggers @ 2026-04-02 23:12 UTC (permalink / raw)
  To: linux-crypto
  Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, Herbert Xu,
	linux-arm-kernel
In-Reply-To: <20260401000548.133151-1-ebiggers@kernel.org>

On Tue, Mar 31, 2026 at 05:05:39PM -0700, Eric Biggers wrote:
> Since commit aefbab8e77eb ("arm64: fpsimd: Preserve/restore kernel mode
> NEON at context switch"), kernel-mode NEON sections have been
> preemptible on arm64.  And since commit 7dadeaa6e851 ("sched: Further
> restrict the preemption modes"), voluntary preemption is no longer
> supported on arm64 either.  Therefore, there's no longer any need to
> limit the length of kernel-mode NEON sections on arm64.
> 
> This series simplifies the code in lib/crypto/arm64/ accordingly by
> using longer kernel-mode NEON sections instead of multiple shorter ones.
> 
> This series is targeting libcrypto-next.

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next

- Eric


^ permalink raw reply

* Re: [PATCH] lib/crypto: arm64: Assume a little-endian kernel
From: Eric Biggers @ 2026-04-02 23:12 UTC (permalink / raw)
  To: linux-crypto
  Cc: linux-kernel, Ard Biesheuvel, Jason A . Donenfeld, Herbert Xu,
	linux-arm-kernel
In-Reply-To: <20260401003331.144065-1-ebiggers@kernel.org>

On Tue, Mar 31, 2026 at 05:33:31PM -0700, Eric Biggers wrote:
> Since support for big-endian arm64 kernels was removed, the CPU_LE()
> macro now unconditionally emits the code it is passed, and the CPU_BE()
> macro now unconditionally discards the code it is passed.
> 
> Simplify the assembly code in lib/crypto/arm64/ accordingly.
> 
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next

- Eric


^ permalink raw reply

* Re: [PATCH] lib/crc: arm64: Assume a little-endian kernel
From: Eric Biggers @ 2026-04-02 23:14 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-crypto, Ard Biesheuvel, linux-arm-kernel
In-Reply-To: <20260401004431.151432-1-ebiggers@kernel.org>

On Tue, Mar 31, 2026 at 05:44:31PM -0700, Eric Biggers wrote:
> Since support for big-endian arm64 kernels was removed, the CPU_LE()
> macro now unconditionally emits the code it is passed, and the CPU_BE()
> macro now unconditionally discards the code it is passed.
> 
> Simplify the assembly code in lib/crc/arm64/ accordingly.
> 
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
> 
> This patch is targeting crc-next

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=crc-next

- Eric


^ permalink raw reply

* RE: [PATCH v6 00/40] arm_mpam: Add KVM/arm64 and resctrl glue code
From: Rose, Charles @ 2026-04-02 23:38 UTC (permalink / raw)
  To: Ben Horgan
  Cc: amitsinght@marvell.com, baisheng.gao@unisoc.com,
	baolin.wang@linux.alibaba.com, carl@os.amperecomputing.com,
	dave.martin@arm.com, david@kernel.org, dfustini@baylibre.com,
	fenghuay@nvidia.com, gshan@redhat.com, james.morse@arm.com,
	jonathan.cameron@huawei.com, kobak@nvidia.com,
	lcherian@marvell.com, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, peternewman@google.com,
	punit.agrawal@oss.qualcomm.com, quic_jiles@quicinc.com,
	reinette.chatre@intel.com, rohit.mathew@arm.com,
	scott@os.amperecomputing.com, sdonthineni@nvidia.com,
	tan.shaopeng@fujitsu.com, xhao@linux.alibaba.com,
	catalin.marinas@arm.com, will@kernel.org, corbet@lwn.net,
	maz@kernel.org, oupton@kernel.org, joey.gouly@arm.com,
	suzuki.poulose@arm.com, kvmarm@lists.linux.dev,
	zengheng4@huawei.com, linux-doc@vger.kernel.org
In-Reply-To: <20260313144617.3420416-1-ben.horgan@arm.com>

Hi Ben,

> This version of the mpam missing pieces series sees a couple of things
> dropped or hidden. Memory bandwith utilization with free-running counters
> is dropped in preference of just always using 'mbm_event' mode (ABMC
> emulation) which simplifies the code and allows for, in the future,
> filtering by read/write traffic. So, for the interim, there is no memory
> bandwidth utilization support. CDP is hidden behind config expert as
> remount of resctrl fs could potentially lead to out of range PARTIDs being
> used and the fix requires a change in fs/resctrl. The setting of MPAM2_EL2
> (for pkvm/nvhe) is dropped as too expensive a write for not much value.
>
> There are a couple of 'fixes' at the start of the series which address
> problems in the base driver but are only user visible due to this series.
>

I tested cache occupancy and memory bandwidth allocation on a Dell PowerEdge XE8712 with NVIDIA Grace A02P. Both seem to work as expected.

For the series:

Tested-by: Charles Rose <charles.rose@dell.com>

Thanks,
Charles

Internal Use - Confidential


^ permalink raw reply

* Re: [PATCH 0/5] crc64: Tweak intrinsics code and enable it for ARM
From: Eric Biggers @ 2026-04-02 23:40 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: linux-crypto, linux-arm-kernel, Demian Shulhan
In-Reply-To: <dc424b4a-11b5-475f-a53a-987b5813bac5@app.fastmail.com>

On Thu, Apr 02, 2026 at 10:52:17AM +0200, Ard Biesheuvel wrote:
> 
> On Wed, 1 Apr 2026, at 21:59, Eric Biggers wrote:
> > On Mon, Mar 30, 2026 at 04:46:31PM +0200, Ard Biesheuvel wrote:
> >> Apply some tweaks to the new arm64 crc64 NEON intrinsics code, and wire
> >> it up for the 32-bit ARM build. Note that true 32-bit ARM CPUs usually
> >> don't implement the prerequisite 64x64 PMULL instructions, but 32-bit
> >> kernels are commonly used on 64-bit capable hardware too, which do
> >> implement the 32-bit versions of the crypto instructions if they are
> >> implemented for the 64-bit ISA (as per the architecture).
> >> 
> >> Cc: Demian Shulhan <demyansh@gmail.com>
> >> Cc: Eric Biggers <ebiggers@kernel.org>
> >> 
> >> Ard Biesheuvel (5):
> >>   lib/crc: arm64: Drop unnecessary chunking logic from crc64
> >>   lib/crc: arm64: Use existing macros for kernel-mode FPU cflags
> >>   ARM: Add a neon-intrinsics.h header like on arm64
> >>   lib/crc: arm64: Simplify intrinsics implementation
> >>   lib/crc: arm: Enable arm64's NEON intrinsics implementation of crc64
> >
> > I think patches 3 and 4 should be swapped, so it's cleanups first (which
> > make sense regardless of the 32-bit ARM support) and then the 32-bit ARM
> > support.
> >
> 
> Ok.

I can also apply patches 1-2 and 4 now if you want.  Let me know if I
should do that or if a new version is coming.

- Eric


^ permalink raw reply

* Re: [PATCH net v4 0/2] stmmac crash/stall fixes when under memory pressure
From: Jakub Kicinski @ 2026-04-03  0:40 UTC (permalink / raw)
  To: Sam Edwards
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
	Maxime Coquelin, Alexandre Torgue, Russell King (Oracle),
	Maxime Chevallier, Ovidiu Panait, Vladimir Oltean, Baruch Siach,
	Serge Semin, Giuseppe Cavallaro, netdev, linux-stm32,
	linux-arm-kernel, linux-kernel
In-Reply-To: <CAH5Ym4j5peYXc5c9ycJzimy26Tv+4x18hyy+j-H4v7PyWuWhtA@mail.gmail.com>

On Thu, 2 Apr 2026 09:53:43 -0700 Sam Edwards wrote:
> On Thu, Apr 2, 2026 at 8:05 AM Jakub Kicinski <kuba@kernel.org> wrote:
> > I meant we need both a threshold, and a delay :(  
> 
> Hi Jakub - got it: when the critical threshold is reached, allow the
> NAPI instance to sleep and start a timer instead.
> 
> 1) We'd either have to leave interrupts masked or let them race
> against the timer. Either one is manageable, but I feel like those
> interactions carry *just* enough regression risk to bump that patch to
> -next.
> 
> 2) Could you point out which NAPI driver best handles this situation?
> I'd like to replicate its approach.

Not sure, the last few NICs I worked on had the ability for SW 
to trigger IRQs exactly because of the Rx buffer depletion issue.
fbnic_napi_depletion_check() for example.

But let's not overthink it.. say we arm a timer and let the IRQ 
be unmasked. The timer just runs napi_schedule(). napi_schedule() 
is thread-safe, if IRQ fires with the timer armed - no problem.



^ permalink raw reply

* [PATCH v3 7/9] driver core: Replace dev->dma_coherent with DEV_FLAG_DMA_COHERENT
From: Douglas Anderson @ 2026-04-03  0:49 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Alan Stern
  Cc: Robin Murphy, Leon Romanovsky, Paul Burton, Saravana Kannan,
	Alexander Lobakin, Eric Dumazet, Toshi Kani, Christoph Hellwig,
	Alexey Kardashevskiy, Johan Hovold, Douglas Anderson, Frank.Li,
	alex, andre.przywara, andrew, aou, catalin.marinas, dmaengine,
	driver-core, gregory.clement, iommu, jgg, kees, linux-arm-kernel,
	linux-kernel, linux-mips, linux-riscv, linux-snps-arc, linux,
	m.szyprowski, palmer, peter.ujfalusi, pjw, sebastian.hesselbarth,
	tsbogend, vgupta, vkoul, will, willy
In-Reply-To: <20260403005005.30424-1-dianders@chromium.org>

In C, bitfields are not necessarily safe to modify from multiple
threads without locking. Switch "dma_coherent" over to the "flags"
field so modifications are safe.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Paul Burton <paul.burton@mips.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Not fixing any known bugs; problem is theoretical and found by code
inspection. Change is done somewhat manually and only lightly tested
(mostly compile-time tested).

NOTE: even though previously we only took up a bit if
CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE, CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU,
or CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL, in this change I reserve the
bit unconditionally.  While we could get the "dynamic" behavior by
changing the flags definition to be an "enum", it doesn't seem worth
it at this point.

Changes in v3:
- New

 arch/arc/mm/dma.c                 |  4 ++--
 arch/arm/mach-highbank/highbank.c |  2 +-
 arch/arm/mach-mvebu/coherency.c   |  2 +-
 arch/arm/mm/dma-mapping-nommu.c   |  4 ++--
 arch/arm/mm/dma-mapping.c         | 30 ++++++++++++++++--------------
 arch/arm64/mm/dma-mapping.c       |  2 +-
 arch/mips/mm/dma-noncoherent.c    |  2 +-
 arch/riscv/mm/dma-noncoherent.c   |  2 +-
 drivers/base/core.c               |  2 +-
 drivers/dma/ti/k3-udma-glue.c     |  6 +++---
 drivers/dma/ti/k3-udma.c          |  6 +++---
 include/linux/device.h            | 10 +++-------
 include/linux/dma-map-ops.h       |  2 +-
 13 files changed, 36 insertions(+), 38 deletions(-)

diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
index 6b85e94f3275..3d56878cb6a2 100644
--- a/arch/arc/mm/dma.c
+++ b/arch/arc/mm/dma.c
@@ -98,8 +98,8 @@ void arch_setup_dma_ops(struct device *dev, bool coherent)
 	 * DMA buffers.
 	 */
 	if (is_isa_arcv2() && ioc_enable && coherent)
-		dev->dma_coherent = true;
+		set_bit(DEV_FLAG_DMA_COHERENT, &dev->flags);
 
 	dev_info(dev, "use %scoherent DMA ops\n",
-		 dev->dma_coherent ? "" : "non");
+		 test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags) ? "" : "non");
 }
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 47335c7dadf8..ffa3f591f57a 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -98,7 +98,7 @@ static int highbank_platform_notifier(struct notifier_block *nb,
 	if (of_property_read_bool(dev->of_node, "dma-coherent")) {
 		val = readl(sregs_base + reg);
 		writel(val | 0xff01, sregs_base + reg);
-		dev->dma_coherent = true;
+		set_bit(DEV_FLAG_DMA_COHERENT, &dev->flags);
 	}
 
 	return NOTIFY_OK;
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index fa2c1e1aeb96..8391303a6a17 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -95,7 +95,7 @@ static int mvebu_hwcc_notifier(struct notifier_block *nb,
 
 	if (event != BUS_NOTIFY_ADD_DEVICE)
 		return NOTIFY_DONE;
-	dev->dma_coherent = true;
+	set_bit(DEV_FLAG_DMA_COHERENT, &dev->flags);
 
 	return NOTIFY_OK;
 }
diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c
index fecac107fd0d..ac0a976e30a0 100644
--- a/arch/arm/mm/dma-mapping-nommu.c
+++ b/arch/arm/mm/dma-mapping-nommu.c
@@ -42,11 +42,11 @@ void arch_setup_dma_ops(struct device *dev, bool coherent)
 		 * enough to check if MPU is in use or not since in absence of
 		 * MPU system memory map is used.
 		 */
-		dev->dma_coherent = cacheid ? coherent : true;
+		assign_bit(DEV_FLAG_DMA_COHERENT, &dev->flags, cacheid ? coherent : true);
 	} else {
 		/*
 		 * Assume coherent DMA in case MMU/MPU has not been set up.
 		 */
-		dev->dma_coherent = (get_cr() & CR_M) ? coherent : true;
+		assign_bit(DEV_FLAG_DMA_COHERENT, &dev->flags, (get_cr() & CR_M) ? coherent : true);
 	}
 }
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f304037d1c34..9c2c635d7ac0 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1076,7 +1076,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
 	pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
 	struct page **pages;
 	void *addr = NULL;
-	int coherent_flag = dev->dma_coherent ? COHERENT : NORMAL;
+	int coherent_flag = test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags) ? COHERENT : NORMAL;
 
 	*handle = DMA_MAPPING_ERROR;
 	size = PAGE_ALIGN(size);
@@ -1124,7 +1124,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 	if (vma->vm_pgoff >= nr_pages)
 		return -ENXIO;
 
-	if (!dev->dma_coherent)
+	if (!test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags))
 		vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
 
 	err = vm_map_pages(vma, pages, nr_pages);
@@ -1141,7 +1141,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 static void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 	dma_addr_t handle, unsigned long attrs)
 {
-	int coherent_flag = dev->dma_coherent ? COHERENT : NORMAL;
+	int coherent_flag = test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags) ? COHERENT : NORMAL;
 	struct page **pages;
 	size = PAGE_ALIGN(size);
 
@@ -1202,7 +1202,8 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
 		phys_addr_t phys = page_to_phys(sg_page(s));
 		unsigned int len = PAGE_ALIGN(s->offset + s->length);
 
-		if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		if (!test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags) &&
+		    !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 			arch_sync_dma_for_device(sg_phys(s), s->length, dir);
 
 		prot = __dma_info_to_prot(dir, attrs);
@@ -1304,7 +1305,8 @@ static void arm_iommu_unmap_sg(struct device *dev,
 		if (sg_dma_len(s))
 			__iommu_remove_mapping(dev, sg_dma_address(s),
 					       sg_dma_len(s));
-		if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		if (!test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags) &&
+		    !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 			arch_sync_dma_for_cpu(sg_phys(s), s->length, dir);
 	}
 }
@@ -1323,7 +1325,7 @@ static void arm_iommu_sync_sg_for_cpu(struct device *dev,
 	struct scatterlist *s;
 	int i;
 
-	if (dev->dma_coherent)
+	if (test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags))
 		return;
 
 	for_each_sg(sg, s, nents, i)
@@ -1345,7 +1347,7 @@ static void arm_iommu_sync_sg_for_device(struct device *dev,
 	struct scatterlist *s;
 	int i;
 
-	if (dev->dma_coherent)
+	if (test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags))
 		return;
 
 	for_each_sg(sg, s, nents, i)
@@ -1371,7 +1373,7 @@ static dma_addr_t arm_iommu_map_phys(struct device *dev, phys_addr_t phys,
 	dma_addr_t dma_addr;
 	int ret, prot;
 
-	if (!dev->dma_coherent &&
+	if (!test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags) &&
 	    !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO)))
 		arch_sync_dma_for_device(phys, size, dir);
 
@@ -1412,7 +1414,7 @@ static void arm_iommu_unmap_phys(struct device *dev, dma_addr_t handle,
 	if (!iova)
 		return;
 
-	if (!dev->dma_coherent &&
+	if (!test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags) &&
 	    !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO))) {
 		phys_addr_t phys = iommu_iova_to_phys(mapping->domain, iova);
 
@@ -1431,7 +1433,7 @@ static void arm_iommu_sync_single_for_cpu(struct device *dev,
 	unsigned int offset = handle & ~PAGE_MASK;
 	phys_addr_t phys;
 
-	if (dev->dma_coherent || !iova)
+	if (test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags) || !iova)
 		return;
 
 	phys = iommu_iova_to_phys(mapping->domain, iova);
@@ -1446,7 +1448,7 @@ static void arm_iommu_sync_single_for_device(struct device *dev,
 	unsigned int offset = handle & ~PAGE_MASK;
 	phys_addr_t phys;
 
-	if (dev->dma_coherent || !iova)
+	if (test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags) || !iova)
 		return;
 
 	phys = iommu_iova_to_phys(mapping->domain, iova);
@@ -1701,13 +1703,13 @@ static void arm_teardown_iommu_dma_ops(struct device *dev) { }
 void arch_setup_dma_ops(struct device *dev, bool coherent)
 {
 	/*
-	 * Due to legacy code that sets the ->dma_coherent flag from a bus
-	 * notifier we can't just assign coherent to the ->dma_coherent flag
+	 * Due to legacy code that sets DEV_FLAG_DMA_COHERENT from a bus
+	 * notifier we can't just assign coherent to DEV_FLAG_DMA_COHERENT
 	 * here, but instead have to make sure we only set but never clear it
 	 * for now.
 	 */
 	if (coherent)
-		dev->dma_coherent = true;
+		set_bit(DEV_FLAG_DMA_COHERENT, &dev->flags);
 
 	/*
 	 * Don't override the dma_ops if they have already been set. Ideally
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index b2b5792b2caa..256c7631aff5 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -48,7 +48,7 @@ void arch_setup_dma_ops(struct device *dev, bool coherent)
 		   dev_driver_string(dev), dev_name(dev),
 		   ARCH_DMA_MINALIGN, cls);
 
-	dev->dma_coherent = coherent;
+	assign_bit(DEV_FLAG_DMA_COHERENT, &dev->flags, coherent);
 
 	xen_setup_dma_ops(dev);
 }
diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c
index ab4f2a75a7d0..496bf5f4999c 100644
--- a/arch/mips/mm/dma-noncoherent.c
+++ b/arch/mips/mm/dma-noncoherent.c
@@ -139,6 +139,6 @@ void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
 #ifdef CONFIG_ARCH_HAS_SETUP_DMA_OPS
 void arch_setup_dma_ops(struct device *dev, bool coherent)
 {
-	dev->dma_coherent = coherent;
+	assign_bit(DEV_FLAG_DMA_COHERENT, &dev->flags, coherent);
 }
 #endif
diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
index cb89d7e0ba88..3b793a1cc607 100644
--- a/arch/riscv/mm/dma-noncoherent.c
+++ b/arch/riscv/mm/dma-noncoherent.c
@@ -140,7 +140,7 @@ void arch_setup_dma_ops(struct device *dev, bool coherent)
 		   "%s %s: device non-coherent but no non-coherent operations supported",
 		   dev_driver_string(dev), dev_name(dev));
 
-	dev->dma_coherent = coherent;
+	assign_bit(DEV_FLAG_DMA_COHERENT, &dev->flags, coherent);
 }
 
 void riscv_noncoherent_supported(void)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8dbb7a9c7aab..00005777c21f 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -3174,7 +3174,7 @@ void device_initialize(struct device *dev)
 #if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
     defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
     defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
-	dev->dma_coherent = dma_default_coherent;
+	assign_bit(DEV_FLAG_DMA_COHERENT, &dev->flags, dma_default_coherent);
 #endif
 	swiotlb_dev_init(dev);
 }
diff --git a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c
index f87d244cc2d6..cda8f4a8f440 100644
--- a/drivers/dma/ti/k3-udma-glue.c
+++ b/drivers/dma/ti/k3-udma-glue.c
@@ -312,7 +312,7 @@ k3_udma_glue_request_tx_chn_common(struct device *dev,
 
 	if (xudma_is_pktdma(tx_chn->common.udmax)) {
 		/* prepare the channel device as coherent */
-		tx_chn->common.chan_dev.dma_coherent = true;
+		set_bit(DEV_FLAG_DMA_COHERENT, &tx_chn->common.chan_dev.flags);
 		dma_coerce_mask_and_coherent(&tx_chn->common.chan_dev,
 					     DMA_BIT_MASK(48));
 	}
@@ -1003,7 +1003,7 @@ k3_udma_glue_request_rx_chn_priv(struct device *dev, const char *name,
 
 	if (xudma_is_pktdma(rx_chn->common.udmax)) {
 		/* prepare the channel device as coherent */
-		rx_chn->common.chan_dev.dma_coherent = true;
+		set_bit(DEV_FLAG_DMA_COHERENT, &rx_chn->common.chan_dev.flags);
 		dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,
 					     DMA_BIT_MASK(48));
 	}
@@ -1104,7 +1104,7 @@ k3_udma_glue_request_remote_rx_chn_common(struct k3_udma_glue_rx_channel *rx_chn
 
 	if (xudma_is_pktdma(rx_chn->common.udmax)) {
 		/* prepare the channel device as coherent */
-		rx_chn->common.chan_dev.dma_coherent = true;
+		set_bit(DEV_FLAG_DMA_COHERENT, &rx_chn->common.chan_dev.flags);
 		dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,
 					     DMA_BIT_MASK(48));
 		rx_chn->single_fdq = false;
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index c964ebfcf3b6..770aae467fc5 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -428,18 +428,18 @@ static void k3_configure_chan_coherency(struct dma_chan *chan, u32 asel)
 		/* No special handling for the channel */
 		chan->dev->chan_dma_dev = false;
 
-		chan_dev->dma_coherent = false;
+		clear_bit(DEV_FLAG_DMA_COHERENT, &chan_dev->flags);
 		chan_dev->dma_parms = NULL;
 	} else if (asel == 14 || asel == 15) {
 		chan->dev->chan_dma_dev = true;
 
-		chan_dev->dma_coherent = true;
+		set_bit(DEV_FLAG_DMA_COHERENT, &chan_dev->flags);
 		dma_coerce_mask_and_coherent(chan_dev, DMA_BIT_MASK(48));
 		chan_dev->dma_parms = chan_dev->parent->dma_parms;
 	} else {
 		dev_warn(chan->device->dev, "Invalid ASEL value: %u\n", asel);
 
-		chan_dev->dma_coherent = false;
+		clear_bit(DEV_FLAG_DMA_COHERENT, &chan_dev->flags);
 		chan_dev->dma_parms = NULL;
 	}
 }
diff --git a/include/linux/device.h b/include/linux/device.h
index 6c961dac9fdb..c2a6dba7a036 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -480,6 +480,8 @@ struct device_physical_location {
  * @DEV_FLAG_STATE_SYNCED: The hardware state of this device has been synced to
  *		match the software state of this device by calling the
  *		driver/bus sync_state() callback.
+ * @DEV_FLAG_DMA_COHERENT: This particular device is dma coherent, even if the
+ *		architecture supports non-coherent devices.
  */
 enum struct_device_flags {
 	DEV_FLAG_READY_TO_PROBE,
@@ -488,6 +490,7 @@ enum struct_device_flags {
 	DEV_FLAG_DMA_SKIP_SYNC,
 	DEV_FLAG_DMA_OPS_BYPASS,
 	DEV_FLAG_STATE_SYNCED,
+	DEV_FLAG_DMA_COHERENT,
 };
 
 /**
@@ -569,8 +572,6 @@ enum struct_device_flags {
  * @offline:	Set after successful invocation of bus type's .offline().
  * @of_node_reused: Set if the device-tree node is shared with an ancestor
  *              device.
- * @dma_coherent: this particular device is dma coherent, even if the
- *		architecture supports non-coherent devices.
  * @flags:	DEV_FLAG_XXX flags. Use atomic bitfield operations to modify.
  *
  * At the lowest level, every device in a Linux system is represented by an
@@ -678,11 +679,6 @@ struct device {
 	bool			offline_disabled:1;
 	bool			offline:1;
 	bool			of_node_reused:1;
-#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
-    defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
-    defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
-	bool			dma_coherent:1;
-#endif
 
 	unsigned long		flags;
 };
diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h
index 4d9d1fe3277c..91d34678657c 100644
--- a/include/linux/dma-map-ops.h
+++ b/include/linux/dma-map-ops.h
@@ -230,7 +230,7 @@ int dma_direct_set_offset(struct device *dev, phys_addr_t cpu_start,
 extern bool dma_default_coherent;
 static inline bool dev_is_dma_coherent(struct device *dev)
 {
-	return dev->dma_coherent;
+	return test_bit(DEV_FLAG_DMA_COHERENT, &dev->flags);
 }
 #else
 #define dma_default_coherent true
-- 
2.53.0.1213.gd9a14994de-goog



^ permalink raw reply related

* [PATCH v3 8/9] driver core: Replace dev->of_node_reused with DEV_FLAG_OF_NODE_REUSED
From: Douglas Anderson @ 2026-04-03  0:49 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Alan Stern
  Cc: Robin Murphy, Leon Romanovsky, Paul Burton, Saravana Kannan,
	Alexander Lobakin, Eric Dumazet, Toshi Kani, Christoph Hellwig,
	Alexey Kardashevskiy, Johan Hovold, Douglas Anderson,
	alexander.stein, andrew, andrew, andriy.shevchenko, astewart,
	bhelgaas, brgl, broonie, davem, devicetree, driver-core,
	hkallweit1, jirislaby, joel, kees, kuba, lgirdwood,
	linux-arm-kernel, linux-aspeed, linux-kernel, linux-pci,
	linux-serial, linux-usb, linux, mani, netdev, pabeni, robh
In-Reply-To: <20260403005005.30424-1-dianders@chromium.org>

In C, bitfields are not necessarily safe to modify from multiple
threads without locking. Switch "of_node_reused" over to the "flags"
field so modifications are safe.

Cc: Johan Hovold <johan@kernel.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Not fixing any known bugs; problem is theoretical and found by code
inspection. Change is done somewhat manually and only lightly tested
(mostly compile-time tested).

Changes in v3:
- New

 drivers/base/core.c                      | 2 +-
 drivers/base/pinctrl.c                   | 2 +-
 drivers/base/platform.c                  | 2 +-
 drivers/net/pcs/pcs-xpcs-plat.c          | 2 +-
 drivers/of/device.c                      | 6 +++---
 drivers/pci/of.c                         | 2 +-
 drivers/pci/pwrctrl/core.c               | 2 +-
 drivers/regulator/bq257xx-regulator.c    | 2 +-
 drivers/regulator/rk808-regulator.c      | 2 +-
 drivers/tty/serial/serial_base_bus.c     | 2 +-
 drivers/usb/gadget/udc/aspeed-vhub/dev.c | 2 +-
 include/linux/device.h                   | 6 +++---
 12 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 00005777c21f..a87bd40499b6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -5282,7 +5282,7 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
 {
 	of_node_put(dev->of_node);
 	dev->of_node = of_node_get(dev2->of_node);
-	dev->of_node_reused = true;
+	set_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags);
 }
 EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
 
diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c
index 6e250272c843..62c228c75d50 100644
--- a/drivers/base/pinctrl.c
+++ b/drivers/base/pinctrl.c
@@ -24,7 +24,7 @@ int pinctrl_bind_pins(struct device *dev)
 {
 	int ret;
 
-	if (dev->of_node_reused)
+	if (test_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags))
 		return 0;
 
 	dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index d44591d52e36..5128ff7e5e78 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -856,7 +856,7 @@ struct platform_device *platform_device_register_full(
 	pdev->dev.parent = pdevinfo->parent;
 	pdev->dev.fwnode = pdevinfo->fwnode;
 	pdev->dev.of_node = of_node_get(to_of_node(pdev->dev.fwnode));
-	pdev->dev.of_node_reused = pdevinfo->of_node_reused;
+	assign_bit(DEV_FLAG_OF_NODE_REUSED, &pdev->dev.flags, pdevinfo->of_node_reused);
 
 	if (pdevinfo->dma_mask) {
 		pdev->platform_dma_mask = pdevinfo->dma_mask;
diff --git a/drivers/net/pcs/pcs-xpcs-plat.c b/drivers/net/pcs/pcs-xpcs-plat.c
index b8c48f9effbf..c2722d8bd98a 100644
--- a/drivers/net/pcs/pcs-xpcs-plat.c
+++ b/drivers/net/pcs/pcs-xpcs-plat.c
@@ -349,7 +349,7 @@ static int xpcs_plat_init_dev(struct dw_xpcs_plat *pxpcs)
 	 * up later. Make sure DD-core is aware of the OF-node being re-used.
 	 */
 	device_set_node(&mdiodev->dev, fwnode_handle_get(dev_fwnode(dev)));
-	mdiodev->dev.of_node_reused = true;
+	set_bit(DEV_FLAG_OF_NODE_REUSED, &mdiodev->dev.flags);
 
 	/* Pass the data further so the DW XPCS driver core could use it */
 	mdiodev->dev.platform_data = (void *)device_get_match_data(dev);
diff --git a/drivers/of/device.c b/drivers/of/device.c
index f7e75e527667..fd77295a8c0f 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -26,7 +26,7 @@
 const struct of_device_id *of_match_device(const struct of_device_id *matches,
 					   const struct device *dev)
 {
-	if (!matches || !dev->of_node || dev->of_node_reused)
+	if (!matches || !dev->of_node || test_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags))
 		return NULL;
 	return of_match_node(matches, dev->of_node);
 }
@@ -192,7 +192,7 @@ ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
 {
 	ssize_t sl;
 
-	if (!dev || !dev->of_node || dev->of_node_reused)
+	if (!dev || !dev->of_node || test_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags))
 		return -ENODEV;
 
 	sl = of_modalias(dev->of_node, str, len - 2);
@@ -254,7 +254,7 @@ int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *
 {
 	int sl;
 
-	if ((!dev) || (!dev->of_node) || dev->of_node_reused)
+	if ((!dev) || (!dev->of_node) || test_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags))
 		return -ENODEV;
 
 	/* Devicetree modalias is tricky, we add it in 2 steps */
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 9f8eb5df279e..197b60c5a660 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -38,7 +38,7 @@ int pci_set_of_node(struct pci_dev *dev)
 	struct device *pdev __free(put_device) =
 		bus_find_device_by_of_node(&platform_bus_type, node);
 	if (pdev)
-		dev->bus->dev.of_node_reused = true;
+		set_bit(DEV_FLAG_OF_NODE_REUSED, &dev->bus->dev.flags);
 
 	device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node)));
 	return 0;
diff --git a/drivers/pci/pwrctrl/core.c b/drivers/pci/pwrctrl/core.c
index 7754baed67f2..cfbe9b615b88 100644
--- a/drivers/pci/pwrctrl/core.c
+++ b/drivers/pci/pwrctrl/core.c
@@ -39,7 +39,7 @@ static int pci_pwrctrl_notify(struct notifier_block *nb, unsigned long action,
 		 * If we got here then the PCI device is the second after the
 		 * power control platform device. Mark its OF node as reused.
 		 */
-		dev->of_node_reused = true;
+		set_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags);
 		break;
 	}
 
diff --git a/drivers/regulator/bq257xx-regulator.c b/drivers/regulator/bq257xx-regulator.c
index dab8f1ab4450..01d3139e1d87 100644
--- a/drivers/regulator/bq257xx-regulator.c
+++ b/drivers/regulator/bq257xx-regulator.c
@@ -143,7 +143,7 @@ static int bq257xx_regulator_probe(struct platform_device *pdev)
 	struct regulator_config cfg = {};
 
 	pdev->dev.of_node = pdev->dev.parent->of_node;
-	pdev->dev.of_node_reused = true;
+	set_bit(DEV_FLAG_OF_NODE_REUSED, &pdev->dev.flags);
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(struct bq257xx_reg_data), GFP_KERNEL);
 	if (!pdata)
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index e66408f23bb6..375ea7861134 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -2115,7 +2115,7 @@ static int rk808_regulator_probe(struct platform_device *pdev)
 	int ret, i, nregulators;
 
 	pdev->dev.of_node = pdev->dev.parent->of_node;
-	pdev->dev.of_node_reused = true;
+	set_bit(DEV_FLAG_OF_NODE_REUSED, &pdev->dev.flags);
 
 	regmap = dev_get_regmap(pdev->dev.parent, NULL);
 	if (!regmap)
diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c
index a12935f6b992..86c6003bbebb 100644
--- a/drivers/tty/serial/serial_base_bus.c
+++ b/drivers/tty/serial/serial_base_bus.c
@@ -74,7 +74,7 @@ static int serial_base_device_init(struct uart_port *port,
 	dev->parent = parent_dev;
 	dev->bus = &serial_base_bus_type;
 	dev->release = release;
-	dev->of_node_reused = true;
+	set_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags);
 
 	device_set_node(dev, fwnode_handle_get(dev_fwnode(parent_dev)));
 
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
index 2ecd049dacc2..57048e3aa6bb 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
@@ -593,7 +593,7 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx)
 		d->gadget.max_speed = USB_SPEED_HIGH;
 	d->gadget.speed = USB_SPEED_UNKNOWN;
 	d->gadget.dev.of_node = vhub->pdev->dev.of_node;
-	d->gadget.dev.of_node_reused = true;
+	set_bit(DEV_FLAG_OF_NODE_REUSED, &d->gadget.dev.flags);
 
 	rc = usb_add_gadget_udc(d->port_dev, &d->gadget);
 	if (rc != 0)
diff --git a/include/linux/device.h b/include/linux/device.h
index c2a6dba7a036..f6ca067bacca 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -482,6 +482,8 @@ struct device_physical_location {
  *		driver/bus sync_state() callback.
  * @DEV_FLAG_DMA_COHERENT: This particular device is dma coherent, even if the
  *		architecture supports non-coherent devices.
+ * @DEV_FLAG_OF_NODE_REUSED: Set if the device-tree node is shared with an
+ *		ancestor device.
  */
 enum struct_device_flags {
 	DEV_FLAG_READY_TO_PROBE,
@@ -491,6 +493,7 @@ enum struct_device_flags {
 	DEV_FLAG_DMA_OPS_BYPASS,
 	DEV_FLAG_STATE_SYNCED,
 	DEV_FLAG_DMA_COHERENT,
+	DEV_FLAG_OF_NODE_REUSED,
 };
 
 /**
@@ -570,8 +573,6 @@ enum struct_device_flags {
  *
  * @offline_disabled: If set, the device is permanently online.
  * @offline:	Set after successful invocation of bus type's .offline().
- * @of_node_reused: Set if the device-tree node is shared with an ancestor
- *              device.
  * @flags:	DEV_FLAG_XXX flags. Use atomic bitfield operations to modify.
  *
  * At the lowest level, every device in a Linux system is represented by an
@@ -678,7 +679,6 @@ struct device {
 
 	bool			offline_disabled:1;
 	bool			offline:1;
-	bool			of_node_reused:1;
 
 	unsigned long		flags;
 };
-- 
2.53.0.1213.gd9a14994de-goog



^ permalink raw reply related

* [PATCH v3 9/9] driver core: Replace dev->offline + ->offline_disabled with DEV_FLAGs
From: Douglas Anderson @ 2026-04-03  0:49 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Alan Stern
  Cc: Robin Murphy, Leon Romanovsky, Paul Burton, Saravana Kannan,
	Alexander Lobakin, Eric Dumazet, Toshi Kani, Christoph Hellwig,
	Alexey Kardashevskiy, Johan Hovold, Douglas Anderson, ardb,
	broonie, catalin.marinas, chleroy, david, driver-core, kees,
	kevin.brodsky, lenb, linux-acpi, linux-arm-kernel, linux-cxl,
	linux-kernel, linux-mm, linuxppc-dev, maddy, maz, miko.lenczewski,
	mpe, npiggin, osalvador, oupton, peterz, tglx, will, yangyicong,
	yeoreum.yun
In-Reply-To: <20260403005005.30424-1-dianders@chromium.org>

In C, bitfields are not necessarily safe to modify from multiple
threads without locking. Switch "offline" and "offline_disabled" over
to the "flags" field so modifications are safe.

Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Toshi Kani <toshi.kani@hp.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Not fixing any known bugs; problem is theoretical and found by code
inspection. Change is done somewhat manually and only lightly tested
(mostly compile-time tested).

Changes in v3:
- New

 arch/arm64/kernel/cpufeature.c                |  2 +-
 .../platforms/pseries/hotplug-memory.c        |  4 ++--
 drivers/acpi/scan.c                           |  3 ++-
 drivers/base/core.c                           | 19 ++++++++++---------
 drivers/base/cpu.c                            |  4 ++--
 drivers/base/memory.c                         |  2 +-
 include/linux/device.h                        |  9 ++++-----
 kernel/cpu.c                                  |  4 ++--
 8 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 32c2dbcc0c64..f6f7c35b7a93 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -4042,7 +4042,7 @@ static int enable_mismatched_32bit_el0(unsigned int cpu)
 	 */
 	lucky_winner = cpu_32bit ? cpu : cpumask_any_and(cpu_32bit_el0_mask,
 							 cpu_active_mask);
-	get_cpu_device(lucky_winner)->offline_disabled = true;
+	set_bit(DEV_FLAG_OFFLINE_DISABLED, &get_cpu_device(lucky_winner)->flags);
 	setup_elf_hwcaps(compat_elf_hwcaps);
 	elf_hwcap_fixup();
 	pr_info("Asymmetric 32-bit EL0 support detected on CPU %u; CPU hot-unplug disabled on CPU %u\n",
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index b2f14db59034..d9a0a75ada46 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -213,9 +213,9 @@ static int dlpar_change_lmb_state(struct drmem_lmb *lmb, bool online)
 		return -EINVAL;
 	}
 
-	if (online && mem_block->dev.offline)
+	if (online && test_bit(DEV_FLAG_OFFLINE, &mem_block->dev.flags))
 		rc = device_online(&mem_block->dev);
-	else if (!online && !mem_block->dev.offline)
+	else if (!online && !test_bit(DEV_FLAG_OFFLINE, &mem_block->dev.flags))
 		rc = device_offline(&mem_block->dev);
 	else
 		rc = 0;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e8cdbdb46fdb..f2707b704468 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -122,7 +122,8 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)
 	mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING);
 
 	list_for_each_entry(pn, &adev->physical_node_list, node)
-		if (device_supports_offline(pn->dev) && !pn->dev->offline) {
+		if (device_supports_offline(pn->dev) &&
+		    !test_bit(DEV_FLAG_OFFLINE, &pn->dev->flags)) {
 			if (uevent)
 				kobject_uevent_env(&pn->dev->kobj, KOBJ_CHANGE, envp);
 
diff --git a/drivers/base/core.c b/drivers/base/core.c
index a87bd40499b6..63d724ece384 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2789,7 +2789,7 @@ static ssize_t online_show(struct device *dev, struct device_attribute *attr,
 	bool val;
 
 	device_lock(dev);
-	val = !dev->offline;
+	val = !test_bit(DEV_FLAG_OFFLINE, &dev->flags);
 	device_unlock(dev);
 	return sysfs_emit(buf, "%u\n", val);
 }
@@ -2914,7 +2914,7 @@ static int device_add_attrs(struct device *dev)
 	if (error)
 		goto err_remove_type_groups;
 
-	if (device_supports_offline(dev) && !dev->offline_disabled) {
+	if (device_supports_offline(dev) && !test_bit(DEV_FLAG_OFFLINE_DISABLED, &dev->flags)) {
 		error = device_create_file(dev, &dev_attr_online);
 		if (error)
 			goto err_remove_dev_groups;
@@ -4179,7 +4179,8 @@ static int device_check_offline(struct device *dev, void *not_used)
 	if (ret)
 		return ret;
 
-	return device_supports_offline(dev) && !dev->offline ? -EBUSY : 0;
+	return device_supports_offline(dev) &&
+	       !test_bit(DEV_FLAG_OFFLINE, &dev->flags) ? -EBUSY : 0;
 }
 
 /**
@@ -4197,7 +4198,7 @@ int device_offline(struct device *dev)
 {
 	int ret;
 
-	if (dev->offline_disabled)
+	if (test_bit(DEV_FLAG_OFFLINE_DISABLED, &dev->flags))
 		return -EPERM;
 
 	ret = device_for_each_child(dev, NULL, device_check_offline);
@@ -4206,13 +4207,13 @@ int device_offline(struct device *dev)
 
 	device_lock(dev);
 	if (device_supports_offline(dev)) {
-		if (dev->offline) {
+		if (test_bit(DEV_FLAG_OFFLINE, &dev->flags)) {
 			ret = 1;
 		} else {
 			ret = dev->bus->offline(dev);
 			if (!ret) {
 				kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
-				dev->offline = true;
+				set_bit(DEV_FLAG_OFFLINE, &dev->flags);
 			}
 		}
 	}
@@ -4237,11 +4238,11 @@ int device_online(struct device *dev)
 
 	device_lock(dev);
 	if (device_supports_offline(dev)) {
-		if (dev->offline) {
+		if (test_bit(DEV_FLAG_OFFLINE, &dev->flags)) {
 			ret = dev->bus->online(dev);
 			if (!ret) {
 				kobject_uevent(&dev->kobj, KOBJ_ONLINE);
-				dev->offline = false;
+				clear_bit(DEV_FLAG_OFFLINE, &dev->flags);
 			}
 		} else {
 			ret = 1;
@@ -4715,7 +4716,7 @@ static int device_attrs_change_owner(struct device *dev, kuid_t kuid,
 	if (error)
 		return error;
 
-	if (device_supports_offline(dev) && !dev->offline_disabled) {
+	if (device_supports_offline(dev) && !test_bit(DEV_FLAG_OFFLINE_DISABLED, &dev->flags)) {
 		/* Change online device attributes of @dev to @kuid/@kgid. */
 		error = sysfs_file_change_owner(kobj, dev_attr_online.attr.name,
 						kuid, kgid);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 875abdc9942e..e4e6a399def4 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -422,8 +422,8 @@ int register_cpu(struct cpu *cpu, int num)
 	cpu->dev.id = num;
 	cpu->dev.bus = &cpu_subsys;
 	cpu->dev.release = cpu_device_release;
-	cpu->dev.offline_disabled = !cpu->hotpluggable;
-	cpu->dev.offline = !cpu_online(num);
+	assign_bit(DEV_FLAG_OFFLINE_DISABLED, &cpu->dev.flags, !cpu->hotpluggable);
+	assign_bit(DEV_FLAG_OFFLINE, &cpu->dev.flags, !cpu_online(num));
 	cpu->dev.of_node = of_get_cpu_node(num, NULL);
 	cpu->dev.groups = common_cpu_attr_groups;
 	if (cpu->hotpluggable)
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index a3091924918b..7f42727dde81 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -697,7 +697,7 @@ static int __add_memory_block(struct memory_block *memory)
 	memory->dev.id = memory->start_section_nr / sections_per_block;
 	memory->dev.release = memory_block_release;
 	memory->dev.groups = memory_memblk_attr_groups;
-	memory->dev.offline = memory->state == MEM_OFFLINE;
+	assign_bit(DEV_FLAG_OFFLINE, &memory->dev.flags, memory->state == MEM_OFFLINE);
 
 	ret = device_register(&memory->dev);
 	if (ret) {
diff --git a/include/linux/device.h b/include/linux/device.h
index f6ca067bacca..fd53aa04cad9 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -484,6 +484,8 @@ struct device_physical_location {
  *		architecture supports non-coherent devices.
  * @DEV_FLAG_OF_NODE_REUSED: Set if the device-tree node is shared with an
  *		ancestor device.
+ * @DEV_FLAG_OFFLINE_DISABLED: If set, the device is permanently online.
+ * @DEV_FLAG_OFFLINE: Set after successful invocation of bus type's .offline().
  */
 enum struct_device_flags {
 	DEV_FLAG_READY_TO_PROBE,
@@ -494,6 +496,8 @@ enum struct_device_flags {
 	DEV_FLAG_STATE_SYNCED,
 	DEV_FLAG_DMA_COHERENT,
 	DEV_FLAG_OF_NODE_REUSED,
+	DEV_FLAG_OFFLINE_DISABLED,
+	DEV_FLAG_OFFLINE,
 };
 
 /**
@@ -571,8 +575,6 @@ enum struct_device_flags {
  *              should be set by the subsystem / bus driver that discovered
  *              the device.
  *
- * @offline_disabled: If set, the device is permanently online.
- * @offline:	Set after successful invocation of bus type's .offline().
  * @flags:	DEV_FLAG_XXX flags. Use atomic bitfield operations to modify.
  *
  * At the lowest level, every device in a Linux system is represented by an
@@ -677,9 +679,6 @@ struct device {
 
 	enum device_removable	removable;
 
-	bool			offline_disabled:1;
-	bool			offline:1;
-
 	unsigned long		flags;
 };
 
diff --git a/kernel/cpu.c b/kernel/cpu.c
index bc4f7a9ba64e..15a873ad8025 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -2639,7 +2639,7 @@ static void cpuhp_offline_cpu_device(unsigned int cpu)
 {
 	struct device *dev = get_cpu_device(cpu);
 
-	dev->offline = true;
+	set_bit(DEV_FLAG_OFFLINE, &dev->flags);
 	/* Tell user space about the state change */
 	kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
 }
@@ -2648,7 +2648,7 @@ static void cpuhp_online_cpu_device(unsigned int cpu)
 {
 	struct device *dev = get_cpu_device(cpu);
 
-	dev->offline = false;
+	clear_bit(DEV_FLAG_OFFLINE, &dev->flags);
 	/* Tell user space about the state change */
 	kobject_uevent(&dev->kobj, KOBJ_ONLINE);
 }
-- 
2.53.0.1213.gd9a14994de-goog



^ permalink raw reply related

* Re: [PATCH v5 2/3] arm64: dts: rockchip: refactor items from Orange Pi 5/b to prep for Pro
From: Andrew Lunn @ 2026-04-03  0:53 UTC (permalink / raw)
  To: Dennis Gilmore
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	FUKAUMI Naoki, Hsun Lai, Jonas Karlman, Chaoyi Chen, John Clark,
	Michael Opdenacker, Quentin Schulz, Chukun Pan, Alexey Charkov,
	Peter Robinson, Michael Riesch, Mykola Kvach, Jimmy Hon,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <CAABkxwvnv7i=xg53qu4JDapBs6ATaMGh9iXZfi+od=CCxRxQUA@mail.gmail.com>

On Wed, Apr 01, 2026 at 08:27:30AM -0500, Dennis Gilmore wrote:
> Hi Andrew,
> 
> On Wed, Apr 1, 2026 at 6:52 AM Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > > +&gmac1 {
> > > +     clock_in_out = "output";
> > > +     phy-handle = <&rgmii_phy1>;
> > > +     phy-mode = "rgmii-rxid";
> > > +     pinctrl-0 = <&gmac1_miim
> > > +                  &gmac1_tx_bus2
> > > +                  &gmac1_rx_bus2
> > > +                  &gmac1_rgmii_clk
> > > +                  &gmac1_rgmii_bus>;
> > > +     pinctrl-names = "default";
> > > +     tx_delay = <0x42>;
> >
> > phy-mode = "rgmii-rxid" means the PCB provides the 2ns delay for
> > TX. This is unlikely to be correct. Please try "rgmii-id" and delete
> > the tx_delay.
> 
> As I mentioned to you in v2 I do not have the affected hardware to
> test any changes. This patch is just moving the existing definition
> from the common dtsi to the two devices that  have gmac1 wired up. I
> am not comfortable making changes here that I can not verify if they
> work or not.

Yes, sorry.

Please add this to the commit message, so i don't make the same point
again.

	Andrew


^ permalink raw reply

* Re: [PATCH v4] crypto: testmgr - Add test vectors for authenc(hmac(md5),cbc(aes))
From: Herbert Xu @ 2026-04-03  1:03 UTC (permalink / raw)
  To: Aleksander Jan Bajkowski
  Cc: davem, mcoquelin.stm32, alexandre.torgue, linux-crypto,
	linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <20260303184916.69132-1-olek2@wp.pl>

On Tue, Mar 03, 2026 at 07:48:44PM +0100, Aleksander Jan Bajkowski wrote:
> Test vectors were generated starting from existing CBC(AES) test vectors
> (RFC3602, NIST SP800-38A) and adding HMAC(MD5) computed with Python
> script. Then, the results were double-checked on Mediatek MT7981 (safexcel)
> and NXP P2020 (talitos). Both platforms pass self-tests.
> 
> Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
> ---
> v4:
> - rename aes-generic -> aes-lib
> v3:
> - correct sha384 -> md5 in description
> v2:
> - rebase and resolve conflicts
> ---
>  crypto/testmgr.c |   7 ++
>  crypto/testmgr.h | 255 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 262 insertions(+)

Patch applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


^ permalink raw reply

* Re: [PATCH] crypto: aspeed/hash: Use memcpy_from_sglist() in aspeed_ahash_dma_prepare()
From: Herbert Xu @ 2026-04-03  1:08 UTC (permalink / raw)
  To: Paul Louvel
  Cc: Neal Liu, David S. Miller, Joel Stanley, Andrew Jeffery,
	Thomas Petazzoni, linux-aspeed, linux-crypto, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260327092418.10476-1-paul.louvel@bootlin.com>

On Fri, Mar 27, 2026 at 10:24:18AM +0100, Paul Louvel wrote:
> Replace scatterwalk_map_and_copy() with memcpy_from_sglist() in
> aspeed_ahash_dma_prepare(). The latter provides a simpler interface
> without requiring a direction parameter, making the code easier to
> read and less error-prone.
> 
> No functional change intended.
> 
> Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
> ---
>  drivers/crypto/aspeed/aspeed-hace-hash.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)

Patch applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


^ permalink raw reply

* Re: [PATCH net-next v2 10/11] net: airoha: Do not stop GDM port if it is shared
From: Jakub Kicinski @ 2026-04-03  1:12 UTC (permalink / raw)
  To: lorenzo
  Cc: Jakub Kicinski, andrew+netdev, davem, edumazet, pabeni, robh,
	krzk+dt, conor+dt, ansuelsmth, benjamin.larsson, linux-arm-kernel,
	linux-mediatek, netdev, devicetree
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-10-ac427ae4beeb@kernel.org>

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: airoha: Do not stop GDM port if it is shared

This patch introduces a port->users reference counter to prevent setting
the GDM port forward configuration to FE_PSE_PORT_DROP if another net_device
is still using the shared GDM port.

> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 0780fb8aacfb..3f9bce8c5370 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
[ ... ]
> @@ -1681,9 +1682,6 @@ static int airoha_dev_stop(struct net_device *netdev)
>  	for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++)
>  		netdev_tx_reset_subqueue(netdev, i);
>  
> -	airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id),
> -				    FE_PSE_PORT_DROP);
> -
>  	if (atomic_dec_and_test(&qdma->users)) {
>  		airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
>  				  GLOBAL_CFG_TX_DMA_EN_MASK |

While this patch aims to support shared GDM ports, does the remaining
unconditional call to airoha_set_vip_for_gdm_port(dev, false) at the start
of airoha_dev_stop() break other active devices sharing the port?

static int airoha_dev_stop(struct net_device *netdev)
{
        ...
        err = airoha_set_vip_for_gdm_port(dev, false);
        ...
}

This appears to clear the REG_FE_VIP_PORT_EN and REG_FE_IFC_PORT_EN hardware
bits for the physical port, which might instantly kill traffic for any other
active interface using the shared port.

Similarly, in airoha_dev_open() and airoha_dev_change_mtu(), the
REG_GDM_LEN_CFG (MTU) is overwritten unconditionally. If a device with a
smaller MTU is brought up, will it overwrite the shared port's MTU limit
and cause the hardware to silently drop larger packets for the other device?

[ ... ]
> @@ -1697,6 +1695,11 @@ static int airoha_dev_stop(struct net_device *netdev)
>  		}
>  	}
>  
> +	if (atomic_dec_and_test(&port->users))
> +		airoha_set_gdm_port_fwd_cfg(qdma->eth,
> +					    REG_GDM_FWD_CFG(port->id),
> +					    FE_PSE_PORT_DROP);
> +
>  	return 0;
>  }

Does moving this FE_PSE_PORT_DROP configuration to the end of airoha_dev_stop()
cause a race condition when stopping the device?

In airoha_dev_open(), the driver correctly enables the QDMA engine before
configuring the GDM port to forward packets. A safe teardown typically
mirrors this by first stopping the packet source (setting FE_PSE_PORT_DROP)
and then disabling the destination DMA engine.

By moving airoha_set_gdm_port_fwd_cfg() after the airoha_qdma_clear() block,
when both qdma->users and port->users reach zero, the QDMA engine and its
queues are shut down while the GDM port is still actively forwarding packets.

Could incoming packets be forwarded to a disabled DMA engine during this
window, risking hardware lockups or buffer leaks?


^ permalink raw reply

* Re: [PATCH net-next v2 09/11] net: airoha: Support multiple net_devices for a single FE GDM port
From: Jakub Kicinski @ 2026-04-03  1:12 UTC (permalink / raw)
  To: lorenzo
  Cc: Jakub Kicinski, andrew+netdev, davem, edumazet, pabeni, robh,
	krzk+dt, conor+dt, ansuelsmth, benjamin.larsson, linux-arm-kernel,
	linux-mediatek, netdev, devicetree
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-9-ac427ae4beeb@kernel.org>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
Subject: net: airoha: Support multiple net_devices for a single FE GDM port

This commit introduces support for multiple net_devices connected to the
same Frame Engine (FE) GDM port via an external hardware arbiter. It
adds logic to parse device tree child nodes and instantiate separate
net_devices for TDM traffic from external SerDes.

> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 5e489e8593ba..0780fb8aacfb 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
[ ... ]
> @@ -614,9 +616,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
>  		u32 hash, reason, msg1 = le32_to_cpu(desc->msg1);
>  		struct page *page = virt_to_head_page(e->buf);
>  		u32 desc_ctrl = le32_to_cpu(desc->ctrl);
> -		struct airoha_gdm_port *port;
> -		struct net_device *netdev;
> -		int data_len, len, p;
> +		struct airoha_gdm_dev *dev;
> +		int data_len, len;
>  
>  		if (!(desc_ctrl & QDMA_DESC_DONE_MASK))
>  			break;
> @@ -633,12 +634,10 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
>  		if (!len || data_len < len)
>  			goto free_frag;
>  
> -		p = airoha_qdma_get_gdm_port(eth, desc);
> -		if (p < 0 || !eth->ports[p])
> +		dev = airoha_qdma_get_gdm_dev(eth, desc);
> +		if (IS_ERR(dev))
>  			goto free_frag;

If a scattered frame is being processed (q->skb is not NULL) and IS_ERR(dev)
triggers the goto free_frag, the error handler frees the skb:

free_frag:
	if (q->skb) {
		dev_kfree_skb(q->skb);
		q->skb = NULL;
	} else {
		page_pool_put_full_page(q->page_pool, page, true);
	}

Since the current fragment's page is not yet attached to q->skb, does this
skip the else branch and permanently leak the page pool buffer?

[ ... ]
> @@ -1747,9 +1748,7 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev)
>  	airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));
>  	airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX));
>  
> -	/* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */
> -	nbq = port->id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0;
> -	src_port = eth->soc->ops.get_src_port_id(port, nbq);
> +	src_port = eth->soc->ops.get_src_port_id(port, dev->nbq);
>  	if (src_port < 0)
>  		return src_port;

With multiple net_devices instantiated for the same physical GDM port, does
the initialization of sibling devices overwrite shared hardware registers?

For example, when airoha_set_gdm2_loopback() uses src_port to configure
REG_FE_WAN_PORT, it explicitly clears the WAN port routing masks:

	airoha_fe_rmw(eth, REG_FE_WAN_PORT,
		      WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
		      FIELD_PREP(WAN0_MASK, src_port));

Will the last initialized device clobber the WAN routing configurations and
hardware MAC filters for the others, causing their traffic to be dropped?

[ ... ]
> @@ -1970,7 +1969,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
>  	}
>  
>  	fport = airoha_get_fe_port(dev);
> -	msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
> +	msg1 = FIELD_PREP(QDMA_ETH_TXMSG_NBOQ_MASK, dev->nbq) |
> +	       FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
>  	       FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
>  
>  	q = &qdma->q_tx[qid];

When multiple net_devices share a single QDMA instance and its TX rings
(qdma->q_tx), a TX queue stall might occur here.

If the shared hardware ring fills up, netif_tx_stop_queue() stops the
transmitting device's queue. Later, when descriptors are freed, the driver
only wakes the queue corresponding to the specific packet that just completed.

If multiple devices' TX queues are stopped, will the other devices' queues
remain stalled unless their specific packets happen to be processed?

[ ... ]
> @@ -2897,10 +2900,11 @@ bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
>  
>  static int airoha_alloc_gdm_device(struct airoha_eth *eth,
>  				   struct airoha_gdm_port *port,
> -				   struct device_node *np)
> +				   int nbq, struct device_node *np)
>  {
> -	struct airoha_gdm_dev *dev;
>  	struct net_device *netdev;
> +	struct airoha_gdm_dev *dev;
> +	u8 index;
>  	int err;
[ ... ]
> +	/* Allowed nbq for EN7581 on GDM3 port are 4 and 5 for PCIE0
> +	 * and PCIE1 respectively.
> +	 */
> +	index = nbq;
> +	if (airoha_is_7581(eth) && port->id == AIROHA_GDM3_IDX)
> +		index -= 4;
> +
> +	if (index >= ARRAY_SIZE(port->devs) || port->devs[index]) {
> +		dev_err(eth->dev, "invalid nbq id: %d\n", nbq);
> +		return -EINVAL;
> +	}

There are two potential issues regarding the new index logic:

First, does this break probing for older device trees without child nodes?
When falling back to airoha_alloc_gdm_device(..., 0, np) with nbq = 0,
the index -= 4 operation for AIROHA_GDM3_IDX will cause the u8 index to
underflow to 252. The bounds check 252 >= 2 fails, returning -EINVAL.

Second, can an invalid device tree value bypass the bounds check?
The int nbq parameter is directly assigned to the u8 index. If a large value
like reg = <256> is provided, it truncates to 0, passing the index >= 2
check. The un-truncated int nbq is then stored in dev->nbq, potentially
causing out-of-bounds shifts when used in hardware macros.

[ ... ]
> @@ -2986,7 +3004,36 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
>  	if (err)
>  		return err;
>  
> -	return airoha_alloc_gdm_device(eth, port, np);
> +	for_each_child_of_node(np, node) {
> +		/* Multiple external serdes connected to the FE GDM port via an
> +		 * external arbiter.
> +		 */
> +		const __be32 *nbq_ptr;
> +
> +		if (!of_device_is_compatible(node, "airoha,eth-port"))
> +			continue;
> +
> +		d++;
> +		if (!of_device_is_available(node))
> +			continue;
> +
> +		nbq_ptr = of_get_property(node, "reg", NULL);
> +		if (!nbq_ptr) {
> +			dev_err(eth->dev, "missing nbq id\n");
> +			err = -EINVAL;
> +			of_node_put(node);
> +			break;
> +		}
> +
> +		err = airoha_alloc_gdm_device(eth, port, be32_to_cpup(nbq_ptr),
> +					      node);
> +		if (err) {
> +			of_node_put(node);
> +			return err;
> +		}
> +	}
> +
> +	return !d ? airoha_alloc_gdm_device(eth, port, 0, np) : 0;
>  }

If nbq_ptr is missing, err = -EINVAL is set and the loop breaks. However,
since the child counter d was already incremented, the final statement
evaluates to 0 (success) because !d is false.

Does this swallow the -EINVAL error and cause a silent failure where the
driver continues probing without initializing the misconfigured GDM devices?

Additionally, the for_each_child_of_node() iterator automatically handles
taking and dropping the reference to node.

When node is passed to airoha_alloc_gdm_device(), it is directly assigned:
netdev->dev.of_node = np;

Since of_node_get() is not called, when the loop iteration finishes and drops
the reference, does this leave the net_device pointing to a freed device
tree node?
-- 
pw-bot: cr


^ permalink raw reply

* Re: [PATCH v4 net-next 03/14] net: enetc: add pre-boot initialization for i.MX94 switch
From: Jakub Kicinski @ 2026-04-03  1:17 UTC (permalink / raw)
  To: wei.fang
  Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
	andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
	f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
	linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-4-wei.fang@nxp.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: enetc: add pre-boot initialization for i.MX94 switch

This commit adds pre-boot initialization logic for the i.MX94 switch
in the NETC block control driver. It configures external ports, MII
protocols, and MDIO PHY addresses, and handles the MAC selection
constraint between switch port 2 and ENETC 0.

> diff --git a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
> index 92a0f824dae7..c21230f7a7fb 100644
> --- a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
> +++ b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
[ ... ]
> +static int imx94_switch_link_config(struct netc_blk_ctrl *priv,
> +				    struct device_node *np,
> +				    bool *swp2_en)
> +{
> +	struct device_node *ports;
> +	int port_id, err = 0;

Since of_property_read_u32() expects a u32 pointer, does passing a
signed int pointer here trigger an incompatible pointer types warning
during compilation?

> +
> +	ports = netc_get_switch_ports(np);
> +	if (!ports)
> +		return -ENODEV;
> +
> +	for_each_available_child_of_node_scoped(ports, child) {
> +		if (of_property_read_u32(child, "reg", &port_id) < 0) {

If the device tree provides a reg value with the MSB set, port_id
would be evaluated as a negative number.

[ ... ]
>  static int imx94_netcmix_init(struct platform_device *pdev)
>  {
>  	struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
>  	struct device_node *np = pdev->dev.of_node;
> +	bool enetc0_en = false, swp2_en = false;
>  	u32 val;
>  	int err;
>  
>  	for_each_child_of_node_scoped(np, child) {
>  		for_each_child_of_node_scoped(child, gchild) {
> -			if (!of_device_is_compatible(gchild, "pci1131,e101"))
> -				continue;
> -
> -			err = imx94_enetc_link_config(priv, gchild);
> -			if (err)
> -				return err;
> +			if (of_device_is_compatible(gchild, "pci1131,e101")) {
> +				err = imx94_enetc_link_config(priv, gchild,
> +							      &enetc0_en);
> +				if (err)
> +					return err;
> +			} else if (of_device_is_compatible(gchild,
> +							   "pci1131,eef2")) {

Is it possible for the switch node to be disabled in the device tree?

If so, should we check of_device_is_available() for gchild before proceeding,
similar to how it is checked for enetc0_en?

Without checking availability, if the disabled switch lacks a ports subnode,
imx94_switch_link_config() might return -ENODEV and abort the entire probe.

Alternatively, if the disabled switch node has a ports subnode with an
available port 2, it could spuriously set swp2_en = true and cause a false
conflict with ENETC 0.

> +				err = imx94_switch_link_config(priv, gchild,
> +							       &swp2_en);
> +				if (err)
> +					return err;
> +			}
>  		}
>  	}
[ ... ]
> @@ -610,6 +682,77 @@ static int imx94_enetc_mdio_phyaddr_config(struct netc_blk_ctrl *priv,
>  	return 0;
>  }
>  
> +static int imx94_ierb_enetc_init(struct netc_blk_ctrl *priv,
[ ... ]
> +static int imx94_switch_mdio_phyaddr_config(struct netc_blk_ctrl *priv,
> +					    struct device_node *np,
> +					    int port_id, u32 phy_mask)
> +{
> +	int addr;
> +
> +	/* The switch has 3 external ports at most */
> +	if (port_id > 2)
> +		return 0;

If port_id is negative due to the signed type, it will bypass this upper
bound check.

> +
> +	addr = netc_get_phy_addr(np);
> +	if (addr < 0) {
> +		if (addr == -ENODEV)
> +			return 0;
> +
> +		return addr;
> +	}
> +
> +	if (phy_mask & BIT(addr)) {
> +		dev_err(&priv->pdev->dev,
> +			"Found same PHY address in EMDIO and switch node\n");
> +		return -EINVAL;
> +	}
> +
> +	netc_reg_write(priv->ierb, IERB_LBCR(port_id),
> +		       LBCR_MDIO_PHYAD_PRTAD(addr));

Could this lead to an out-of-bounds register write prior to the array base
since port_id is negative?

> +
> +	return 0;
> +}
> +
> +static int imx94_ierb_switch_init(struct netc_blk_ctrl *priv,
> +				  struct device_node *np,
> +				  u32 phy_mask)
> +{
> +	struct device_node *ports;
> +	int port_id, err = 0;

A similar signed int declaration is used here for port_id, which would run
into the same pointer type warning and negative value issues.

> +
> +	ports = netc_get_switch_ports(np);
> +	if (!ports)
> +		return -ENODEV;
[ ... ]
-- 
pw-bot: cr


^ permalink raw reply

* Re: [PATCH v4 net-next 04/14] net: enetc: add basic operations to the FDB table
From: Jakub Kicinski @ 2026-04-03  1:17 UTC (permalink / raw)
  To: wei.fang
  Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
	andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
	f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
	linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-5-wei.fang@nxp.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: enetc: add basic operations to the FDB table

This commit adds FDB table management operations (Add, Delete, Update,
Query/Search) to the enetc driver using NTMP version 2.0. FDB entries
are managed via the command BD ring.

> diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
> index 916dc4fe7de3..a9f3e6cbf422 100644
> --- a/include/linux/fsl/ntmp.h
> +++ b/include/linux/fsl/ntmp.h

[ ... ]

> @@ -116,6 +158,31 @@ static inline int ntmp_rsst_query_entry(struct ntmp_user *user,
>  	return 0;
>  }
>  
> +static inline int ntmp_fdbt_add_entry(struct ntmp_user *user, u32 *entry_id,
> +				      const struct fdbt_keye_data *keye,
> +				      const struct fdbt_cfge_data *data)
> +{
> +	return 0;
> +}

If CONFIG_NXP_NETC_LIB is disabled, will returning 0 here cause callers to
falsely assume the operation succeeded and proceed to use an uninitialized
entry_id pointer? Would it be safer to return an error code such as
-EOPNOTSUPP for stubs that have output parameters?

[ ... ]

> +static inline int ntmp_fdbt_search_port_entry(struct ntmp_user *user, int port,
> +					      u32 *resume_entry_id,
> +					      struct fdbt_entry_data *entry)
> +{
> +	return 0;
> +}

Similar to the above, does returning 0 here leave both resume_entry_id and
entry uninitialized while signaling success? Since resume_entry_id is
typically used as an iterator, could this lead to an infinite loop or other
unpredictable behavior in the caller if they interpret the 0 return as a
successful read of valid hardware configuration data?


^ permalink raw reply

* Re: [PATCH v4 net-next 05/14] net: enetc: add support for the "Add" operation to VLAN filter table
From: Jakub Kicinski @ 2026-04-03  1:17 UTC (permalink / raw)
  To: wei.fang
  Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
	andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
	f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
	linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-6-wei.fang@nxp.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: enetc: add support for the "Add" operation to VLAN filter table

This patch adds the ntmp_vft_add_entry() helper function to support adding
entries to the VLAN filter table. It allocates a DMA buffer, formats the
request, and transmits it via the command BD ring using netc_xmit_ntmp_cmd().

> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
> --- a/drivers/net/ethernet/freescale/enetc/ntmp.c
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c

[ ... ]

> @@ -652,5 +655,52 @@ int ntmp_fdbt_search_port_entry(struct ntmp_user *user, int port,
> +int ntmp_vft_add_entry(struct ntmp_user *user, u16 vid,
> +		       const struct vft_cfge_data *cfge)
> +{
> +	struct ntmp_dma_buf data = {
> +		.dev = user->dev,
> +		.size = sizeof(struct vft_req_ua),
> +	};
> +	struct vft_req_ua *req;
> +	union netc_cbd cbd;
> +	u32 len;
> +	int err;
> +
> +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> +	if (err)
> +		return err;
> +
> +	/* Request data */
> +	ntmp_fill_crd(&req->crd, user->tbl.vft_ver, 0,
> +		      NTMP_GEN_UA_CFGEU);
> +	req->ak.exact.vid = cpu_to_le16(vid);
> +	req->cfge = *cfge;
> +
> +	/* Request header */
> +	len = NTMP_LEN(data.size, NTMP_STATUS_RESP_LEN);
> +	ntmp_fill_request_hdr(&cbd, data.dma, len, NTMP_VFT_ID,
> +			      NTMP_CMD_ADD, NTMP_AM_EXACT_KEY);
> +
> +	err = netc_xmit_ntmp_cmd(user, &cbd);
> +	if (err)
> +		dev_err(user->dev,
> +			"Failed to add %s entry, vid: %u, err: %pe\n",
> +			ntmp_table_name(NTMP_VFT_ID), vid, ERR_PTR(err));
> +
> +	ntmp_free_data_mem(&data);

Does this code safely handle hardware timeouts?

If netc_xmit_ntmp_cmd() times out and returns an error, the pending
transaction is not explicitly aborted before ntmp_free_data_mem()
unconditionally frees the DMA buffer.

Could the hardware eventually process the pending command and perform a
DMA write of the response to the physical address of the freed buffer?

This might lead to silent memory corruption if that memory has already
been reallocated to another subsystem. Would it be safer to explicitly
abort the pending DMA transaction, reset the device on timeout, or
intentionally delay freeing the buffer until it is proven safe?

> +
> +	return err;
> +}


^ permalink raw reply

* Re: [PATCH v4 net-next 06/14] net: enetc: add support for the "Update" operation to buffer pool table
From: Jakub Kicinski @ 2026-04-03  1:17 UTC (permalink / raw)
  To: wei.fang
  Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
	andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
	f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
	linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-7-wei.fang@nxp.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
Subject: net: enetc: add support for the "Update" operation to buffer pool table

This patch adds the ntmp_bpt_update_entry() helper function to support
updating a specified entry in the buffer pool table. It provides the
ability to update buffer pool configuration data.

> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> --- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h

[ ... ]

> +/* Buffer Pool Table Request Data Buffer Format of Update action */
> +struct bpt_req_update {
> +	struct ntmp_req_by_eid rbe;
> +	struct bpt_cfge_data cfge;
> +};
> +

[ ... ]

> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
> --- a/drivers/net/ethernet/freescale/enetc/ntmp.c
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c

[ ... ]

> @@ -702,5 +708,38 @@ int ntmp_vft_add_entry(struct ntmp_user *user, u16 vid,
>  }
>  EXPORT_SYMBOL_GPL(ntmp_vft_add_entry);
>  
> +int ntmp_bpt_update_entry(struct ntmp_user *user, u32 entry_id,
> +			  const struct bpt_cfge_data *cfge)
> +{
> +	struct ntmp_dma_buf data = {
> +		.dev = user->dev,
> +		.size = sizeof(struct bpt_req_update),
> +	};
> +	struct bpt_req_update *req;
> +	union netc_cbd cbd;
> +	int err;
> +
> +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> +	if (err)
> +		return err;
> +
> +	ntmp_fill_crd_eid(&req->rbe, user->tbl.bpt_ver, 0,
> +			  NTMP_GEN_UA_CFGEU | BPT_UA_BPSEU, entry_id);

Does this update action mask match the size of the request buffer?

The mask includes both NTMP_GEN_UA_CFGEU and BPT_UA_BPSEU, which instructs
the hardware to update both the configuration entry and the status entry.
However, struct bpt_req_update only contains the configuration data,
omitting the status data.

If the hardware attempts to read the missing BPSE data, could it reject
the command due to an undersized request length, or read beyond the
intended payload into zero-initialized DMA padding? This might overwrite
critical buffer pool tracking variables like amount_used_hwm.

If only the configuration is being updated, should the BPT_UA_BPSEU flag
be removed?

> +	req->cfge = *cfge;
> +	ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(data.size, 0),
> +			      NTMP_BPT_ID, NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
> +
> +	err = netc_xmit_ntmp_cmd(user, &cbd);
> +	if (err)
> +		dev_err(user->dev,
> +			"Failed to update %s entry 0x%x, err: %pe\n",
> +			ntmp_table_name(NTMP_BPT_ID), entry_id, ERR_PTR(err));
> +
> +	ntmp_free_data_mem(&data);

Can this result in a DMA use-after-free if the hardware command times out?

If netc_xmit_ntmp_cmd() times out waiting for the hardware to process the
command, it returns -ETIMEDOUT without resetting the hardware ring or
explicitly cancelling the command.

The descriptor remains active in the ring, and ntmp_free_data_mem()
unconditionally frees the DMA-mapped buffer. If the hardware eventually
processes the descriptor, it will read from the now-freed DMA memory.

Could this lead to an IOMMU fault or cause the hardware to read garbage
data if the page has been reallocated?

> +
> +	return err;
> +}


^ permalink raw reply

* Re: [PATCH v4 net-next 07/14] net: enetc: add support for "Add" and "Delete" operations to IPFT
From: Jakub Kicinski @ 2026-04-03  1:17 UTC (permalink / raw)
  To: wei.fang
  Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
	andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
	f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
	linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-8-wei.fang@nxp.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: enetc: add support for "Add" and "Delete" operations to IPFT

This commit adds support for the "Add" and "Delete" operations to the
ingress port filter table (IPFT). These interfaces will be used by both
the ENETC driver and the NETC switch driver.

> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
> index 3c59b355c142..960d5be8ec42 100644
> --- a/drivers/net/ethernet/freescale/enetc/ntmp.c
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c

[ ... ]

> @@ -468,6 +471,79 @@ int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)
>  }
>  EXPORT_SYMBOL_GPL(ntmp_rsst_query_entry);
>  
> +/**
> + * ntmp_ipft_add_entry - add an entry into the ingress port filter table
> + * @user: target ntmp_user struct
> + * @entry: the entry data, entry->cfge (configuration element data) and
> + * entry->keye (key element data) are used as input. Since the entry ID
> + * is assigned by the hardware, so entry->entry_id is a returned value
> + * for the driver to use, the driver can update/delete/query the entry
> + * based on the entry_id.
> + *
> + * Return: 0 on success, otherwise a negative error code
> + */
> +int ntmp_ipft_add_entry(struct ntmp_user *user,
> +			struct ipft_entry_data *entry)
> +{
[ ... ]
> +	err = ntmp_alloc_data_mem(&data, (void **)&req);
> +	if (err)
> +		return err;
> +
> +	ntmp_fill_crd(&req->crd, user->tbl.ipft_ver, NTMP_QA_ENTRY_ID,
> +		      NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU);
> +	req->ak.keye = entry->keye;
> +	req->cfge = entry->cfge;

The request sets NTMP_GEN_UA_STSEU to indicate statistics data is present,
but struct ipft_req_ua does not appear to contain a match_count or STSE data
field before cfge.

Since the hardware expects STSE data before CFGE data (as seen in
struct ipft_resp_query), will this cause the hardware to misinterpret the
first 8 bytes of cfge as the match_count, and then read the actual filter
configuration from out-of-bounds or uninitialized memory?

> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> index 7d50af7745c7..6d519d59a433 100644
> --- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h

[ ... ]

> +/* Ingress Port Filter Table Request Data Buffer Format of Update and
> + * Add actions
> + */
> +struct ipft_req_ua {
> +	struct ntmp_cmn_req_data crd;
> +	union ipft_access_key ak;
> +	struct ipft_cfge_data cfge;
> +};

Does this struct need an STSE data field before cfge to match the request
header flags?

> diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
> index a54945dcdc61..efda35e5e22c 100644
> --- a/include/linux/fsl/ntmp.h
> +++ b/include/linux/fsl/ntmp.h

[ ... ]

> @@ -66,6 +68,94 @@ struct maft_entry_data {
>  	struct maft_cfge_data cfge;
>  };
>  
> +struct ipft_pld_byte {
> +	u8 data;
> +	u8 mask;
> +};
> +
> +struct ipft_keye_data {
> +	__le16 precedence;
> +	__le16 resv0[3];
> +	__le16 frm_attr_flags;
> +#define IPFT_FAF_OVLAN		BIT(2)
> +#define IPFT_FAF_IVLAN		BIT(3)
> +#define IPFT_FAF_IP_HDR		BIT(7)
> +#define IPFT_FAF_IP_VER6	BIT(8)
> +#define IPFT_FAF_L4_CODE	GENMASK(11, 10)
> +#define  IPFT_FAF_TCP_HDR	1
> +#define  IPFT_FAF_UDP_HDR	2
> +#define  IPFT_FAF_SCTP_HDR	3
> +#define IPFT_FAF_WOL_MAGIC	BIT(12)
> +	__le16 frm_attr_flags_mask;
> +	__le16 dscp;
> +#define IPFT_DSCP		GENMASK(5, 0)
> +#define IPFT_DSCP_MASK		GENMASK(11, 0)

Does IPFT_DSCP_MASK completely overlap with IPFT_DSCP?

If it is defined as GENMASK(11, 0) instead of GENMASK(11, 6), using
FIELD_PREP with this mask will not shift the value into the upper bits,
which might overwrite the actual DSCP value in bits 0-5.


^ permalink raw reply

* Re: [PATCH v4 net-next 09/14] net: dsa: add NETC switch tag support
From: Jakub Kicinski @ 2026-04-03  1:17 UTC (permalink / raw)
  To: wei.fang
  Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
	andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
	f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
	linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-10-wei.fang@nxp.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: dsa: add NETC switch tag support

Adds support for the proprietary NXP NETC switch tag used in NXP NETC
switches version 4.3 or later. The tag has 3 types (Forward, To_Port,
To_Host) and supports a varying length between 6 and 14 bytes.

> diff --git a/net/dsa/tag_netc.c b/net/dsa/tag_netc.c
> new file mode 100644
> index 000000000000..addd41f7f1b6
> --- /dev/null
> +++ b/net/dsa/tag_netc.c
[ ... ]
> +static void *netc_fill_common_tp_tag(struct sk_buff *skb,
> +				     struct net_device *ndev,
> +				     u8 subtype, int tag_len)
> +{
> +	struct dsa_port *dp = dsa_user_to_port(ndev);
> +	u16 queue = skb_get_queue_mapping(skb);
> +	u8 ipv = netdev_txq_to_tc(ndev, queue);

What happens here if the interface doesn't have traffic classes configured?

By default, netdev_txq_to_tc() returns -1. Because ipv is an unsigned 8-bit
integer, this casts to 255.

When this is later passed to FIELD_PREP(NETC_TAG_IPV, ipv) in
netc_fill_common_tag(), the macro blindly masks the variable, silently
forcing the IPV field to 7 (the maximum priority) for all default,
unconfigured traffic. Valid TC values greater than 7 would also be silently
truncated.

Does this code bypass the intended QoS mechanisms?

> +	void *tag;
> +
> +	skb_push(skb, tag_len);
> +	dsa_alloc_etype_header(skb, tag_len);
> +
> +	tag = dsa_etype_header_pos_tx(skb);
> +	memset(tag + NETC_TAG_CMN_LEN, 0, tag_len - NETC_TAG_CMN_LEN);
> +	netc_fill_common_tag(tag, NETC_TAG_TO_PORT, subtype,
> +			     dp->ds->index, dp->index, ipv);

Will this break communication for standard single-switch setups?

The driver passes dp->ds->index as the hardware switch ID here, which
defaults to 0 for the first switch in a DSA tree. However, on the receive
path, frames stamped with switch ID 0 are rejected.

If the physical switch hardware uses an ID greater than 0, frames will fail
the lookup in dsa_conduit_find_user() on receive because the software index
is 0.

> +
> +	return tag;
> +}
[ ... ]
> +static struct sk_buff *netc_rcv(struct sk_buff *skb,
> +				struct net_device *ndev)
> +{
> +	struct netc_tag_cmn *tag_cmn;
> +	int tag_len, sw_id, port;
[ ... ]
> +	if (tag_cmn->qos & NETC_TAG_QV)
> +		skb->priority = FIELD_GET(NETC_TAG_IPV, tag_cmn->qos);
> +
> +	sw_id = NETC_TAG_SWITCH & tag_cmn->switch_port;

This isn't a bug, but is there a reason to use a raw bitwise AND for sw_id
instead of using FIELD_GET(NETC_TAG_SWITCH, ...) to match how the port
field is extracted just below this?

> +	/* ENETC VEPA switch ID (0) is not supported yet */
> +	if (!sw_id) {
> +		dev_warn_ratelimited(&ndev->dev,
> +				     "VEPA switch ID is not supported yet\n");
> +
> +		return NULL;
> +	}
> +
> +	port = FIELD_GET(NETC_TAG_PORT, tag_cmn->switch_port);
> +	skb->dev = dsa_conduit_find_user(ndev, sw_id, port);
[ ... ]


^ 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