LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] powerpc: Move CONFIG_QE_GPIO to SoC
From: Christophe Leroy (CS GROUP) @ 2026-07-07 15:00 UTC (permalink / raw)
  To: Qiang Zhao, Madhavan Srinivasan, Christophe Leroy (CS GROUP)
  Cc: linux-kernel, linuxppc-dev, linux-arm-kernel, Paul Louvel
In-Reply-To: <b08f76c1d8ff864774246f1e2c2158c223c001be.1783435914.git.chleroy@kernel.org>

Commit 7aa1aa6ecec2 ("QE: Move QE from arch/powerpc to drivers/soc")
moved QE into drivers/soc including gpio.c but left CONFIG_QE_GPIO
in powerpc's Kconfig.

Move it to SoC as well as it is the only place it is used:

  drivers/soc/fsl/qe/Makefile:obj-$(CONFIG_QE_GPIO)       += gpio.o qe_ports_ic.o
  include/soc/fsl/qe/qe.h:#ifdef CONFIG_QE_GPIO
  include/soc/fsl/qe/qe.h:#endif /* CONFIG_QE_GPIO */

Link: https://lore.kernel.org/r/16a187116511f5c844c43a12d09f263e77f4fd60.1780936729.git.chleroy@kernel.org
Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
---
 arch/powerpc/platforms/Kconfig | 8 --------
 drivers/soc/fsl/qe/Kconfig     | 8 ++++++++
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index c4e61843d9d99..2f797ac6f1b3f 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -228,14 +228,6 @@ config TAU_AVERAGE
 
 	  If in doubt, say N here.
 
-config QE_GPIO
-	bool "QE GPIO support"
-	depends on QUICC_ENGINE
-	select GPIOLIB
-	help
-	  Say Y here if you're going to use hardware that connects to the
-	  QE GPIOs.
-
 config CPM2
 	bool "Enable support for the CPM2 (Communications Processor Module)"
 	depends on (FSL_SOC_BOOKE && PPC32) || PPC_82xx
diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig
index eb03f42ab9781..b35a8fd30ebfb 100644
--- a/drivers/soc/fsl/qe/Kconfig
+++ b/drivers/soc/fsl/qe/Kconfig
@@ -67,3 +67,11 @@ config QE_USB
 	default y if USB_FSL_QE
 	help
 	  QE USB Controller support
+
+config QE_GPIO
+	bool "QE GPIO support"
+	depends on QUICC_ENGINE
+	select GPIOLIB
+	help
+	  Say Y here if you're going to use hardware that connects to the
+	  QE GPIOs.
-- 
2.54.0



^ permalink raw reply related

* [PATCH v8] mm: pgtable: free kernel page tables via RCU to fix ptdump UAF
From: David Carlier @ 2026-07-06 20:31 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Dev Jain, David Hildenbrand, Lorenzo Stoakes, Liam R . Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Dave Hansen, Lu Baolu, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy, Ritesh Harjani,
	syzbot+fd95a72470f5a44e464c, linux-mm, linux-kernel, linux-riscv,
	linuxppc-dev, David Carlier

ptdump_walk_pgd() walks the kernel page tables under get_online_mems().
That does not stop vmalloc from freeing a kernel PTE page underneath the
walk.

When vmap_try_huge_pmd() promotes a range to a huge PMD it collapses the
existing PTE table and frees it via pmd_free_pte_page(). On x86, riscv and
powerpc this runs without the init_mm mmap lock; only arm64 takes it, and
not on the block-split path. So ptdump can dereference a just-freed PTE
page, which is the use after free syzbot hit in ptdump_pte_entry().

The race is not new. ptdump walks the whole kernel address space, including
ranges other code is actively mapping, so it reads page tables it does not
own. Commit 5ba2f0a15564 ("mm: introduce deferred freeing for kernel page
tables") only widened the window; the Fixes tag points there for that
reason.

Every other walker works on a range it owns and is the only one mutating
it: set_memory() on arm64/riscv/loongarch, the arm64 block-split path, the
openrisc DMA path and the hugetlb_vmemmap remap. Nothing frees those ranges
concurrently, so they cannot race and do not need RCU. ptdump is the only
walker that traverses ranges it does not own.

Defer the free by an RCU grace period. pagetable_free_kernel() now frees
via call_rcu() in both the async and non-async configs. The async path
still flushes the TLB first, then queues the per-page RCU free. The page
stays valid until any walk that may have observed it drops its RCU read
lock.

x86, arm64 and riscv reach pagetable_free_kernel() for the collapsed PTE
page (the ptdesc carries PT_kernel), so the deferral covers them. powerpc
uses its own fragment allocator: pte_free_kernel() there frees the page
synchronously via pte_fragment_free() and the ptdesc is not flagged kernel,
so defer the kernel case in pte_fragment_free() as well. arm64 also takes
init_mm.mmap_lock around the free under a static key; that is now redundant
with the RCU deferral but left in place.

On the read side walk_page_range_debug() walks the init_mm range in bounded
chunks, taking rcu_read_lock() around each chunk and calling cond_resched()
between them. It uses the lockless walker as the mmap lock is no longer
held, and pgd_addr_end() to bound each chunk without overflowing at the top
of the address space. A walker either sees the cleared PMD and skips, or
keeps the page alive until it drops the lock. The owned-range walkers are
unchanged.

Stop taking mmap_write_lock() in ptdump_walk_pgd() for init_mm. It never
guarded against this free -- most architectures free the collapsed PTE
table without it -- and RCU now provides the synchronisation. efi_mm and
current->mm page tables are not RCU-freed, so they keep the mmap write
lock.

ptdump callbacks run under RCU within a chunk, so they must not sleep. The
arch note_page() and effective_prot() callbacks only format into the
preallocated seq_file buffer; the only GFP_KERNEL marker setup runs before
the walk, and cond_resched() happens between chunks, outside the read lock.

Fixes: 5ba2f0a15564 ("mm: introduce deferred freeing for kernel page tables")
Reported-by: syzbot+fd95a72470f5a44e464c@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/6a287988.39669fcc.33b062.00a0.GAE@google.com/T/
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: David Carlier <devnexen@gmail.com>
---
v8: fix four issues raised by the Gemini review of v7 (relayed by Andrew).
    - the init_mm walk called walk_kernel_page_table_range(), which
      asserts init_mm.mmap_lock -- but that lock is now dropped; use the
      lockless walker instead.
    - only stop taking mmap_write_lock() for init_mm; efi_mm and
      current->mm are not RCU-freed and keep it.
    - bound each chunk with pgd_addr_end() so the last chunk does not
      overflow at the top of the address space.
    - powerpc frees kernel PTE pages synchronously via pte_fragment_free()
      and never sets PT_kernel, so it bypassed the RCU deferral; defer the
      kernel case there too.
v7: no code change; add version tag and per-revision changelog (Dev).
v6: chunk the init_mm walk in walk_page_range_debug() and take
    rcu_read_lock() per chunk (reverting v5's caller-side lock + assert)
    so the read section stays bounded on large kernel address spaces and
    can cond_resched() between chunks; drop the now-redundant
    mmap_write_lock() in ptdump_walk_pgd().
v5: reframe changelog around the pre-existing race and range ownership;
    correct the mmap-lock description (arm64 is the exception, not x86);
    move rcu_read_lock() into ptdump_walk_pgd() and assert it in
    walk_page_range_debug(); drop walk_kernel_page_table_range_rcu(); fix
    the pgtable-generic.c comment; document the no-sleep audit of the
    callbacks.
v4: defer the free in both the async and non-async configs, not just the
    async one; add a walk_kernel_page_table_range_rcu() helper.
v3: take rcu_read_lock() in the init_mm branch of walk_page_range_debug().
v2: use call_rcu() instead of synchronize_rcu().
 arch/powerpc/mm/pgtable-frag.c |  7 ++++++-
 include/linux/mm.h             |  7 -------
 mm/pagewalk.c                  | 36 +++++++++++++++++++++++++++++-----
 mm/pgtable-generic.c           | 22 ++++++++++++++++++++-
 mm/ptdump.c                    | 11 +++++++++--
 5 files changed, 67 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/mm/pgtable-frag.c b/arch/powerpc/mm/pgtable-frag.c
index ae742564a3d5..1e1e88f831f7 100644
--- a/arch/powerpc/mm/pgtable-frag.c
+++ b/arch/powerpc/mm/pgtable-frag.c
@@ -123,7 +123,12 @@ void pte_fragment_free(unsigned long *table, int kernel)
 
 	BUG_ON(atomic_read(&ptdesc->pt_frag_refcount) <= 0);
 	if (atomic_dec_and_test(&ptdesc->pt_frag_refcount)) {
-		if (kernel || !folio_test_clear_active(ptdesc_folio(ptdesc)))
+		/*
+		 * Kernel page tables may be walked locklessly under RCU by
+		 * ptdump, so defer their free by a grace period too, like the
+		 * lockless-GUP case below for user tables.
+		 */
+		if (!kernel && !folio_test_clear_active(ptdesc_folio(ptdesc)))
 			pte_free_now(&ptdesc->pt_rcu_head);
 		else
 			call_rcu(&ptdesc->pt_rcu_head, pte_free_now);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 485df9c2dbdd..79408a17a1b0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3695,14 +3695,7 @@ static inline void __pagetable_free(struct ptdesc *pt)
 	__free_pages(page, compound_order(page));
 }
 
-#ifdef CONFIG_ASYNC_KERNEL_PGTABLE_FREE
 void pagetable_free_kernel(struct ptdesc *pt);
-#else
-static inline void pagetable_free_kernel(struct ptdesc *pt)
-{
-	__pagetable_free(pt);
-}
-#endif
 /**
  * pagetable_free - Free pagetables
  * @pt:	The page table descriptor
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index 3ae2586ff45b..fc2fe014ac8c 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -620,7 +620,7 @@ int walk_page_range(struct mm_struct *mm, unsigned long start,
  * Note: Be careful to walk the kernel pages tables, the caller may be need to
  * take other effective approaches (mmap lock may be insufficient) to prevent
  * the intermediate kernel page tables belonging to the specified address range
- * from being freed (e.g. memory hot-remove).
+ * from being freed (e.g. memory hot-remove, vmap huge page promotion).
  */
 int walk_kernel_page_table_range(unsigned long start, unsigned long end,
 		const struct mm_walk_ops *ops, pgd_t *pgd, void *private)
@@ -643,7 +643,7 @@ int walk_kernel_page_table_range(unsigned long start, unsigned long end,
  * Use this function to walk the kernel page tables locklessly. It should be
  * guaranteed that the caller has exclusive access over the range they are
  * operating on - that there should be no concurrent access, for example,
- * changing permissions for vmalloc objects.
+ * changing permissions for vmalloc objects, or vmap huge page promotion.
  */
 int walk_kernel_page_table_range_lockless(unsigned long start, unsigned long end,
 		const struct mm_walk_ops *ops, pgd_t *pgd, void *private)
@@ -692,9 +692,35 @@ int walk_page_range_debug(struct mm_struct *mm, unsigned long start,
 	};
 
 	/* For convenience, we allow traversal of kernel mappings. */
-	if (mm == &init_mm)
-		return walk_kernel_page_table_range(start, end, ops,
-						    pgd, private);
+	if (mm == &init_mm) {
+		unsigned long addr = start;
+
+		/*
+		 * Walk in bounded chunks so the RCU read lock is never held
+		 * across the whole kernel address space.  A kernel page table
+		 * freed via pagetable_free_kernel() stays valid until the walk
+		 * that may have observed it drops the lock; releasing the lock
+		 * between chunks is safe as no page table pointer is held
+		 * across the gap. The mmap lock is not held, so use the
+		 * lockless walker; RCU, not the lock, keeps the table alive.
+		 */
+		while (addr < end) {
+			unsigned long next = pgd_addr_end(addr, end);
+			int err;
+
+			rcu_read_lock();
+			err = walk_kernel_page_table_range_lockless(addr, next, ops,
+								    pgd, private);
+			rcu_read_unlock();
+			if (err)
+				return err;
+
+			addr = next;
+			cond_resched();
+		}
+		return 0;
+	}
+
 	if (start >= end || !walk.mm)
 		return -EINVAL;
 	if (!check_ops_safe(ops))
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index b91b1a98029c..7a32e4821957 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -410,6 +410,13 @@ pte_t *pte_offset_map_lock(struct mm_struct *mm, pmd_t *pmd,
 	goto again;
 }
 
+static void kernel_pgtable_free_rcu(struct rcu_head *head)
+{
+	struct ptdesc *pt = container_of(head, struct ptdesc, pt_rcu_head);
+
+	__pagetable_free(pt);
+}
+
 #ifdef CONFIG_ASYNC_KERNEL_PGTABLE_FREE
 static void kernel_pgtable_work_func(struct work_struct *work);
 
@@ -434,8 +441,15 @@ static void kernel_pgtable_work_func(struct work_struct *work)
 	spin_unlock(&kernel_pgtable_work.lock);
 
 	iommu_sva_invalidate_kva_range(PAGE_OFFSET, TLB_FLUSH_ALL);
+
+	/*
+	 * Debug walkers (ptdump) may walk ranges they do not own and race this
+	 * free, so they walk under rcu_read_lock(). Free after a grace period:
+	 * a walker either already saw the cleared PMD, or keeps the page alive
+	 * until it drops the RCU lock.
+	 */
 	list_for_each_entry_safe(pt, next, &page_list, pt_list)
-		__pagetable_free(pt);
+		call_rcu(&pt->pt_rcu_head, kernel_pgtable_free_rcu);
 }
 
 void pagetable_free_kernel(struct ptdesc *pt)
@@ -446,4 +460,10 @@ void pagetable_free_kernel(struct ptdesc *pt)
 
 	schedule_work(&kernel_pgtable_work.work);
 }
+#else
+void pagetable_free_kernel(struct ptdesc *pt)
+{
+	/* Defer the free by a grace period; see kernel_pgtable_work_func(). */
+	call_rcu(&pt->pt_rcu_head, kernel_pgtable_free_rcu);
+}
 #endif
diff --git a/mm/ptdump.c b/mm/ptdump.c
index 973020000096..537be9995e1a 100644
--- a/mm/ptdump.c
+++ b/mm/ptdump.c
@@ -177,13 +177,20 @@ void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
 	const struct ptdump_range *range = st->range;
 
 	get_online_mems();
-	mmap_write_lock(mm);
+	/*
+	 * init_mm is walked locklessly under RCU by walk_page_range_debug().
+	 * efi_mm / current->mm page tables are not RCU-freed, so hold the
+	 * mmap write lock to keep them stable against concurrent teardown.
+	 */
+	if (mm != &init_mm)
+		mmap_write_lock(mm);
 	while (range->start != range->end) {
 		walk_page_range_debug(mm, range->start, range->end,
 				      &ptdump_ops, pgd, st);
 		range++;
 	}
-	mmap_write_unlock(mm);
+	if (mm != &init_mm)
+		mmap_write_unlock(mm);
 	put_online_mems();
 
 	/* Flush out the last page */
-- 
2.53.0



^ permalink raw reply related

* [PATCH 1/2] soc: fsl: qe_ports_ic: Use generic I/O helper instead of specific powerPC ones
From: Christophe Leroy (CS GROUP) @ 2026-07-07 14:58 UTC (permalink / raw)
  To: Qiang Zhao, Madhavan Srinivasan, Christophe Leroy (CS GROUP)
  Cc: linux-kernel, linuxppc-dev, linux-arm-kernel, Paul Louvel

Use ioread32be() and iowrite32be() instead of in_be32() and out_be32()
to allow build on other platforms than powerPC.

Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
---
 drivers/soc/fsl/qe/qe_ports_ic.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/soc/fsl/qe/qe_ports_ic.c b/drivers/soc/fsl/qe/qe_ports_ic.c
index 9b0bba64e91e4..33ca1ddafe18c 100644
--- a/drivers/soc/fsl/qe/qe_ports_ic.c
+++ b/drivers/soc/fsl/qe/qe_ports_ic.c
@@ -23,36 +23,39 @@ struct qepic_data {
 static void qepic_mask(struct irq_data *d)
 {
 	struct qepic_data *data = irq_data_get_irq_chip_data(d);
+	u32 val = ioread32be(data->reg + CEPIMR);
 
-	clrbits32(data->reg + CEPIMR, 1 << (31 - irqd_to_hwirq(d)));
+	iowrite32be(val & ~(1 << (31 - irqd_to_hwirq(d))), data->reg + CEPIMR);
 }
 
 static void qepic_unmask(struct irq_data *d)
 {
 	struct qepic_data *data = irq_data_get_irq_chip_data(d);
+	u32 val = ioread32be(data->reg + CEPIMR);
 
-	setbits32(data->reg + CEPIMR, 1 << (31 - irqd_to_hwirq(d)));
+	iowrite32be(val | 1 << (31 - irqd_to_hwirq(d)), data->reg + CEPIMR);
 }
 
 static void qepic_end(struct irq_data *d)
 {
 	struct qepic_data *data = irq_data_get_irq_chip_data(d);
 
-	out_be32(data->reg + CEPIER, 1 << (31 - irqd_to_hwirq(d)));
+	iowrite32be(1 << (31 - irqd_to_hwirq(d)), data->reg + CEPIER);
 }
 
 static int qepic_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	struct qepic_data *data = irq_data_get_irq_chip_data(d);
 	unsigned int vec = (unsigned int)irqd_to_hwirq(d);
+	u32 val = ioread32be(data->reg + CEPICR);
 
 	switch (flow_type & IRQ_TYPE_SENSE_MASK) {
 	case IRQ_TYPE_EDGE_FALLING:
-		setbits32(data->reg + CEPICR, 1 << (31 - vec));
+		iowrite32be(val | 1 << (31 - vec), data->reg + CEPICR);
 		return 0;
 	case IRQ_TYPE_EDGE_BOTH:
 	case IRQ_TYPE_NONE:
-		clrbits32(data->reg + CEPICR, 1 << (31 - vec));
+		iowrite32be(val & ~(1 << (31 - vec)), data->reg + CEPICR);
 		return 0;
 	}
 	return -EINVAL;
@@ -69,7 +72,7 @@ static struct irq_chip qepic = {
 static int qepic_get_irq(struct irq_desc *desc)
 {
 	struct qepic_data *data = irq_desc_get_handler_data(desc);
-	u32 event = in_be32(data->reg + CEPIER);
+	u32 event = ioread32be(data->reg + CEPIER);
 
 	if (!event)
 		return -1;
-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH 30/42] staging: media: cedrus: Use devm_of_reserved_mem_device_init()
From: Paul Kocialkowski @ 2026-07-07 14:05 UTC (permalink / raw)
  To: Mukesh Ojha
  Cc: Bjorn Andersson, Konrad Dybcio, Liviu Dudau, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Joel Stanley, Andrew Jeffery, Paul Cercueil, Anitha Chrisanthus,
	Linus Walleij, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Alexey Brodkin, Laurent Pinchart, Tomi Valkeinen, Michal Simek,
	Daniel Scally, Jacopo Mondi, Mauro Carvalho Chehab, Eddie James,
	Tiffany Lin, Andrew-CT Chen, Yunfei Dong, Minghsiu Tsai,
	Houlong Wei, Matthias Brugger, AngeloGioacchino Del Regno,
	Joseph Liu, Marvin Lin, Dmitry Osipenko, Krzysztof Kozlowski,
	Thierry Reding, Jonathan Hunter, Srinivas Kandagatla,
	Arnd Bergmann, Greg Kroah-Hartman, Ge Gordon, Adrian Hunter,
	Ulf Hansson, Rob Herring, Saravana Kannan, Mathieu Poirier,
	Jaroslav Kysela, Takashi Iwai, Shengjiu Wang, Xiubo Li,
	Liam Girdwood, Mark Brown, Frank Li, Sascha Hauer, Peter Ujfalusi,
	Bard Liao, Daniel Baluta, Orson Zhai, Baolin Wang, Peter Chen,
	Fugang Duan, Ekansh Gupta, BST Linux Kernel Upstream Group,
	Fabio Estevam, Nicolin Chen, Pengutronix Kernel Team,
	Kai Vehmanen, Pierre-Louis Bossart, Vijendar Mukunda,
	Chunyan Zhang, CIX Linux Kernel Upstream Group, linux-arm-msm,
	linux-kernel, dri-devel, linux-aspeed, linux-arm-kernel,
	linux-mips, linux-sunxi, linux-media, openbmc, linux-mediatek,
	kernel, linux-tegra, linux-mmc, devicetree, linux-remoteproc,
	linux-staging, linux-sound, linuxppc-dev, imx,
	sound-open-firmware
In-Reply-To: <20260703193855.110619-31-mukesh.ojha@oss.qualcomm.com>

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

Hi Mukesh,

On Sat 04 Jul 26, 01:08, Mukesh Ojha wrote:
> Use the devres-managed devm_of_reserved_mem_device_init() instead of
> the manual of_reserved_mem_device_init()/of_reserved_mem_device_release()
> pair, letting the device resource manager handle cleanup automatically.

Thanks for your work!

> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> ---
>  drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 6 +-----
>  1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
> index 444fb53878d1..7b5aa94064a1 100644
> --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
> +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
> @@ -266,7 +266,7 @@ int cedrus_hw_probe(struct cedrus_dev *dev)
>  		return ret;
>  	}
>  
> -	ret = of_reserved_mem_device_init(dev->dev);
> +	ret = devm_of_reserved_mem_device_init(dev->dev);
>  	if (ret && ret != -ENODEV) {
>  		dev_err(dev->dev, "Failed to reserve memory\n");
>  
> @@ -341,8 +341,6 @@ int cedrus_hw_probe(struct cedrus_dev *dev)
>  err_sram:
>  	sunxi_sram_release(dev->dev);
>  err_mem:

Could you also remove this label and switch the goto user to a regular
return ret?

Thanks!

All the best,

Paul

> -	of_reserved_mem_device_release(dev->dev);
> -
>  	return ret;
>  }
>  
> @@ -353,6 +351,4 @@ void cedrus_hw_remove(struct cedrus_dev *dev)
>  		cedrus_hw_suspend(dev->dev);
>  
>  	sunxi_sram_release(dev->dev);
> -
> -	of_reserved_mem_device_release(dev->dev);
>  }
> -- 
> 2.53.0
> 

-- 
Paul Kocialkowski,

Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/

Expert in multimedia, graphics and embedded hardware support with Linux.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH 08/42] drm: logicvc: Use devm_of_reserved_mem_device_init()
From: Paul Kocialkowski @ 2026-07-07 14:10 UTC (permalink / raw)
  To: Mukesh Ojha
  Cc: Bjorn Andersson, Konrad Dybcio, Liviu Dudau, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Joel Stanley, Andrew Jeffery, Paul Cercueil, Anitha Chrisanthus,
	Linus Walleij, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Alexey Brodkin, Laurent Pinchart, Tomi Valkeinen, Michal Simek,
	Daniel Scally, Jacopo Mondi, Mauro Carvalho Chehab, Eddie James,
	Tiffany Lin, Andrew-CT Chen, Yunfei Dong, Minghsiu Tsai,
	Houlong Wei, Matthias Brugger, AngeloGioacchino Del Regno,
	Joseph Liu, Marvin Lin, Dmitry Osipenko, Krzysztof Kozlowski,
	Thierry Reding, Jonathan Hunter, Srinivas Kandagatla,
	Arnd Bergmann, Greg Kroah-Hartman, Ge Gordon, Adrian Hunter,
	Ulf Hansson, Rob Herring, Saravana Kannan, Mathieu Poirier,
	Jaroslav Kysela, Takashi Iwai, Shengjiu Wang, Xiubo Li,
	Liam Girdwood, Mark Brown, Frank Li, Sascha Hauer, Peter Ujfalusi,
	Bard Liao, Daniel Baluta, Orson Zhai, Baolin Wang, Peter Chen,
	Fugang Duan, Ekansh Gupta, BST Linux Kernel Upstream Group,
	Fabio Estevam, Nicolin Chen, Pengutronix Kernel Team,
	Kai Vehmanen, Pierre-Louis Bossart, Vijendar Mukunda,
	Chunyan Zhang, CIX Linux Kernel Upstream Group, linux-arm-msm,
	linux-kernel, dri-devel, linux-aspeed, linux-arm-kernel,
	linux-mips, linux-sunxi, linux-media, openbmc, linux-mediatek,
	kernel, linux-tegra, linux-mmc, devicetree, linux-remoteproc,
	linux-staging, linux-sound, linuxppc-dev, imx,
	sound-open-firmware
In-Reply-To: <20260703193855.110619-9-mukesh.ojha@oss.qualcomm.com>

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

Hi Mukesh,

On Sat 04 Jul 26, 01:08, Mukesh Ojha wrote:
> Switch to devm_of_reserved_mem_device_init() so the reserved memory
> region is released automatically on probe failure or device unbind.
> Replace all error paths that jumped to error_reserved_mem: with
> error_early: since the manual cleanup label is no longer needed, and
> remove the explicit of_reserved_mem_device_release() call in the remove
> function.
> 
> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>

Looks good to me, thanks!

Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Acked-by: Paul Kocialkowski <paulk@sys-base.io>

All the best,

Paul

> ---
>  drivers/gpu/drm/logicvc/logicvc_drm.c | 21 ++++++++-------------
>  1 file changed, 8 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/logicvc/logicvc_drm.c b/drivers/gpu/drm/logicvc/logicvc_drm.c
> index bbebf4fc7f51..d6dbe52ff0a9 100644
> --- a/drivers/gpu/drm/logicvc/logicvc_drm.c
> +++ b/drivers/gpu/drm/logicvc/logicvc_drm.c
> @@ -306,7 +306,7 @@ static int logicvc_drm_probe(struct platform_device *pdev)
>  	int irq;
>  	int ret;
>  
> -	ret = of_reserved_mem_device_init(dev);
> +	ret = devm_of_reserved_mem_device_init(dev);
>  	if (ret && ret != -ENODEV) {
>  		dev_err(dev, "Failed to init memory region\n");
>  		goto error_early;
> @@ -327,14 +327,14 @@ static int logicvc_drm_probe(struct platform_device *pdev)
>  		ret = of_address_to_resource(of_node, 0, &res);
>  		if (ret) {
>  			dev_err(dev, "Failed to get resource from address\n");
> -			goto error_reserved_mem;
> +			goto error_early;
>  		}
>  
>  		base = devm_ioremap_resource(dev, &res);
>  		if (IS_ERR(base)) {
>  			dev_err(dev, "Failed to map I/O base\n");
>  			ret = PTR_ERR(base);
> -			goto error_reserved_mem;
> +			goto error_early;
>  		}
>  
>  		logicvc_drm_regmap_config.max_register = resource_size(&res) -
> @@ -345,21 +345,21 @@ static int logicvc_drm_probe(struct platform_device *pdev)
>  		if (IS_ERR(regmap)) {
>  			dev_err(dev, "Failed to create regmap for I/O\n");
>  			ret = PTR_ERR(regmap);
> -			goto error_reserved_mem;
> +			goto error_early;
>  		}
>  	}
>  
>  	irq = platform_get_irq(pdev, 0);
>  	if (irq < 0) {
>  		ret = -ENODEV;
> -		goto error_reserved_mem;
> +		goto error_early;
>  	}
>  
>  	logicvc = devm_drm_dev_alloc(dev, &logicvc_drm_driver,
>  				     struct logicvc_drm, drm_dev);
>  	if (IS_ERR(logicvc)) {
>  		ret = PTR_ERR(logicvc);
> -		goto error_reserved_mem;
> +		goto error_early;
>  	}
>  
>  	platform_set_drvdata(pdev, logicvc);
> @@ -371,7 +371,7 @@ static int logicvc_drm_probe(struct platform_device *pdev)
>  	caps = logicvc_drm_caps_match(logicvc);
>  	if (!caps) {
>  		ret = -EINVAL;
> -		goto error_reserved_mem;
> +		goto error_early;
>  	}
>  
>  	logicvc->caps = caps;
> @@ -382,7 +382,7 @@ static int logicvc_drm_probe(struct platform_device *pdev)
>  	ret = logicvc_clocks_prepare(logicvc);
>  	if (ret) {
>  		drm_err(drm_dev, "Failed to prepare clocks\n");
> -		goto error_reserved_mem;
> +		goto error_early;
>  	}
>  
>  	ret = devm_request_irq(dev, irq, logicvc_drm_irq_handler, 0,
> @@ -450,9 +450,6 @@ static int logicvc_drm_probe(struct platform_device *pdev)
>  error_clocks:
>  	logicvc_clocks_unprepare(logicvc);
>  
> -error_reserved_mem:
> -	of_reserved_mem_device_release(dev);
> -
>  error_early:
>  	return ret;
>  }
> @@ -469,8 +466,6 @@ static void logicvc_drm_remove(struct platform_device *pdev)
>  	logicvc_mode_fini(logicvc);
>  
>  	logicvc_clocks_unprepare(logicvc);
> -
> -	of_reserved_mem_device_release(dev);
>  }
>  
>  static void logicvc_drm_shutdown(struct platform_device *pdev)
> -- 
> 2.53.0
> 

-- 
Paul Kocialkowski,

Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/

Expert in multimedia, graphics and embedded hardware support with Linux.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH 20/42] drm: xlnx: zynqmp_dpsub: Use devm_of_reserved_mem_device_init()
From: Pandey, Radhey Shyam @ 2026-07-07  9:13 UTC (permalink / raw)
  To: Mukesh Ojha, Bjorn Andersson, Konrad Dybcio, Liviu Dudau,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Joel Stanley, Andrew Jeffery, Paul Cercueil,
	Anitha Chrisanthus, Paul Kocialkowski, Linus Walleij,
	Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Alexey Brodkin,
	Laurent Pinchart, Tomi Valkeinen, Michal Simek, Daniel Scally,
	Jacopo Mondi, Mauro Carvalho Chehab, Eddie James, Tiffany Lin,
	Andrew-CT Chen, Yunfei Dong, Minghsiu Tsai, Houlong Wei,
	Matthias Brugger, AngeloGioacchino Del Regno, Joseph Liu,
	Marvin Lin, Dmitry Osipenko, Krzysztof Kozlowski, Thierry Reding,
	Jonathan Hunter, Srinivas Kandagatla, Arnd Bergmann,
	Greg Kroah-Hartman, Ge Gordon, Adrian Hunter, Ulf Hansson,
	Rob Herring, Saravana Kannan, Mathieu Poirier, Jaroslav Kysela,
	Takashi Iwai, Shengjiu Wang, Xiubo Li, Liam Girdwood, Mark Brown,
	Frank Li, Sascha Hauer, Peter Ujfalusi, Bard Liao, Daniel Baluta,
	Orson Zhai, Baolin Wang, Peter Chen, Fugang Duan
  Cc: Ekansh Gupta, BST Linux Kernel Upstream Group, Fabio Estevam,
	Nicolin Chen, Pengutronix Kernel Team, Kai Vehmanen,
	Pierre-Louis Bossart, Vijendar Mukunda, Chunyan Zhang,
	CIX Linux Kernel Upstream Group, linux-arm-msm, linux-kernel,
	dri-devel, linux-aspeed, linux-arm-kernel, linux-mips,
	linux-sunxi, linux-media, openbmc, linux-mediatek, kernel,
	linux-tegra, linux-mmc, devicetree, linux-remoteproc,
	linux-staging, linux-sound, linuxppc-dev, imx,
	sound-open-firmware
In-Reply-To: <20260703193855.110619-21-mukesh.ojha@oss.qualcomm.com>

> Use the devres-managed devm_of_reserved_mem_device_init() instead of
> the manual of_reserved_mem_device_init()/of_reserved_mem_device_release()
> pair, letting the device resource manager handle cleanup automatically.
> 
> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>

Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Thanks!

> ---
>   drivers/gpu/drm/xlnx/zynqmp_dpsub.c | 4 +---
>   1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
> index 53ab1a2a5aaf..e93a7a299b52 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
> @@ -203,7 +203,7 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
>   	dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
>   
>   	/* Try the reserved memory. Proceed if there's none. */
> -	of_reserved_mem_device_init(&pdev->dev);
> +	devm_of_reserved_mem_device_init(&pdev->dev);
>   
>   	ret = zynqmp_dpsub_init_clocks(dpsub);
>   	if (ret < 0)
> @@ -255,7 +255,6 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
>   	pm_runtime_disable(&pdev->dev);
>   	clk_disable_unprepare(dpsub->apb_clk);
>   err_mem:
> -	of_reserved_mem_device_release(&pdev->dev);
>   	if (!dpsub->drm)
>   		zynqmp_dpsub_release(dpsub);
>   	return ret;
> @@ -276,7 +275,6 @@ static void zynqmp_dpsub_remove(struct platform_device *pdev)
>   
>   	pm_runtime_disable(&pdev->dev);
>   	clk_disable_unprepare(dpsub->apb_clk);
> -	of_reserved_mem_device_release(&pdev->dev);
>   
>   	if (!dpsub->drm)
>   		zynqmp_dpsub_release(dpsub);



^ permalink raw reply

* Re: [PATCH] perf data convert json: Fix trace_seq memory leak in process_sample_event()
From: Tanushree Shah @ 2026-07-07 14:06 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, jolsa, adrian.hunter, vmolnaro, mpetlan,
	tmricht, maddy, irogers, linux-perf-users, linuxppc-dev, atrajeev,
	hbathini, Tejas.Manhas1, Tanushree.Shah, Shivani.Nittor
In-Reply-To: <akhM9-d-tNjZzb-A@google.com>

Hi Namhyung,
The only change I had planned for v2 was the fix for the pre-existing 
issue, which has now already been merged separately upstream.

https://github.com/torvalds/linux/commit/2857a5dca750ea989c6fb70b4c14e801e4b7b4ad

Please let me know if there is any additional change you would like me 
to include in v2.

On 04/07/26 05:29, Namhyung Kim wrote:
> On Thu, Jul 02, 2026 at 12:46:54PM +0530, Tanushree Shah wrote:
>> Hi Namhyung,
>>
>> Yes, I was planning to send a v2 based on the review comments to fix the
>> pre-existing issue.
>>
>> However, Arnaldo mentioned that the original patch had already been merged
>> before I got to send a v2, so I addressed the pre-existing issue in a
>> separate patch instead. The patch is available here:
>>
>> https://lore.kernel.org/linux-perf-users/20260606121528.406919-2-tshah@linux.ibm.com/
>>
>> That said, although Arnaldo mentioned that this patch had been merged, I
>> don't see it in perf-tools-next yet either. I'll wait for him to clarify its
>> current status.
> 
> It's not in the perf-tools-next, and no plan to add it.  Please send v2.
> 
> Thanks,
> Namhyung
> 
> 
Thanks
Tanushree Shah


^ permalink raw reply

* Re: [PATCH v3] perf dso: Fix kallsyms DSO detection with fallback logic
From: Tanushree Shah @ 2026-07-07 14:03 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: acme, jolsa, adrian.hunter, vmolnaro, mpetlan, tmricht, maddy,
	irogers, linux-perf-users, linuxppc-dev, atrajeev, hbathini,
	Tejas.Manhas1, Tanushree.Shah, Shivani.Nittor
In-Reply-To: <akRWfQB9lLwq2HsR@google.com>


Hello, Thanks for the review.
On 01/07/26 05:21, Namhyung Kim wrote:
> On Fri, Jun 26, 2026 at 09:40:53PM +0530, Tanushree Shah wrote:
>> The current kallsyms detection in dso__is_kallsyms() uses the
>> dso_binary_type enum which fixes the issue of kallsyms being cached in
>> the build-id cache for out-of-tree modules.
>>
>> However, during build-id injection in perf record/inject, dso_binary_type
>> has not been explicitly set yet,so dso__binary_type() returns
>> DSO_BINARY_TYPE__NOT_FOUND instead of DSO_BINARY_TYPE__KALLSYMS for the
>> kernel DSO. The current check then fails to identify it as kallsyms,
>> causing build-id symlinks to not be created in ~/.debug/.build-id/ and
>> perf archive to fail with "Cannot stat" errors.
>>
>> Steps to reproduce the issue:
>> 1. rm -rf ~/.debug/.build-id
>> 2. perf record sleep 1
>> 3. perf archive
>>
>> Fix by falling back to matching long_name against the known kallsyms
>> strings explicitly when binary_type is not yet set
>> (== DSO_BINARY_TYPE__NOT_FOUND). Use strcmp() for exact matching of
>> fixed names and strict validation for guest kallsyms with embedded PID
>> to prevent path traversal attacks.
>>
>> Fixes: ebf0b332732d ("perf dso: fix dso__is_kallsyms() check")
>> Signed-off-by: Tanushree Shah <tshah@linux.ibm.com>
>> ---
>> v2 -> v3: Replace strncmp() prefix matching with strcmp() for fixed
>>            kallsyms names and add is_guest_kallsyms_pid_name() to
>>            strictly validate guest kallsyms with PID format, preventing
>>            path traversal attacks.
>>
>> v1 -> v2: Rename DSO__NAME_GUEST_KALLSYMS to DSO__PREFIX_GUEST_KALLSYMS
>>            to reflect that it is a prefix, not a full name.
>>
>> v1: https://lore.kernel.org/all/20260410071225.708005-2-tshah@linux.ibm.com/
>>
>>   tools/perf/util/dso.h | 57 ++++++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 56 insertions(+), 1 deletion(-)
>>
>> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
>> index ede691e9a249..8763e6f65316 100644
>> --- a/tools/perf/util/dso.h
>> +++ b/tools/perf/util/dso.h
>> @@ -9,6 +9,7 @@
>>   #include <stdbool.h>
>>   #include <stdio.h>
>>   #include <linux/bitops.h>
>> +#include <string.h>
>>   #include "build-id.h"
>>   #include "debuginfo.h"
>>   #include "mutex.h"
>> @@ -20,6 +21,40 @@ struct perf_env;
>>   
>>   #define DSO__NAME_KALLSYMS	"[kernel.kallsyms]"
>>   #define DSO__NAME_KCORE		"[kernel.kcore]"
>> +#define DSO__NAME_GUEST_KALLSYMS		"[guest.kernel.kallsyms]"
>> +#define DSO__NAME_GUEST_KALLSYMS_PID_PREFIX	"[guest.kernel.kallsyms."
>> +
>> +/*
>> + * Validate names of the form "[guest.kernel.kallsyms.<pid>]", where
>> + * <pid> is the PID of the guest VM and varies per guest, so it
>> + * cannot be matched with strcmp() against a fixed string.
>> + *
>> + * Every character after the fixed prefix must be a decimal digit,
>> + * with ']' immediately terminating the digit run and nothing
>> + * following it. This rules out '/', "..", or any other character
>> + * being smuggled into the name.
>> + */
>> +static inline bool is_guest_kallsyms_pid_name(const char *name)
>> +{
>> +	const size_t prefix_len = sizeof(DSO__NAME_GUEST_KALLSYMS_PID_PREFIX) - 1;
>> +	size_t digits;
>> +
>> +	if (strncmp(name, DSO__NAME_GUEST_KALLSYMS_PID_PREFIX, prefix_len) != 0)
>> +		return false;
>> +
>> +	digits = strspn(name + prefix_len, "0123456789");
>> +	if (digits == 0)
>> +		return false;
>> +
>> +	/* ']' must terminate the digit run, with nothing trailing it */
>> +	if (name[prefix_len + digits] != ']')
>> +		return false;
>> +
>> +	if (name[prefix_len + digits + 1] != '\0')
>> +		return false;
>> +
>> +	return true;
>> +}
>>   
>>   /**
>>    * enum dso_binary_type - The kind of DSO generally associated with a memory
>> @@ -914,8 +949,28 @@ static inline bool dso__is_kcore(const struct dso *dso)
>>   static inline bool dso__is_kallsyms(const struct dso *dso)
>>   {
>>   	enum dso_binary_type bt = dso__binary_type(dso);
> 
> I have to check its usage carefully but any chance dso__symtab_type(dso)
> instead produces better results?
> 
I did some additional logging and found that symtab_type is not getting 
set while running perf record, so it seems dso__symtab_type(dso) would 
likely have the same issue here.
> 
>> +	const char *name;
>> +
>> +	if (bt == DSO_BINARY_TYPE__KALLSYMS || bt == DSO_BINARY_TYPE__GUEST_KALLSYMS)
>> +		return true;
>> +
>> +	if (bt != DSO_BINARY_TYPE__NOT_FOUND)
>> +		return false;
>> +
>> +	if (!RC_CHK_ACCESS(dso)->kernel)
> 
> I think the proper wrapper is dso__kernel().
> 
Thanks for the pointer. Will use this and send v4.
> 
>> +		return false;
>> +
>> +	name = RC_CHK_ACCESS(dso)->long_name;
> 
> And dso__long_name().

Sure, will use this and send v4.
> 
> Thanks,
> Namhyung
> 
> 
>> +	if (!name)
>> +		return false;
>> +
>> +	if (!strcmp(name, DSO__NAME_KALLSYMS))
>> +		return true;
>> +
>> +	if (!strcmp(name, DSO__NAME_GUEST_KALLSYMS))
>> +		return true;
>>   
>> -	return bt == DSO_BINARY_TYPE__KALLSYMS || bt == DSO_BINARY_TYPE__GUEST_KALLSYMS;
>> +	return is_guest_kallsyms_pid_name(name);
>>   }
>>   
>>   bool dso__is_object_file(const struct dso *dso);
>> -- 
>> 2.47.3
>>
> 
Thanks
Tanushree Shah



^ permalink raw reply

* [PATCH RFC] RAS: hwerr_tracking: move recoverable hardware error tracking out of vmcoreinfo
From: Breno Leitao @ 2026-07-07 14:02 UTC (permalink / raw)
  To: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
	Dave Hansen, x86, H. Peter Anvin, Rafael J. Wysocki, Hanjun Guo,
	Mauro Carvalho Chehab, Shuai Xue, Len Brown, Mahesh J Salgaonkar,
	Oliver O'Halloran, Bjorn Helgaas, Breno Leitao
  Cc: linux-kernel, linux-edac, linux-acpi, linuxppc-dev, linux-pci,
	kernel-team, Breno Leitao

The recoverable hardware error tracking (hwerr_log_error_type() and the
hwerr_data[] counters) was added under vmcoreinfo, but it uses none of the
vmcoreinfo note machinery: hwerr_data[] is a plain global array that crash
tools read from the vmcore by symbol, like any other global.  Functionally
it is RAS code, fed only by the hardware error paths (x86 MCE, APEI GHES
and PCIe AER).

I wanted to expand it, and Baoquan suggested moving it away from vmcore
info, which makes sense. [1]

Move the implementation to drivers/ras/hwerr_tracking.c and the
declaration (with its no-op stub) to <linux/ras.h>.  Give it a dedicated
CONFIG_RAS_HWERR (bool, under RAS, default y) rather than riding
CONFIG_VMCORE_INFO, so it is a first-class RAS feature that can be turned
off on its own.  The producers now reach hwerr_log_error_type() through
<linux/ras.h>: x86 MCE and APEI GHES already include it, so drop their
<linux/vmcore_info.h> include; PCIe AER switches its include from
<linux/vmcore_info.h> to <linux/ras.h>.

enum hwerr_error_type stays in <uapi/linux/vmcore.h> as it has been part
of the UAPI since the feature shipped; <linux/ras.h> includes it from
there.

hwerr_data[] keeps its name and layout, so existing crash/drgn recipes
keep working.  The config gate moves from CONFIG_VMCORE_INFO to
CONFIG_RAS_HWERR (default y).

Link: https://lore.kernel.org/all/aYvi4Y_HNqk_u1-v@fedora/ [1]
Signed-off-by: Breno Leitao <leitao@debian.org>
---
Once we move it outside of vmcore info, I am planning to add new
features that are in the limbo now, given they don't belong to vmcore
info, such as:

Track fatal hardware errors
	https://lore.kernel.org/all/20260617-hwerr-v1-0-ff131cd6203c@debian.org/

Expose hardware error recovery statistics via sysfs
	https://lore.kernel.org/all/20260202-vmcoreinfo_sysfs-v2-0-8f3b5308b894@debian.org/
---
 MAINTAINERS                    |  7 +++++++
 arch/x86/kernel/cpu/mce/core.c |  1 -
 drivers/acpi/apei/ghes.c       |  1 -
 drivers/pci/pcie/aer.c         |  2 +-
 drivers/ras/Kconfig            | 12 ++++++++++++
 drivers/ras/Makefile           |  1 +
 drivers/ras/hwerr_tracking.c   | 35 +++++++++++++++++++++++++++++++++++
 include/linux/ras.h            |  7 +++++++
 include/linux/vmcore_info.h    |  7 -------
 kernel/vmcore_info.c           | 21 ---------------------
 10 files changed, 63 insertions(+), 31 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1705eb823dd00..356a51032e4b0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22539,6 +22539,13 @@ L:	linux-edac@vger.kernel.org
 S:	Maintained
 F:	drivers/ras/amd/fmpm.c
 
+RAS RECOVERABLE HARDWARE ERROR TRACKING
+M:	Breno Leitao <leitao@kernel.org>
+L:	linux-edac@vger.kernel.org
+S:	Maintained
+F:	Documentation/driver-api/hw-recoverable-errors.rst
+F:	drivers/ras/hwerr_tracking.c
+
 RASPBERRY PI PISP BACK END
 M:	Jacopo Mondi <jacopo.mondi@ideasonboard.com>
 R:	Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
index 9bba1e2f03af7..58f1d7a601883 100644
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -45,7 +45,6 @@
 #include <linux/task_work.h>
 #include <linux/hardirq.h>
 #include <linux/kexec.h>
-#include <linux/vmcore_info.h>
 
 #include <asm/fred.h>
 #include <asm/cpu_device_id.h>
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 3236a3ce79d6b..4b6666bc19c77 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -45,7 +45,6 @@
 #include <linux/uuid.h>
 #include <linux/ras.h>
 #include <linux/task_work.h>
-#include <linux/vmcore_info.h>
 
 #include <acpi/actbl1.h>
 #include <acpi/ghes.h>
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index c4fd9c0b2a548..00cdca26a5114 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -30,7 +30,7 @@
 #include <linux/kfifo.h>
 #include <linux/ratelimit.h>
 #include <linux/slab.h>
-#include <linux/vmcore_info.h>
+#include <linux/ras.h>
 #include <acpi/apei.h>
 #include <acpi/ghes.h>
 #include <ras/ras_event.h>
diff --git a/drivers/ras/Kconfig b/drivers/ras/Kconfig
index fc4f4bb94a4c6..241642679c1f1 100644
--- a/drivers/ras/Kconfig
+++ b/drivers/ras/Kconfig
@@ -34,6 +34,18 @@ if RAS
 source "arch/x86/ras/Kconfig"
 source "drivers/ras/amd/atl/Kconfig"
 
+config RAS_HWERR
+	bool "Track hardware errors for crash analysis"
+	default y
+	help
+	  Record the count and timestamp of the most recent recoverable
+	  hardware error for each source (CPU, memory, PCI, CXL, ...).  The
+	  data is written at runtime and read post-mortem from a vmcore by
+	  tools such as crash or drgn, to correlate recoverable errors with a
+	  later panic.
+
+	  If unsure, say Y.
+
 config RAS_FMPM
 	tristate "FRU Memory Poison Manager"
 	default m
diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile
index 11f95d59d3972..4217bee75d910 100644
--- a/drivers/ras/Makefile
+++ b/drivers/ras/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_RAS)	+= ras.o
+obj-$(CONFIG_RAS_HWERR)	+= hwerr_tracking.o
 obj-$(CONFIG_DEBUG_FS)	+= debugfs.o
 obj-$(CONFIG_RAS_CEC)	+= cec.o
 
diff --git a/drivers/ras/hwerr_tracking.c b/drivers/ras/hwerr_tracking.c
new file mode 100644
index 0000000000000..847c01fb24d55
--- /dev/null
+++ b/drivers/ras/hwerr_tracking.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Track recoverable hardware errors (visible to the OS but not fatal) so that
+ * crash tools like crash/drgn can read the count and timestamp of the last
+ * occurrence from a vmcore and correlate them with a subsequent panic.
+ *
+ * Copyright (c) 2026 Meta Platforms, Inc. and affiliates
+ * Copyright (c) 2026 Breno Leitao <leitao@kernel.org>
+ */
+
+#include <linux/atomic.h>
+#include <linux/export.h>
+#include <linux/ras.h>
+#include <linux/timekeeping.h>
+
+struct hwerr_info {
+	atomic_t count;
+	time64_t timestamp;
+};
+
+/*
+ * Keep hwerr_data[] at global scope so it stays accessible from the vmcore
+ * (via crash/drgn) even when Link Time Optimization (LTO) is enabled.
+ */
+struct hwerr_info hwerr_data[HWERR_RECOV_MAX];
+
+void hwerr_log_error_type(enum hwerr_error_type src)
+{
+	if (src < 0 || src >= HWERR_RECOV_MAX)
+		return;
+
+	atomic_inc(&hwerr_data[src].count);
+	WRITE_ONCE(hwerr_data[src].timestamp, ktime_get_real_seconds());
+}
+EXPORT_SYMBOL_GPL(hwerr_log_error_type);
diff --git a/include/linux/ras.h b/include/linux/ras.h
index 468941bfe855f..1019183c00342 100644
--- a/include/linux/ras.h
+++ b/include/linux/ras.h
@@ -5,6 +5,7 @@
 #include <asm/errno.h>
 #include <linux/uuid.h>
 #include <linux/cper.h>
+#include <uapi/linux/vmcore.h>
 
 #ifdef CONFIG_DEBUG_FS
 int ras_userspace_consumers(void);
@@ -35,6 +36,12 @@ static inline void
 log_arm_hw_error(struct cper_sec_proc_arm *err, const u8 sev) { return; }
 #endif
 
+#ifdef CONFIG_RAS_HWERR
+void hwerr_log_error_type(enum hwerr_error_type src);
+#else
+static inline void hwerr_log_error_type(enum hwerr_error_type src) { }
+#endif
+
 struct atl_err {
 	u64 addr;
 	u64 ipid;
diff --git a/include/linux/vmcore_info.h b/include/linux/vmcore_info.h
index e71518caacdfc..fb6f29b7202e3 100644
--- a/include/linux/vmcore_info.h
+++ b/include/linux/vmcore_info.h
@@ -5,7 +5,6 @@
 #include <linux/linkage.h>
 #include <linux/elfcore.h>
 #include <linux/elf.h>
-#include <uapi/linux/vmcore.h>
 
 #define CRASH_CORE_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
 #define CRASH_CORE_NOTE_NAME_BYTES ALIGN(sizeof(NN_PRSTATUS), 4)
@@ -79,10 +78,4 @@ Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
 			  void *data, size_t data_len);
 void final_note(Elf_Word *buf);
 
-#ifdef CONFIG_VMCORE_INFO
-void hwerr_log_error_type(enum hwerr_error_type src);
-#else
-static inline void hwerr_log_error_type(enum hwerr_error_type src) {};
-#endif
-
 #endif /* LINUX_VMCORE_INFO_H */
diff --git a/kernel/vmcore_info.c b/kernel/vmcore_info.c
index 8614430ca212a..5c288796bdbf5 100644
--- a/kernel/vmcore_info.c
+++ b/kernel/vmcore_info.c
@@ -29,17 +29,6 @@ u32 *vmcoreinfo_note;
 /* trusted vmcoreinfo, e.g. we can make a copy in the crash memory */
 static unsigned char *vmcoreinfo_data_safecopy;
 
-struct hwerr_info {
-	atomic_t count;
-	time64_t timestamp;
-};
-
-/*
- * The hwerr_data[] array is declared with global scope so that it remains
- * accessible to vmcoreinfo even when Link Time Optimization (LTO) is enabled.
- */
-struct hwerr_info hwerr_data[HWERR_RECOV_MAX];
-
 Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
 			  void *data, size_t data_len)
 {
@@ -127,16 +116,6 @@ phys_addr_t __weak paddr_vmcoreinfo_note(void)
 }
 EXPORT_SYMBOL(paddr_vmcoreinfo_note);
 
-void hwerr_log_error_type(enum hwerr_error_type src)
-{
-	if (src < 0 || src >= HWERR_RECOV_MAX)
-		return;
-
-	atomic_inc(&hwerr_data[src].count);
-	WRITE_ONCE(hwerr_data[src].timestamp, ktime_get_real_seconds());
-}
-EXPORT_SYMBOL_GPL(hwerr_log_error_type);
-
 static int __init crash_save_vmcoreinfo_init(void)
 {
 	int order;

---
base-commit: 3d5670d672ae08b8c534b7beed6f57c8b44e7b43
change-id: 20260629-hwerr-ras-e26664926c58

Best regards,
--  
Breno Leitao <leitao@debian.org>



^ permalink raw reply related

* Re: [PATCH v2 0/5] treewide: remove unreachable memblock_reserve() return value checks in early boot
From: Mike Rapoport @ 2026-07-07 13:40 UTC (permalink / raw)
  To: Sang-Heon Jeon
  Cc: Ard Biesheuvel, Borislav Petkov, Chris Zankel, Dave Hansen,
	Ingo Molnar, John Paul Adrian Glaubitz, Madhavan Srinivasan,
	Max Filippov, Michael Ellerman, Rich Felker, Thomas Gleixner,
	Yoshinori Sato, linux-mm, Christophe Leroy (CS GROUP),
	H. Peter Anvin, Ilias Apalodimas, linux-efi, linux-kernel,
	linuxppc-dev, linux-sh, Nicholas Piggin, x86
In-Reply-To: <CABFDxME7ig1SQDB39TUeUXoAOA2jSRhg6h-bm0kUHrHzGYeE-A@mail.gmail.com>

On Tue, Jul 07, 2026 at 10:24:09PM +0900, Sang-Heon Jeon wrote:
> Hi Mike,
> 
> On Tue, Jul 7, 2026 at 3:17 PM Mike Rapoport <rppt@kernel.org> wrote:
> >
> > Hi Sang-Heon,
> >
> > On Tue, Jul 07, 2026 at 01:37:48AM +0900, Sang-Heon Jeon wrote:
> > > memblock_reserve() can only return an error after memblock_allow_resize()
> > > has been called. Before that it either succeeds or panics, never returning
> > > an error.
> > >
> > > Before memblock_allow_resize() is called, the return value checks of
> > > memblock_reserve() are unreachable and can be removed.
> >
> > I'd rather keep these checks.
> >
> > Removing them relies on internal details of memblock_reserve() implementation
> > and the existing event sequence. If the code would move around relying on
> > panic in memblock_reserve() may not be correct.
> >
> > And the few bytes and cycles the change saves do not worth the churn.
> 
> Makes sense to me.
> 
> But most early boot callers of memblock_reserve() don't check the
> return value, so I thought we already rely on its internal behavior
> anyway. So the few remaining checks just looked a bit inconsistent to
> me.

In reality it's very unlikely for memblock_reserve() to fail, especially
after resize is allowed. 
And if it does fail, the system would trip on a memory error, usually
sooner than later.

> Would you still prefer to keep these checks? If so, I'm fine with
> dropping this patch series. It's not a big deal :)

Let's keep the checks as they are now.
 
> Best Regards,
> Sang-Heon Jeon

-- 
Sincerely yours,
Mike.


^ permalink raw reply

* Re: [PATCH v2 0/5] treewide: remove unreachable memblock_reserve() return value checks in early boot
From: Sang-Heon Jeon @ 2026-07-07 13:24 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Ard Biesheuvel, Borislav Petkov, Chris Zankel, Dave Hansen,
	Ingo Molnar, John Paul Adrian Glaubitz, Madhavan Srinivasan,
	Max Filippov, Michael Ellerman, Rich Felker, Thomas Gleixner,
	Yoshinori Sato, linux-mm, Christophe Leroy (CS GROUP),
	H. Peter Anvin, Ilias Apalodimas, linux-efi, linux-kernel,
	linuxppc-dev, linux-sh, Nicholas Piggin, x86
In-Reply-To: <akyZ5DhIV_Grn1Kc@kernel.org>

Hi Mike,

On Tue, Jul 7, 2026 at 3:17 PM Mike Rapoport <rppt@kernel.org> wrote:
>
> Hi Sang-Heon,
>
> On Tue, Jul 07, 2026 at 01:37:48AM +0900, Sang-Heon Jeon wrote:
> > memblock_reserve() can only return an error after memblock_allow_resize()
> > has been called. Before that it either succeeds or panics, never returning
> > an error.
> >
> > Before memblock_allow_resize() is called, the return value checks of
> > memblock_reserve() are unreachable and can be removed.
>
> I'd rather keep these checks.
>
> Removing them relies on internal details of memblock_reserve() implementation
> and the existing event sequence. If the code would move around relying on
> panic in memblock_reserve() may not be correct.
>
> And the few bytes and cycles the change saves do not worth the churn.

Makes sense to me.

But most early boot callers of memblock_reserve() don't check the
return value, so I thought we already rely on its internal behavior
anyway. So the few remaining checks just looked a bit inconsistent to
me.

Would you still prefer to keep these checks? If so, I'm fine with
dropping this patch series. It's not a big deal :)

Thank you for taking the time to review this series.

> --
> Sincerely yours,
> Mike.

Best Regards,
Sang-Heon Jeon


^ permalink raw reply

* Re: [PATCH v7 00/22] dma-mapping: Track shared DMA state through direct, pool and swiotlb paths
From: Marek Szyprowski @ 2026-07-07 13:03 UTC (permalink / raw)
  To: Aneesh Kumar K.V, iommu, linux-arm-kernel, linux-kernel,
	linux-coco
  Cc: Robin Murphy, Will Deacon, Marc Zyngier, Steven Price,
	Suzuki K Poulose, Catalin Marinas, Jiri Pirko, Jason Gunthorpe,
	Mostafa Saleh, Petr Tesarik, Alexey Kardashevskiy, Dan Williams,
	Xu Yilun, linuxppc-dev, linux-s390, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP),
	Alexander Gordeev, Gerald Schaefer, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Sven Schnelle, x86
In-Reply-To: <yq5av7argr65.fsf@kernel.org>

On 07.07.2026 10:06, Aneesh Kumar K.V wrote:
> "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org> writes:
>
>> This series tracks confidential-computing shared DMA state through the
>> dma-direct, dma-pool, and swiotlb paths so that encrypted and decrypted
>> DMA buffers are handled consistently.
>>
>> Today, the direct DMA path mostly relies on force_dma_unencrypted() for
>> shared/decrypted buffer handling. This series consolidates the
>> force_dma_unencrypted() checks in the top-level functions and ensures
>> that the remaining DMA interfaces use DMA attributes to make the correct
>> decisions.
>>
>> The series separates mapping and allocation state:
>> - DMA_ATTR_CC_SHARED describes the DMA address attribute requested for a
>>   mapping. It tells the DMA mapping path that the DMA address must target
>>   shared/decrypted memory.
>> - __DMA_ATTR_ALLOC_CC_SHARED is an internal DMA-mapping attribute used only
>>   by allocation paths after the DMA core decides that the backing pages
>>   must be allocated as shared/decrypted memory.
>>
>> The series:
>> - moves swiotlb-backed allocations out of __dma_direct_alloc_pages(),
>> - uses __DMA_ATTR_ALLOC_CC_SHARED through the dma-direct alloc/free paths
>> - teaches the atomic DMA pools to track encrypted versus decrypted
>>   state
>> - tracks swiotlb pool encryption state and enforces strict pool
>>   selection
>> - centralizes encrypted/decrypted pgprot handling in dma_pgprot() using
>>   DMA attributes
>> - passes DMA attributes down to dma_capable() so capability checks can
>>   validate whether the selected DMA address encoding matches
>>   DMA_ATTR_CC_SHARED
>> - makes dma_direct_map_phys() choose the DMA address encoding from
>>   DMA_ATTR_CC_SHARED and fall back to swiotlb when a shared DMA request
>>   cannot use the direct mapping, which lets arm64 and x86 CCA guests stop
>>   relying on SWIOTLB_FORCE for DMA mappings
>> - use the selected swiotlb pool state to derive the returned DMA
>>   address
>> - reports CC_ATTR_GUEST_MEM_ENCRYPT for arm64 Realms, powerpc secure
>>   guests, and s390 protected virtualization guests.
>>
>> Dependency:
>> This series depends on the pKVM changes posted at:
>> https://lore.kernel.org/all/20260603110522.3331819-1-smostafa@google.com
>>
>> Please merge this series only after the pKVM changes above are merged.
>> Otherwise pKVM will be broken.
>>
> A rebased tree on top of the dependent pKVM changes can be found at:
> https://gitlab.arm.com/linux-arm/linux-cca/-/tree/scratch/pkvm/testing?ref_type=heads
>
> The patches had minor conflicts. I am not sure how we want to get this
> merged.
>
> Should we ask the pKVM maintainers for a topic branch, and then I can
> repost the updated series on top of that?
I'm fine with merging on top of the topic branch and I assume that this
patchset is mature enough to give it a try in linux-next, but first I
would like to get a review or at least acks from others with good CC
knowledge or experience.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



^ permalink raw reply

* Re: [PATCH 00/42] of: reserved_mem: Introduce devres helpers and convert drivers
From: Liviu Dudau @ 2026-07-07 11:39 UTC (permalink / raw)
  To: Mukesh Ojha
  Cc: Bjorn Andersson, Konrad Dybcio, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Joel Stanley,
	Andrew Jeffery, Paul Cercueil, Anitha Chrisanthus,
	Paul Kocialkowski, Linus Walleij, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland, Alexey Brodkin, Laurent Pinchart, Tomi Valkeinen,
	Michal Simek, Daniel Scally, Jacopo Mondi, Mauro Carvalho Chehab,
	Eddie James, Tiffany Lin, Andrew-CT Chen, Yunfei Dong,
	Minghsiu Tsai, Houlong Wei, Matthias Brugger,
	AngeloGioacchino Del Regno, Joseph Liu, Marvin Lin,
	Dmitry Osipenko, Krzysztof Kozlowski, Thierry Reding,
	Jonathan Hunter, Srinivas Kandagatla, Arnd Bergmann,
	Greg Kroah-Hartman, Ge Gordon, Adrian Hunter, Ulf Hansson,
	Rob Herring, Saravana Kannan, Mathieu Poirier, Jaroslav Kysela,
	Takashi Iwai, Shengjiu Wang, Xiubo Li, Liam Girdwood, Mark Brown,
	Frank Li, Sascha Hauer, Peter Ujfalusi, Bard Liao, Daniel Baluta,
	Orson Zhai, Baolin Wang, Peter Chen, Fugang Duan, Ekansh Gupta,
	BST Linux Kernel Upstream Group, Fabio Estevam, Nicolin Chen,
	Pengutronix Kernel Team, Kai Vehmanen, Pierre-Louis Bossart,
	Vijendar Mukunda, Chunyan Zhang, CIX Linux Kernel Upstream Group,
	linux-arm-msm, linux-kernel, dri-devel, linux-aspeed,
	linux-arm-kernel, linux-mips, linux-sunxi, linux-media, openbmc,
	linux-mediatek, kernel, linux-tegra, linux-mmc, devicetree,
	linux-remoteproc, linux-staging, linux-sound, linuxppc-dev, imx,
	sound-open-firmware
In-Reply-To: <20260703193855.110619-1-mukesh.ojha@oss.qualcomm.com>

On Sat, Jul 04, 2026 at 01:08:13AM +0530, Mukesh Ojha wrote:
> Drivers using of_reserved_mem_device_init() and its variants must
> manually call of_reserved_mem_device_release() in their remove and
> error-unwind paths. This is repetitive boilerplate that is easy to
> get wrong, and several drivers have open-coded the teardown
> inconsistently or skipped it entirely, leading to dangling reserved
> memory references.
> 
> This series introduces devres-managed wrappers —
> devm_of_reserved_mem_device_init(), devm_of_reserved_mem_device_init_by_idx(),
> and devm_of_reserved_mem_device_init_by_name() — that tie the reserved
> memory region lifetime to the device, releasing it automatically on
> unbind. The remaining 40 patches convert drivers across the drm, media,
> ASoC, remoteproc, firmware, mmc, memory and misc subsystems to use these
> helpers, yielding a net reduction of ~90 lines of boilerplate.
> 
> This series depends on  https://lore.kernel.org/lkml/20260703164457.4040457-1-mukesh.ojha@oss.qualcomm.com/
> 
> Konrad Dybcio (1):
>   of: reserved_mem: Introduce devres-managed initialization functions
> 
> Mukesh Ojha (41):
>   of: reserved_mem: Add devm_of_reserved_mem_device_init_by_name()
>   firmware: qcom: scm: Use devm_of_reserved_mem_device_init()
>   remoteproc: da8xx: Use devm_of_reserved_mem_device_init()
>   remoteproc: keystone: Use devm_of_reserved_mem_device_init()
>   media: synopsys: hdmirx: Use devm_of_reserved_mem_device_init()
>   remoteproc: omap: Use devm_of_reserved_mem_device_init()
>   drm: logicvc: Use devm_of_reserved_mem_device_init()
>   drm: hdlcd: Use devm_of_reserved_mem_device_init()
>   drm: pl111: Use devm_of_reserved_mem_device_init()
>   remoteproc: mtk_scp: Use devm_of_reserved_mem_device_init()
>   media: aspeed: Use devm_of_reserved_mem_device_init()
>   media: nuvoton: npcm-video: Use devm_of_reserved_mem_device_init()
>   memory: tegra210-emc: Use devm_of_reserved_mem_device_init_by_name()
>   drm: komeda: Use devm_of_reserved_mem_device_init()
>   drm: malidp: Use devm_of_reserved_mem_device_init()

For the hdlcd, komeda and malidp drivers:

Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>

Best regards,
Liviu

>   drm: ingenic: Use devm_of_reserved_mem_device_init()
>   drm: kmb: Use devm_of_reserved_mem_device_init()
>   drm: sun4i: Use devm_of_reserved_mem_device_init()
>   drm: xlnx: zynqmp_dpsub: Use devm_of_reserved_mem_device_init()
>   media: arm: mali-c55: Use devm_of_reserved_mem_device_init()
>   media: mediatek: vpu: Use devm_of_reserved_mem_device_init()
>   mmc: sdhci-of-bst: Use devm_of_reserved_mem_device_init_by_idx()
>   remoteproc: ti_k3: Use devm_of_reserved_mem_device_init()
>   ASoC: mediatek: mt8192: Use devm_of_reserved_mem_device_init()
>   ASoC: mediatek: mt8196: Use devm_of_reserved_mem_device_init()
>   ASoC: mediatek: mt8183: Use devm_of_reserved_mem_device_init()
>   ASoC: mediatek: mt8189: Use devm_of_reserved_mem_device_init()
>   ASoC: SOF: imx: Use devm_of_reserved_mem_device_init_by_name()
>   staging: media: cedrus: Use devm_of_reserved_mem_device_init()
>   ASoC: cix-ipbloq: Use devm_of_reserved_mem_device_init()
>   drm: aspeed: Use devm_of_reserved_mem_device_init()
>   drm: arcpgu: Use devm_of_reserved_mem_device_init()
>   ASoC: mediatek: mt8173: Use devm_of_reserved_mem_device_init()
>   ASoC: mediatek: mt8186: Use devm_of_reserved_mem_device_init()
>   ASoC: mediatek: mt8188: Use devm_of_reserved_mem_device_init()
>   ASoC: mediatek: mt8195: Use devm_of_reserved_mem_device_init()
>   ASoC: SOF: mediatek: mt8186: Use devm_of_reserved_mem_device_init()
>   ASoC: SOF: mediatek: mt8195: Use devm_of_reserved_mem_device_init()
>   misc: fastrpc: Use devm_of_reserved_mem_device_init()
>   ASoC: fsl: imx-rpmsg: Use devm_of_reserved_mem_device_init_by_idx()
>   ASoC: sprd: Use devm_of_reserved_mem_device_init()
> 
>  drivers/firmware/qcom/qcom_scm.c              | 22 +++------
>  .../gpu/drm/arm/display/komeda/komeda_dev.c   |  4 +-
>  drivers/gpu/drm/arm/hdlcd_drv.c               |  6 +--
>  drivers/gpu/drm/arm/malidp_drv.c              |  4 +-
>  drivers/gpu/drm/aspeed/aspeed_gfx_drv.c       |  2 +-
>  drivers/gpu/drm/ingenic/ingenic-drm-drv.c     | 13 +-----
>  drivers/gpu/drm/kmb/kmb_drv.c                 | 12 +----
>  drivers/gpu/drm/logicvc/logicvc_drm.c         | 21 ++++-----
>  drivers/gpu/drm/pl111/pl111_drv.c             |  4 +-
>  drivers/gpu/drm/sun4i/sun4i_drv.c             |  4 +-
>  drivers/gpu/drm/tiny/arcpgu.c                 |  2 +-
>  drivers/gpu/drm/xlnx/zynqmp_dpsub.c           |  4 +-
>  .../platform/arm/mali-c55/mali-c55-core.c     | 12 ++---
>  drivers/media/platform/aspeed/aspeed-video.c  | 12 ++---
>  drivers/media/platform/mediatek/vpu/mtk_vpu.c |  3 +-
>  drivers/media/platform/nuvoton/npcm-video.c   |  9 +---
>  .../platform/synopsys/hdmirx/snps_hdmirx.c    | 16 +------
>  drivers/memory/tegra/tegra210-emc-core.c      | 21 ++++-----
>  drivers/misc/fastrpc.c                        |  2 +-
>  drivers/mmc/host/sdhci-of-bst.c               |  7 +--
>  drivers/of/of_reserved_mem.c                  | 41 +++++++++++++++++
>  drivers/remoteproc/da8xx_remoteproc.c         | 10 +---
>  drivers/remoteproc/keystone_remoteproc.c      | 16 +------
>  drivers/remoteproc/mtk_scp.c                  |  3 +-
>  drivers/remoteproc/omap_remoteproc.c          | 13 +-----
>  drivers/remoteproc/ti_k3_common.c             | 13 +-----
>  drivers/remoteproc/ti_k3_common.h             |  1 -
>  .../staging/media/sunxi/cedrus/cedrus_hw.c    |  6 +--
>  include/linux/of_reserved_mem.h               | 46 +++++++++++++++++++
>  sound/hda/controllers/cix-ipbloq.c            |  2 +-
>  sound/soc/fsl/imx-rpmsg.c                     |  2 +-
>  sound/soc/mediatek/mt8173/mt8173-afe-pcm.c    |  2 +-
>  sound/soc/mediatek/mt8183/mt8183-afe-pcm.c    | 13 +-----
>  sound/soc/mediatek/mt8186/mt8186-afe-pcm.c    |  2 +-
>  sound/soc/mediatek/mt8188/mt8188-afe-pcm.c    |  2 +-
>  sound/soc/mediatek/mt8189/mt8189-afe-pcm.c    | 16 +------
>  sound/soc/mediatek/mt8192/mt8192-afe-pcm.c    | 11 +----
>  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    |  2 +-
>  sound/soc/mediatek/mt8196/mt8196-afe-pcm.c    | 14 +-----
>  sound/soc/sof/imx/imx-common.c                |  9 ++--
>  sound/soc/sof/mediatek/mt8186/mt8186.c        |  2 +-
>  sound/soc/sof/mediatek/mt8195/mt8195.c        |  2 +-
>  sound/soc/sprd/sprd-pcm-dma.c                 |  3 +-
>  43 files changed, 162 insertions(+), 249 deletions(-)
> 
> -- 
> 2.53.0
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


^ permalink raw reply

* Re: [PATCH V16 4/7] rust/powerpc: Set min rustc version for powerpc
From: Link Mauve @ 2026-07-07 10:20 UTC (permalink / raw)
  To: Mukesh Kumar Chaurasiya
  Cc: Miguel Ojeda, maddy, mpe, npiggin, chleroy, peterz, jpoimboe,
	jbaron, aliceryhl, rostedt, ardb, ojeda, boqun, gary, bjorn3_gh,
	lossin, a.hindborg, tmgross, dakr, nathan, nick.desaulniers+lkml,
	morbo, justinstitt, daniel.almeida, acourbot, fujita.tomonori,
	gregkh, prafulrai522, tamird, kees, lyude, airlied, linuxppc-dev,
	linux-kernel, rust-for-linux, llvm
In-Reply-To: <akyiZBPCaZOOyTw6@li-1a3e774c-28e4-11b2-a85c-acc9f2883e29.ibm.com>

On Tue, Jul 07, 2026 at 12:41:37PM +0530, Mukesh Kumar Chaurasiya wrote:
> On Tue, Jun 30, 2026 at 11:15:03AM +0530, Mukesh Kumar Chaurasiya wrote:
> > On Mon, Jun 29, 2026 at 11:11:44AM +0200, Miguel Ojeda wrote:
> > > On Mon, Jun 29, 2026 at 6:57 AM Mukesh Kumar Chaurasiya
> > > <mkchauras@gmail.com> wrote:
> > > >
> > > > Sure i'll bisect. Meanwhile i would still like to get this upstream.
> > > 
> > > It is very early on the cycle -- I would suggest bisecting first.
> > > 
> > > But it is up to ppc, of course.
> > > 
> > > Cheers,
> > > Miguel
> Hey Miguel,
> 
> I was able to bisect this. This got fixed in 1.87 with
> #![feature(asm_experimental_arch)].

On 1.85.0 though, with this feature allowed, the kernel gets built
perfectly without any need for 1.87.0.  You might want to require 1.87.0
only with altivec enabled, whereas on 32-bit we can build on 1.85.0 just
fine.

> 
> 1st commit that contributed towards this is
> e4f539ea17a3 ("Bump to version 1.87.0")
> 
> This caused another issue to come up while building
> 
> ```
> error: extern blocks must be unsafe
>   --> /home/mkchauras/.local/rustc-src/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/src/powerpc/vsx.rs:38:1
>    |
> 38 | / extern "C" {
> 39 | |     #[link_name = "llvm.ppc.altivec.vperm"]
> 40 | |     fn vperm(
> 41 | |         a: vector_signed_int,
> ...  |
> 44 | |     ) -> vector_signed_int;
> 45 | | }
>    | |_^
> ```
> 
> Which is fixed by 
> a78d1b092c9c ("Update stdarch")
> 
> Both these commits went in 1.87.0 and fixed the build.
> 
> Regards,
> Mukesh
> 
> > Sure, I'll bisect it first.
> > 
> > Regards,
> > Mukesh
> 

-- 
Link Mauve


^ permalink raw reply

* Re: [PATCH 03/13] mm: convert __get_unmapped_area() to use vma_flags_t
From: Lorenzo Stoakes @ 2026-07-07 10:16 UTC (permalink / raw)
  To: Zi Yan
  Cc: Andrew Morton, Thomas Bogendoerfer, Madhavan Srinivasan,
	Michael Ellerman, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Lucas Stach,
	Inki Dae, Seung-Woo Kim, Kyungmin Park, Krzysztof Kozlowski,
	Peter Griffin, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Tvrtko Ursulin, Rob Clark, Dmitry Baryshkov, Lyude Paul,
	Danilo Krummrich, Tomi Valkeinen, Sandy Huang, Heiko Stübner,
	Andy Yan, Thierry Reding, Mikko Perttunen, Jonathan Hunter,
	Gerd Hoffmann, Dmitry Osipenko, Zack Rusin, Matthew Brost,
	Thomas Hellstrom, Oleksandr Andrushchenko, Helge Deller,
	Benjamin LaHaise, Alexander Viro, Christian Brauner, Muchun Song,
	Oscar Salvador, David Hildenbrand, Baolin Wang, Liam R . Howlett,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Hugh Dickins, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
	Michal Hocko, Jann Horn, Pedro Falcato, Kees Cook,
	Jaroslav Kysela, Takashi Iwai, linux-mips, linux-kernel,
	linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
	linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
	linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
	linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <DJRZGEZU5ESV.3IP5LEAUQJCBK@nvidia.com>

On Mon, Jul 06, 2026 at 10:28:24PM -0400, Zi Yan wrote:
> On Mon Jun 29, 2026 at 3:25 PM EDT, Lorenzo Stoakes wrote:
> > Update __get_unmapped_area() to be parameterised by vma_flags_t rather than
> > vm_flags_t as part of the effort to move VMA flags from a system word to a
> > bitmap.
> >
> > We cascade the changes up to arch_get_unmapped_area_topdown() and
> > arch_get_unmapped_area(), where, for now, we use vma_flags_to_legacy() in
> > order to propagate the VMA flags.
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> >  fs/hugetlbfs/inode.c     |  3 ++-
> >  include/linux/huge_mm.h  | 10 +++++-----
> >  include/linux/mm.h       |  6 ++++--
> >  include/linux/sched/mm.h | 12 ++++++------
> >  mm/huge_memory.c         | 21 ++++++++++++---------
> >  mm/mmap.c                | 27 ++++++++++++++-------------
> >  6 files changed, 43 insertions(+), 36 deletions(-)
> >
> <snip>
>
> > diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
> > index 95d0040df584..b301ec90740a 100644
> > --- a/include/linux/sched/mm.h
> > +++ b/include/linux/sched/mm.h
> > @@ -193,12 +193,12 @@ unsigned long mm_get_unmapped_area(struct file *filp, unsigned long addr,
> >  				   unsigned long len, unsigned long pgoff,
> >  				   unsigned long flags);
> >
> > -unsigned long mm_get_unmapped_area_vmflags(struct file *filp,
> > -					   unsigned long addr,
> > -					   unsigned long len,
> > -					   unsigned long pgoff,
> > -					   unsigned long flags,
> > -					   vm_flags_t vm_flags);
> > +unsigned long mm_get_unmapped_area_vmaflags(struct file *filp,
> > +					    unsigned long addr,
> > +					    unsigned long len,
> > +					    unsigned long pgoff,
> > +					    unsigned long flags,
> > +					    vma_flags_t vma_flags);
>
> Want to use two-tab indentation while at it?

Yeah sure will fix on respin!

>
> <snip>
>
> > @@ -812,19 +811,20 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
> >  }
> >  #endif
> >
> > -unsigned long mm_get_unmapped_area_vmflags(struct file *filp, unsigned long addr,
> > -					   unsigned long len, unsigned long pgoff,
> > -					   unsigned long flags, vm_flags_t vm_flags)
> > +unsigned long mm_get_unmapped_area_vmaflags(struct file *filp, unsigned long addr,
> > +					    unsigned long len, unsigned long pgoff,
> > +					    unsigned long flags, vma_flags_t vma_flags)
>
> Ditto.

Ack will fix!

>
> LGTM.
>
> Reviewed-by: Zi Yan <ziy@nvidia.com>

Thanks!

>
>
> --
> Best Regards,
> Yan, Zi
>

Cheers, Lorenzo


^ permalink raw reply

* Re: [PATCH 02/13] mm/vma: update do_mmap() to use vma_flags_t
From: Lorenzo Stoakes @ 2026-07-07 10:15 UTC (permalink / raw)
  To: Zi Yan
  Cc: Andrew Morton, Thomas Bogendoerfer, Madhavan Srinivasan,
	Michael Ellerman, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Lucas Stach,
	Inki Dae, Seung-Woo Kim, Kyungmin Park, Krzysztof Kozlowski,
	Peter Griffin, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Tvrtko Ursulin, Rob Clark, Dmitry Baryshkov, Lyude Paul,
	Danilo Krummrich, Tomi Valkeinen, Sandy Huang, Heiko Stübner,
	Andy Yan, Thierry Reding, Mikko Perttunen, Jonathan Hunter,
	Gerd Hoffmann, Dmitry Osipenko, Zack Rusin, Matthew Brost,
	Thomas Hellstrom, Oleksandr Andrushchenko, Helge Deller,
	Benjamin LaHaise, Alexander Viro, Christian Brauner, Muchun Song,
	Oscar Salvador, David Hildenbrand, Baolin Wang, Liam R . Howlett,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Hugh Dickins, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
	Michal Hocko, Jann Horn, Pedro Falcato, Kees Cook,
	Jaroslav Kysela, Takashi Iwai, linux-mips, linux-kernel,
	linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
	linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
	linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
	linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <DJRZ2QCEIVA6.1AZF5S891NKS4@nvidia.com>

On Mon, Jul 06, 2026 at 10:10:32PM -0400, Zi Yan wrote:
> On Mon Jun 29, 2026 at 3:25 PM EDT, Lorenzo Stoakes wrote:
> > The core do_mmap() function accepts a vm_flags_t parameter which it then
> > manipulates before passing to mmap_region() to do the heavy lifting of the
> > memory mapping.
> >
> > Update do_mmap() to instead accept a vma_flags_t parameter, and adjust all
> > the logic within do_mmap() to manipulate this instead.
> >
> > This is as part of the ongoing effort to convert VMA flags from a system
> > word size to a bitmap type which allows us to unrestrict the number of VMA
> > flags, as well as gain control over how VMA flag manipulation occurs.
> >
> > We do not cascade these changes to all functions which accept vm_flags_t,
> > but rather use vma_flags_to_legacy() where necessary, specifically
> > deferring converting calc_vm_prot_bits(), calc_vm_flag_bits() and
> > __get_unmapped_area() to vma_flags_t.
> >
> > Also utilise the new vma_flags_can_grow() predicate which correctly handles
> > the case of architectures without upward growing stacks.
> >
> > As part of this change, introduce VMA_SHADOW_STACK so we can correctly
> > handle the case of the shadow stack not being defined.
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> >  arch/mips/kernel/vdso.c |  4 +--
> >  fs/aio.c                |  2 +-
> >  include/linux/memfd.h   |  6 ++--
> >  include/linux/mm.h      |  6 ++--
> >  ipc/shm.c               |  3 +-
> >  mm/memfd.c              | 15 ++++-----
> >  mm/mmap.c               | 67 ++++++++++++++++++++++++-----------------
> >  mm/nommu.c              |  3 +-
> >  mm/util.c               | 10 +++---
> >  mm/vma.c                |  7 ++---
> >  mm/vma.h                |  2 +-
> >  11 files changed, 69 insertions(+), 56 deletions(-)
> >
>
> <snip>
>
> >
> > -static int check_write_seal(vm_flags_t *vm_flags_ptr)
> > +static int check_write_seal(vma_flags_t *vma_flags_ptr)
> >  {
> > -	vm_flags_t vm_flags = *vm_flags_ptr;
> > -	vm_flags_t mask = vm_flags & (VM_SHARED | VM_WRITE);
> > -
> >  	/* If a private mapping then writability is irrelevant. */
> > -	if (!(mask & VM_SHARED))
> > +	if (!vma_flags_test(vma_flags_ptr, VMA_SHARED_BIT))
> >  		return 0;
> >
> >  	/*
> >  	 * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
> >  	 * write seals are active.
> >  	 */
> > -	if (mask & VM_WRITE)
> > +	if (vma_flags_test(vma_flags_ptr, VMA_WRITE_BIT))
> >  		return -EPERM;
> >
> >  	/*
> >  	 * This is a read-only mapping, disallow mprotect() from making a
> >  	 * write-sealed mapping writable in future.
> >  	 */
> > -	*vm_flags_ptr &= ~VM_MAYWRITE;
> > +	vma_flags_clear(vma_flags_ptr, VMA_MAYWRITE_BIT);
> >
> >  	return 0;
> >  }
>
> This function alone changed its original behavior, since vm_flags is a
> snapshot of *vm_flags_ptr, but after the change this snapshot is gone.
> But its only caller memfd_check_seals_mmap() gets vm_flags_ptr from the
> input parameter of do_mmap(), so the overall behavior does not change.

Right yeah, the snapshot was always just a convenience thing :)

>
> <snip>
>
> > +		case MAP_DROPPABLE: {
> > +			vma_flags_t droppable = VMA_DROPPABLE;
> > +
> > +			if (vma_flags_empty(&droppable))
> >  				return -EOPNOTSUPP;
> > +			vma_flags_set_mask(&vma_flags, droppable);
> > +
> >  			/*
> >  			 * A locked or stack area makes no sense to be droppable.
> >  			 *
> > @@ -515,23 +527,24 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
> >  			 */
> >  			if (flags & (MAP_LOCKED | MAP_HUGETLB))
> >  			        return -EINVAL;
> > -			if (vm_flags & (VM_GROWSDOWN | VM_GROWSUP))
> > +			if (vma_flags_can_grow(&vma_flags))
> >  			        return -EINVAL;
> >
> > -			vm_flags |= VM_DROPPABLE;
> > -
>
> Lance pointed out the reordering of setting VMA_DROPPABLE and checking
> of can_grow, but these flags are not overlapped and there is no parallel
> writer to vma_flags. So it is still no functional change, just not
> mechanical changes. :)

Right yes exactly :)

>
> Otherwise, LGTM.
>
> Reviewed-by: Zi Yan <ziy@nvidia.com>

Thanks!

>
> --
> Best Regards,
> Yan, Zi
>

Cheers, Lorenzo


^ permalink raw reply

* [PATCH v4 net-next 14/14] net: enetc: use kzalloc_flex() for enetc_psfp_gate allocation
From: wei.fang @ 2026-07-07  8:18 UTC (permalink / raw)
  To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, linux, wei.fang, chleroy,
	maxime.chevallier
  Cc: imx, netdev, linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20260707081834.710730-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

Replace the open-coded struct_size() + kzalloc() pattern with the
kzalloc_flex() helper when allocating struct enetc_psfp_gate. This
removes the intermediate entries_size local variable and makes the
allocation site more concise.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc_qos.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
index 7b17bca24f26..2aa0fcaafcd2 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
@@ -1135,7 +1135,6 @@ static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv,
 	struct flow_action_entry *entry;
 	struct action_gate_entry *e;
 	u8 sfi_overwrite = 0;
-	int entries_size;
 	int i, err;
 
 	if (f->common.chain_index >= priv->psfp_cap.max_streamid) {
@@ -1242,8 +1241,7 @@ static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv,
 		goto free_filter;
 	}
 
-	entries_size = struct_size(sgi, entries, entryg->gate.num_entries);
-	sgi = kzalloc(entries_size, GFP_KERNEL);
+	sgi = kzalloc_flex(*sgi, entries, entryg->gate.num_entries);
 	if (!sgi) {
 		err = -ENOMEM;
 		goto free_filter;
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 net-next 13/14] net: enetc: use alloc_etherdev_mqs() to create netdev for VF driver
From: wei.fang @ 2026-07-07  8:18 UTC (permalink / raw)
  To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, linux, wei.fang, chleroy,
	maxime.chevallier
  Cc: imx, netdev, linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20260707081834.710730-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

The VF driver uses alloc_etherdev_mq() with ENETC_MAX_NUM_TXQS as the
queue count, which forces the TX and RX queue counts to be equal and
uses a compile-time constant rather than the actual hardware capability.

After enetc_get_si_caps() is called, si->num_tx_rings and
si->num_rx_rings reflect the actual number of rings assigned to the VF
by the PF. For the ENETC VF on LS1028A and the upcoming i.MX95/94, their
SoCs have no more than 6 CPUs, and the number of TX/RX rings allocated
to the VF is less than 8.

Therefore, switch to alloc_etherdev_mqs() so that the TX and RX queue
counts are set independently, each capped at ENETC_MAX_NUM_TXQS, based
on the actual number of rings assigned to the VF by the PF.

Note that if future SoCs have more than 6 CPUs and more than 6 RX rings
allocated to VFs, the size of the int_vector array in struct
enetc_ndev_priv will need to be modified. Similarly, if more than 8 TX
rings are allocated to each int_vector, ENETC_MAX_NUM_TXQS will also
need to be modified.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc_vf.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 9cdb0a4d6baf..7dcb4a0246f5 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -317,7 +317,14 @@ static int enetc_vf_probe(struct pci_dev *pdev,
 
 	enetc_get_si_caps(si);
 
-	ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS);
+	/* Currently, the supported SoCs have a max of 6 CPUs and the VFs
+	 * have less than 6 RX/TX rings. So no issues for these supported
+	 * SoCs, but for future SoCs which have more CPUs or more TX/RX
+	 * rings, all the related logic needs to be improved.
+	 */
+	ndev = alloc_etherdev_mqs(sizeof(*priv),
+				  min(si->num_tx_rings, ENETC_MAX_NUM_TXQS),
+				  min(si->num_rx_rings, ENETC_MAX_NUM_TXQS));
 	if (!ndev) {
 		err = -ENOMEM;
 		dev_err(&pdev->dev, "netdev creation failed\n");
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 net-next 12/14] net: enetc: remove redundant num_vsi field from enetc_port_caps
From: wei.fang @ 2026-07-07  8:18 UTC (permalink / raw)
  To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, linux, wei.fang, chleroy,
	maxime.chevallier
  Cc: imx, netdev, linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20260707081834.710730-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

The num_vsi field in struct enetc_port_caps is populated by reading the
NUM_VSI field of the ECAPR1 register, which reports the number of VSIs
supported by the ENETC4 port. When CONFIG_PCI_IOV is enabled, this value
always matches pf->total_vfs, which is obtained from the read-only
PCI_SRIOV_TOTAL_VF register via pci_sriov_get_totalvfs() during probe.
Both ECAPR1[NUM_VSI] and PCI_SRIOV_TOTAL_VF are derived from the same
IERB register EaVFRIDAR[NUM_VF] (a 4-bit field), so they are guaranteed
to be equal. When CONFIG_PCI_IOV is disabled, pci_sriov_get_totalvfs()
returns 0, but this is benign since pci_enable_sriov() is also stubbed
to return -ENODEV, so no VF can be created, and enetc4_enable_all_si()
only enables the PF SI (PSI).

Since pf->total_vfs already reflects the number of VFs that can actually
be used, and is the established convention in the sibling FSL_ENETC PF
driver, there is no need to read and cache num_vsi separately in the port
capabilities structure. Remove the num_vsi field from enetc_port_caps,
and replace all uses of pf->caps.num_vsi with pf->total_vfs in the ring
allocation, MSI-X configuration, SI enable, and debugfs code paths.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 .../ethernet/freescale/enetc/enetc4_debugfs.c | 13 ++-
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 86 ++++++++++++++-----
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  1 -
 3 files changed, 68 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
index be378bf8f74d..5029038bf99f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -28,17 +28,14 @@ static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
 
 static int enetc_mac_filter_show(struct seq_file *s, void *data)
 {
-	struct enetc_si *si = s->private;
-	struct enetc_hw *hw = &si->hw;
+	struct enetc_pf *pf = enetc_si_priv(s->private);
+	struct enetc_hw *hw = &pf->si->hw;
+	int num_si = pf->total_vfs + 1;
 	struct maft_entry_data maft;
 	struct ntmp_user *user;
-	struct enetc_pf *pf;
 	u32 val, entry_id;
-	int i, num_si;
 	int err = 0;
-
-	pf = enetc_si_priv(si);
-	num_si = pf->caps.num_vsi + 1;
+	int i;
 
 	val = enetc_port_rd(hw, ENETC4_PSIPMMR);
 	for (i = 0; i < num_si; i++) {
@@ -52,7 +49,7 @@ static int enetc_mac_filter_show(struct seq_file *s, void *data)
 	for (i = 0; i < num_si; i++)
 		enetc_show_si_mac_hash_filter(s, i);
 
-	user = &si->ntmp_user;
+	user = &pf->si->ntmp_user;
 	rtnl_lock();
 
 	if (bitmap_empty(user->maft_eid_bitmap, user->maft_num_entries))
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index cab79f81d6fe..fcfbabb29d22 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -23,7 +23,6 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
 	u32 val;
 
 	val = enetc_port_rd(hw, ENETC4_ECAPR1);
-	pf->caps.num_vsi = (val & ECAPR1_NUM_VSI) >> 24;
 	pf->caps.num_msix = ((val & ECAPR1_NUM_MSIX) >> 12) + 1;
 
 	val = enetc_port_rd(hw, ENETC4_ECAPR2);
@@ -255,34 +254,35 @@ static void enetc4_default_rings_allocation(struct enetc_pf *pf)
 {
 	struct enetc_hw *hw = &pf->si->hw;
 	u32 num_rx_bdr, num_tx_bdr, val;
+	int num_vfs = pf->total_vfs;
 	u32 vf_tx_bdr, vf_rx_bdr;
 	int i, rx_rem, tx_rem;
 
-	if (pf->caps.num_rx_bdr < ENETC_SI_MAX_RING_NUM + pf->caps.num_vsi)
-		num_rx_bdr = pf->caps.num_rx_bdr - pf->caps.num_vsi;
+	if (pf->caps.num_rx_bdr < ENETC_SI_MAX_RING_NUM + num_vfs)
+		num_rx_bdr = pf->caps.num_rx_bdr - num_vfs;
 	else
 		num_rx_bdr = ENETC_SI_MAX_RING_NUM;
 
-	if (pf->caps.num_tx_bdr < ENETC_SI_MAX_RING_NUM + pf->caps.num_vsi)
-		num_tx_bdr = pf->caps.num_tx_bdr - pf->caps.num_vsi;
+	if (pf->caps.num_tx_bdr < ENETC_SI_MAX_RING_NUM + num_vfs)
+		num_tx_bdr = pf->caps.num_tx_bdr - num_vfs;
 	else
 		num_tx_bdr = ENETC_SI_MAX_RING_NUM;
 
 	val = enetc4_psicfgr0_val_construct(false, num_tx_bdr, num_rx_bdr);
 	enetc_port_wr(hw, ENETC4_PSICFGR0(0), val);
 
-	if (!pf->caps.num_vsi)
+	if (!num_vfs)
 		return;
 
 	num_rx_bdr = pf->caps.num_rx_bdr - num_rx_bdr;
-	rx_rem = num_rx_bdr % pf->caps.num_vsi;
-	num_rx_bdr = num_rx_bdr / pf->caps.num_vsi;
+	rx_rem = num_rx_bdr % num_vfs;
+	num_rx_bdr = num_rx_bdr / num_vfs;
 
 	num_tx_bdr = pf->caps.num_tx_bdr - num_tx_bdr;
-	tx_rem = num_tx_bdr % pf->caps.num_vsi;
-	num_tx_bdr = num_tx_bdr / pf->caps.num_vsi;
+	tx_rem = num_tx_bdr % num_vfs;
+	num_tx_bdr = num_tx_bdr / num_vfs;
 
-	for (i = 0; i < pf->caps.num_vsi; i++) {
+	for (i = 0; i < num_vfs; i++) {
 		vf_tx_bdr = (i < tx_rem) ? num_tx_bdr + 1 : num_tx_bdr;
 		vf_rx_bdr = (i < rx_rem) ? num_rx_bdr + 1 : num_rx_bdr;
 		val = enetc4_psicfgr0_val_construct(true, vf_tx_bdr, vf_rx_bdr);
@@ -298,27 +298,67 @@ static void enetc4_allocate_si_rings(struct enetc_pf *pf)
 /* Allocate the number of MSI-X vectors for per SI. */
 static void enetc4_set_si_msix_num(struct enetc_pf *pf)
 {
+	int valid_num_si = pf->total_vfs + 1;
 	struct enetc_hw *hw = &pf->si->hw;
-	int i, num_msix, total_si;
+	int i, num_msix, num_vsi;
 	u32 val;
 
-	total_si = pf->caps.num_vsi + 1;
+	val = enetc_port_rd(hw, ENETC4_ECAPR1);
+	num_vsi = FIELD_GET(ECAPR1_NUM_VSI, val);
+
+	/* The PSIaCFGR2[NUM_MSIX] indicates the number of MSI-X allocated to
+	 * the SI is NUM_MSIX + 1, so the minimum number of MSI-X allocated to
+	 * each SI is 1. The total number of MSI-X allocated to PSI and VSIs
+	 * cannot exceed the total number of MSI-X owned by this ENETC, which
+	 * is ECAPR1[NUM_MSIX]. Otherwise, when multiple ENETC instances exist,
+	 * it will affect other ENETCs whose MSI-X interrupts cannot be
+	 * generated. This is similar to out-of-bounds array access: the array
+	 * itself is not affected, but adjacent arrays will be corrupted.
+	 *
+	 * pf->total_vfs is 0 if CONFIG_PCI_IOV is disabled. If the hardware
+	 * itself supports SR-IOV, then when allocating the number of MSIXs to
+	 * the SI, it must be taken into account that the VSI has at least 1
+	 * MSIX, and the total number of MSIXs of all SIs cannot exceed
+	 * ECAPR1[NUM_MSIX].
+	 */
+	if (!pf->total_vfs && num_vsi) {
+		/* Because each SI has at least one MSIX, and from the hardware
+		 * perspective, pf->caps.num_msix will always be greater than
+		 * num_vsi. So num_msix is always greater than or equal to 0.
+		 */
+		num_msix = pf->caps.num_msix - num_vsi - 1;
+		if (num_msix > PSICFGR2_NUM_MSIX)
+			num_msix = PSICFGR2_NUM_MSIX;
+		enetc_port_wr(hw, ENETC4_PSICFGR2(0), num_msix);
 
-	num_msix = pf->caps.num_msix / total_si +
-		   pf->caps.num_msix % total_si - 1;
-	val = num_msix & PSICFGR2_NUM_MSIX;
-	enetc_port_wr(hw, ENETC4_PSICFGR2(0), val);
+		for (i = 0; i < num_vsi; i++)
+			enetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), 0);
 
-	num_msix = pf->caps.num_msix / total_si - 1;
-	val = num_msix & PSICFGR2_NUM_MSIX;
-	for (i = 0; i < pf->caps.num_vsi; i++)
-		enetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), val);
+		return;
+	}
+
+	/* Likewise, from the hardware perspective pf->caps.num_msix is always
+	 * greater than valid_num_si. So num_msix is always greater than or
+	 * equal to 0.
+	 */
+	num_msix = pf->caps.num_msix / valid_num_si +
+		   pf->caps.num_msix % valid_num_si - 1;
+	if (num_msix > PSICFGR2_NUM_MSIX)
+		num_msix = PSICFGR2_NUM_MSIX;
+	enetc_port_wr(hw, ENETC4_PSICFGR2(0), num_msix);
+
+	num_msix = pf->caps.num_msix / valid_num_si - 1;
+	if (num_msix > PSICFGR2_NUM_MSIX)
+		num_msix = PSICFGR2_NUM_MSIX;
+
+	for (i = 0; i < pf->total_vfs; i++)
+		enetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), num_msix);
 }
 
 static void enetc4_enable_all_si(struct enetc_pf *pf)
 {
 	struct enetc_hw *hw = &pf->si->hw;
-	int num_si = pf->caps.num_vsi + 1;
+	int num_si = pf->total_vfs + 1;
 	u32 si_bitmap = 0;
 	int i;
 
@@ -339,7 +379,7 @@ static void enetc4_configure_port_si(struct enetc_pf *pf)
 	enetc_port_wr(hw, ENETC4_PSIVLANFMR, PSIVLANFMR_VS);
 
 	/* Enforce VLAN promiscuous mode for all SIs */
-	for (int i = 0; i < pf->caps.num_vsi + 1; i++)
+	for (int i = 0; i < pf->total_vfs + 1; i++)
 		enetc_set_si_vlan_promisc(pf->si, i, true);
 
 	/* Disable SI MAC multicast & unicast promiscuous */
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 1bd3063a3be3..56d23a8a11a0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -17,7 +17,6 @@ struct enetc_vf_state {
 };
 
 struct enetc_port_caps {
-	int num_vsi;
 	int num_msix;
 	int num_rx_bdr;
 	int num_tx_bdr;
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 net-next 11/14] net: enetc: move enetc_set_si_vlan_promisc() to enetc_pf_common.c
From: wei.fang @ 2026-07-07  8:18 UTC (permalink / raw)
  To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, linux, wei.fang, chleroy,
	maxime.chevallier
  Cc: imx, netdev, linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20260707081834.710730-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

The PSIPVMR in ENETC v4 has the same bit layout and functionality as the
PSIPVMR register in ENETC v1: bit n (n <= 15) controls VLAN promiscuous
mode for SI n. The only difference between the two hardware generations
is the register address offset.

Since the register functionality is identical, the VLAN promiscuous mode
setting code can be shared between ENETC v1 and v4 drivers.

Move enetc_set_si_vlan_promisc() from enetc_pf.c to enetc_pf_common.c
and export it so that it can be shared between the two drivers. Add a
revision check using is_enetc_rev1() to select the correct register
offset (ENETC_PSIPVMR for v1 and ENETC4_PSIPVMR for v4) while keeping
the same logic.

Remove the v4-specific enetc4_pf_set_si_vlan_promisc() from enetc4_pf.c
and replace its call site with the new common enetc_set_si_vlan_promisc()
to eliminate code duplication.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 17 ++------------
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 16 --------------
 .../freescale/enetc/enetc_pf_common.c         | 22 +++++++++++++++++++
 .../freescale/enetc/enetc_pf_common.h         |  1 +
 4 files changed, 25 insertions(+), 31 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 505e4abf6c37..cab79f81d6fe 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -295,18 +295,6 @@ static void enetc4_allocate_si_rings(struct enetc_pf *pf)
 	enetc4_default_rings_allocation(pf);
 }
 
-static void enetc4_pf_set_si_vlan_promisc(struct enetc_hw *hw, int si, bool en)
-{
-	u32 val = enetc_port_rd(hw, ENETC4_PSIPVMR);
-
-	if (en)
-		val |= BIT(si);
-	else
-		val &= ~BIT(si);
-
-	enetc_port_wr(hw, ENETC4_PSIPVMR, val);
-}
-
 /* Allocate the number of MSI-X vectors for per SI. */
 static void enetc4_set_si_msix_num(struct enetc_pf *pf)
 {
@@ -352,7 +340,7 @@ static void enetc4_configure_port_si(struct enetc_pf *pf)
 
 	/* Enforce VLAN promiscuous mode for all SIs */
 	for (int i = 0; i < pf->caps.num_vsi + 1; i++)
-		enetc4_pf_set_si_vlan_promisc(hw, i, true);
+		enetc_set_si_vlan_promisc(pf->si, i, true);
 
 	/* Disable SI MAC multicast & unicast promiscuous */
 	enetc_port_wr(hw, ENETC4_PSIPMMR, 0);
@@ -518,12 +506,11 @@ static int enetc4_pf_set_features(struct net_device *ndev,
 {
 	netdev_features_t changed = ndev->features ^ features;
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct enetc_hw *hw = &priv->si->hw;
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
 		bool promisc_en = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
 
-		enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
+		enetc_set_si_vlan_promisc(priv->si, 0, promisc_en);
 	}
 
 	if (changed & NETIF_F_LOOPBACK)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index afc02ed62c77..a509929f89f2 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -42,22 +42,6 @@ static void enetc_pf_destroy_pcs(struct phylink_pcs *pcs)
 	lynx_pcs_destroy(pcs);
 }
 
-static void enetc_set_si_vlan_promisc(struct enetc_si *si, int si_id,
-				      bool promisc)
-{
-	struct enetc_hw *hw = &si->hw;
-	u32 val;
-
-	val = enetc_port_rd(hw, ENETC_PSIPVMR);
-
-	if (promisc)
-		val |= PSIPVMR_SI_VLAN_P(si_id);
-	else
-		val &= ~PSIPVMR_SI_VLAN_P(si_id);
-
-	enetc_port_wr(hw, ENETC_PSIPVMR, val);
-}
-
 static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos)
 {
 	u32 val = 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 781b22198ca8..d32a195a04c9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -171,6 +171,28 @@ void enetc_set_si_mc_hash_filter(struct enetc_si *si, int si_id, u64 hash)
 }
 EXPORT_SYMBOL_GPL(enetc_set_si_mc_hash_filter);
 
+void enetc_set_si_vlan_promisc(struct enetc_si *si, int si_id, bool promisc)
+{
+	struct enetc_hw *hw = &si->hw;
+	int psipvmr_off;
+	u32 val;
+
+	if (is_enetc_rev1(si))
+		psipvmr_off = ENETC_PSIPVMR;
+	else
+		psipvmr_off = ENETC4_PSIPVMR;
+
+	val = enetc_port_rd(hw, psipvmr_off);
+
+	if (promisc)
+		val |= PSIPVMR_SI_VLAN_P(si_id);
+	else
+		val &= ~PSIPVMR_SI_VLAN_P(si_id);
+
+	enetc_port_wr(hw, psipvmr_off, val);
+}
+EXPORT_SYMBOL_GPL(enetc_set_si_vlan_promisc);
+
 void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 			   const struct net_device_ops *ndev_ops)
 {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
index bf9029b0a017..8243ce0de57f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
@@ -21,6 +21,7 @@ void enetc_set_si_uc_promisc(struct enetc_si *si, int si_id, bool promisc);
 void enetc_set_si_mc_promisc(struct enetc_si *si, int si_id, bool promisc);
 void enetc_set_si_uc_hash_filter(struct enetc_si *si, int si_id, u64 hash);
 void enetc_set_si_mc_hash_filter(struct enetc_si *si, int si_id, u64 hash);
+void enetc_set_si_vlan_promisc(struct enetc_si *si, int si_id, bool promisc);
 
 static inline u16 enetc_get_ip_revision(struct enetc_hw *hw)
 {
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 net-next 10/14] net: enetc: refactor SI VLAN promiscuous mode configuration
From: wei.fang @ 2026-07-07  8:18 UTC (permalink / raw)
  To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, linux, wei.fang, chleroy,
	maxime.chevallier
  Cc: imx, netdev, linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20260707081834.710730-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

Remove the enetc_set_vlan_promisc(), enetc_enable_si_vlan_promisc() and
enetc_disable_si_vlan_promisc() functions, and introduce a new unified
function enetc_set_si_vlan_promisc() to enable or disable VLAN
promiscuous mode for a specific SI. This simplifies the logic and makes
the interface more straightforward. The vlan_promisc_simap field in
struct enetc_pf is no longer needed to track the current state.

As ENETC V4 only changes the address offset of PSIPVMR register compared
to V1 without any functional difference, enetc_set_si_vlan_promisc() can
be moved to enetc_pf_common.c in the future with minor adjustments to be
reused by the ENETC V4 driver

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 .../net/ethernet/freescale/enetc/enetc_hw.h   |  5 ++-
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 36 ++++++++-----------
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  1 -
 3 files changed, 16 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index 66bfda60da9c..16da732dc5de 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -185,9 +185,8 @@ enum enetc_bdr_type {TX, RX};
 #define  PSIPMMR_SI_MAC_MP(n)	BIT((n) + 16)
 
 #define ENETC_PSIPVMR		0x001c
-#define ENETC_VLAN_PROMISC_MAP_ALL	0x7
-#define ENETC_PSIPVMR_SET_VP(simap)	((simap) & 0x7)
-#define ENETC_PSIPVMR_SET_VUTA(simap)	(((simap) & 0x7) << 16)
+#define  PSIPVMR_SI_VLAN_P(n)	BIT(n) /* n = SI index */
+
 #define ENETC_PSIPMAR0(n)	(0x0100 + (n) * 0x8) /* n = SI index */
 #define ENETC_PSIPMAR1(n)	(0x0104 + (n) * 0x8)
 #define ENETC_PVCLCTR		0x0208
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index db2a800a7aaf..afc02ed62c77 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -42,24 +42,20 @@ static void enetc_pf_destroy_pcs(struct phylink_pcs *pcs)
 	lynx_pcs_destroy(pcs);
 }
 
-static void enetc_set_vlan_promisc(struct enetc_hw *hw, char si_map)
+static void enetc_set_si_vlan_promisc(struct enetc_si *si, int si_id,
+				      bool promisc)
 {
-	u32 val = enetc_port_rd(hw, ENETC_PSIPVMR);
+	struct enetc_hw *hw = &si->hw;
+	u32 val;
 
-	val &= ~ENETC_PSIPVMR_SET_VP(ENETC_VLAN_PROMISC_MAP_ALL);
-	enetc_port_wr(hw, ENETC_PSIPVMR, ENETC_PSIPVMR_SET_VP(si_map) | val);
-}
+	val = enetc_port_rd(hw, ENETC_PSIPVMR);
 
-static void enetc_enable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)
-{
-	pf->vlan_promisc_simap |= BIT(si_idx);
-	enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap);
-}
+	if (promisc)
+		val |= PSIPVMR_SI_VLAN_P(si_id);
+	else
+		val &= ~PSIPVMR_SI_VLAN_P(si_id);
 
-static void enetc_disable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)
-{
-	pf->vlan_promisc_simap &= ~BIT(si_idx);
-	enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap);
+	enetc_port_wr(hw, ENETC_PSIPVMR, val);
 }
 
 static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos)
@@ -441,10 +437,9 @@ static void enetc_configure_port(struct enetc_pf *pf)
 
 	/* split up RFS entries */
 	enetc_port_assign_rfs_entries(pf->si);
-
 	/* enforce VLAN promisc mode for all SIs */
-	pf->vlan_promisc_simap = ENETC_VLAN_PROMISC_MAP_ALL;
-	enetc_set_vlan_promisc(hw, pf->vlan_promisc_simap);
+	for (int i = 0; i < pf->total_vfs + 1; i++)
+		enetc_set_si_vlan_promisc(pf->si, i, true);
 
 	enetc_port_wr(hw, ENETC_PSIPMMR, 0);
 
@@ -466,12 +461,9 @@ static int enetc_pf_set_features(struct net_device *ndev,
 	}
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
-		struct enetc_pf *pf = enetc_si_priv(priv->si);
+		bool promisc = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
 
-		if (!!(features & NETIF_F_HW_VLAN_CTAG_FILTER))
-			enetc_disable_si_vlan_promisc(pf, 0);
-		else
-			enetc_enable_si_vlan_promisc(pf, 0);
+		enetc_set_si_vlan_promisc(priv->si, 0, promisc);
 	}
 
 	if (changed & NETIF_F_LOOPBACK)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 7e886dc49997..1bd3063a3be3 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -45,7 +45,6 @@ struct enetc_pf {
 	struct work_struct msg_task;
 	char msg_int_name[ENETC_INT_NAME_MAX];
 
-	char vlan_promisc_simap; /* bitmap of SIs in VLAN promisc mode */
 	DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
 	DECLARE_BITMAP(active_vlans, VLAN_N_VID);
 
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 net-next 09/14] net: enetc: open-code enetc4_set_default_si_vlan_promisc()
From: wei.fang @ 2026-07-07  8:18 UTC (permalink / raw)
  To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, linux, wei.fang, chleroy,
	maxime.chevallier
  Cc: imx, netdev, linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20260707081834.710730-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

The function enetc4_set_default_si_vlan_promisc() is only called once,
from enetc4_configure_port_si(). Open-code the loop at the call site
and remove the single-use wrapper.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc4_pf.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 859b02f5170a..505e4abf6c37 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -307,17 +307,6 @@ static void enetc4_pf_set_si_vlan_promisc(struct enetc_hw *hw, int si, bool en)
 	enetc_port_wr(hw, ENETC4_PSIPVMR, val);
 }
 
-static void enetc4_set_default_si_vlan_promisc(struct enetc_pf *pf)
-{
-	struct enetc_hw *hw = &pf->si->hw;
-	int num_si = pf->caps.num_vsi + 1;
-	int i;
-
-	/* enforce VLAN promiscuous mode for all SIs */
-	for (i = 0; i < num_si; i++)
-		enetc4_pf_set_si_vlan_promisc(hw, i, true);
-}
-
 /* Allocate the number of MSI-X vectors for per SI. */
 static void enetc4_set_si_msix_num(struct enetc_pf *pf)
 {
@@ -361,7 +350,9 @@ static void enetc4_configure_port_si(struct enetc_pf *pf)
 	/* Outer VLAN tag will be used for VLAN filtering */
 	enetc_port_wr(hw, ENETC4_PSIVLANFMR, PSIVLANFMR_VS);
 
-	enetc4_set_default_si_vlan_promisc(pf);
+	/* Enforce VLAN promiscuous mode for all SIs */
+	for (int i = 0; i < pf->caps.num_vsi + 1; i++)
+		enetc4_pf_set_si_vlan_promisc(hw, i, true);
 
 	/* Disable SI MAC multicast & unicast promiscuous */
 	enetc_port_wr(hw, ENETC4_PSIPMMR, 0);
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 net-next 08/14] net: enetc: remove invalid code from enetc4_pl_mac_link_up()
From: wei.fang @ 2026-07-07  8:18 UTC (permalink / raw)
  To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, linux, wei.fang, chleroy,
	maxime.chevallier
  Cc: imx, netdev, linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20260707081834.710730-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

When adding phylink MAC operations support to the NETC switch driver,
Russell King pointed out several pieces of invalid logic in the
.mac_link_up() implementation (see [1] and [2]):

1) Half-duplex backpressure is not supported by the kernel, Ethernet
   relies on packet dropping for congestion management.

2) phylink_autoneg_inband() is unnecessary, as RGMII in-band status is
   not supported.

3) TX and RX pause are disabled in half-duplex mode, so there is no
   need to override them in .mac_link_up().

The same invalid logic is also present in enetc4_pl_mac_link_up(), so
remove the invalid code from it.

Given enetc4_set_hd_flow_control() is removed, pf->caps.half_duplex has
also become useless and should therefore be removed as well.

Link: https://lore.kernel.org/imx/acEIQqI-_oyCym8O@shell.armlinux.org.uk/ # 1
Link: https://lore.kernel.org/imx/acEFwqmAvWls_9Ef@shell.armlinux.org.uk/ # 2
Signed-off-by: Wei Fang <wei.fang@nxp.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  2 -
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 38 +------------------
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  1 -
 3 files changed, 1 insertion(+), 40 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index dea1fd0b8175..09025e7a2a3a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -135,7 +135,6 @@
 #define ENETC4_PSIVHFR1(a)		((a) * 0x80 + 0x2064)
 
 #define ENETC4_PMCAPR			0x4004
-#define  PMCAPR_HD			BIT(8)
 #define  PMCAPR_FP			GENMASK(10, 9)
 
 /* Port capability register */
@@ -198,7 +197,6 @@
 #define  PM_CMD_CFG_CNT_FRM_EN		BIT(13)
 #define  PM_CMD_CFG_TXP			BIT(15)
 #define  PM_CMD_CFG_SEND_IDLE		BIT(16)
-#define  PM_CMD_CFG_HD_FCEN		BIT(18)
 #define  PM_CMD_CFG_SFD			BIT(21)
 #define  PM_CMD_CFG_TX_FLUSH		BIT(22)
 #define  PM_CMD_CFG_TX_LOWP_EN		BIT(23)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 75ee117e9b1d..859b02f5170a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -29,9 +29,6 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
 	val = enetc_port_rd(hw, ENETC4_ECAPR2);
 	pf->caps.num_rx_bdr = (val & ECAPR2_NUM_RX_BDR) >> 16;
 	pf->caps.num_tx_bdr = val & ECAPR2_NUM_TX_BDR;
-
-	val = enetc_port_rd(hw, ENETC4_PMCAPR);
-	pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
 }
 
 static void enetc4_get_psi_hw_features(struct enetc_si *si)
@@ -588,11 +585,6 @@ static void enetc4_mac_config(struct enetc_pf *pf, unsigned int mode,
 	case PHY_INTERFACE_MODE_RGMII_RXID:
 	case PHY_INTERFACE_MODE_RGMII_TXID:
 		val |= IFMODE_RGMII;
-		/* We need to enable auto-negotiation for the MAC
-		 * if its RGMII interface support In-Band status.
-		 */
-		if (phylink_autoneg_inband(mode))
-			val |= PM_IF_MODE_ENA;
 		break;
 	case PHY_INTERFACE_MODE_RMII:
 		val |= IFMODE_RMII;
@@ -695,22 +687,6 @@ static void enetc4_set_rmii_mac(struct enetc_pf *pf, int speed, int duplex)
 	enetc_port_mac_wr(si, ENETC4_PM_IF_MODE(0), val);
 }
 
-static void enetc4_set_hd_flow_control(struct enetc_pf *pf, bool enable)
-{
-	struct enetc_si *si = pf->si;
-	u32 old_val, val;
-
-	if (!pf->caps.half_duplex)
-		return;
-
-	old_val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
-	val = u32_replace_bits(old_val, enable ? 1 : 0, PM_CMD_CFG_HD_FCEN);
-	if (val == old_val)
-		return;
-
-	enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
-}
-
 static void enetc4_set_rx_pause(struct enetc_pf *pf, bool rx_pause)
 {
 	struct enetc_si *si = pf->si;
@@ -886,13 +862,11 @@ static void enetc4_pl_mac_link_up(struct phylink_config *config,
 	struct enetc_pf *pf = phylink_to_enetc_pf(config);
 	struct enetc_si *si = pf->si;
 	struct enetc_ndev_priv *priv;
-	bool hd_fc = false;
 
 	priv = netdev_priv(si->ndev);
 	enetc4_set_port_speed(priv, speed);
 
-	if (!phylink_autoneg_inband(mode) &&
-	    phy_interface_mode_is_rgmii(interface))
+	if (phy_interface_mode_is_rgmii(interface))
 		enetc4_set_rgmii_mac(pf, speed, duplex);
 
 	if (interface == PHY_INTERFACE_MODE_RMII)
@@ -904,18 +878,8 @@ static void enetc4_pl_mac_link_up(struct phylink_config *config,
 		 */
 		if (priv->active_offloads & ENETC_F_QBU)
 			tx_pause = false;
-	} else { /* DUPLEX_HALF */
-		if (tx_pause || rx_pause)
-			hd_fc = true;
-
-		/* As per 802.3 annex 31B, PAUSE frames are only supported
-		 * when the link is configured for full duplex operation.
-		 */
-		tx_pause = false;
-		rx_pause = false;
 	}
 
-	enetc4_set_hd_flow_control(pf, hd_fc);
 	enetc4_set_tx_pause(pf, priv->num_rx_rings, tx_pause);
 	enetc4_set_rx_pause(pf, rx_pause);
 	enetc4_mac_tx_enable(pf);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index 6f15f9ea1664..7e886dc49997 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -17,7 +17,6 @@ struct enetc_vf_state {
 };
 
 struct enetc_port_caps {
-	u32 half_duplex:1;
 	int num_vsi;
 	int num_msix;
 	int num_rx_bdr;
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 net-next 07/14] net: enetc: differentiate phylink capabilities for pseudo-MAC and standalone MAC
From: wei.fang @ 2026-07-07  8:18 UTC (permalink / raw)
  To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, linux, wei.fang, chleroy,
	maxime.chevallier
  Cc: imx, netdev, linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20260707081834.710730-1-wei.fang@oss.nxp.com>

From: Claudiu Manoil <claudiu.manoil@nxp.com>

The ENETC pseudo-MACs are proprietary internal links that do not
implement any standard MII interface, so restrict their supported PHY
interface modes to PHY_INTERFACE_MODE_INTERNAL only.

Since pseudo-MACs can operate at any speed between 10Mbps and 25Gbps
in multiples of 10Mbps, set their MAC capabilities to cover the full
range of standard full-duplex speeds: 10/100/1000/2500/5000/10000/
20000/25000 Mbps.

For standalone ENETC (v4), expand the supported interface modes to
include 10GBASER in addition to the existing RGMII, SGMII, 1000BASEX,
2500BASEX and USXGMII modes, with MAC capabilities up to 10G. MAC_1000
is replaced with MAC_1000FD to explicitly exclude 1000M half-duplex,
which is not supported.

Note that 10GBASE-R mode of ENETC v4 has not supported yet, the current
patch adds PHY_INTERFACE_MODE_10GBASER simply as preparation for the
upcoming support of the 10GBASE-R mode.

Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Signed-off-by: Wei Fang <wei.fang@nxp.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +-
 .../net/ethernet/freescale/enetc/enetc4_pf.c  |  1 -
 .../freescale/enetc/enetc_pf_common.c         | 44 +++++++++++++------
 3 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 06a9f1ee0970..8839cfb49bcf 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-/* Copyright 2017-2019 NXP */
+/* Copyright 2017-2019, 2025-2026 NXP */
 
 #include <linux/timer.h>
 #include <linux/pci.h>
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index f24269a48c26..75ee117e9b1d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -602,7 +602,6 @@ static void enetc4_mac_config(struct enetc_pf *pf, unsigned int mode,
 		val |= IFMODE_SGMII;
 		break;
 	case PHY_INTERFACE_MODE_10GBASER:
-	case PHY_INTERFACE_MODE_XGMII:
 	case PHY_INTERFACE_MODE_USXGMII:
 		val |= IFMODE_XGMII;
 		break;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 3597cb81a7cc..781b22198ca8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/* Copyright 2024 NXP */
+/* Copyright 2024-2026 NXP */
 
 #include <linux/fsl/enetc_mdio.h>
 #include <linux/of_mdio.h>
@@ -359,7 +359,8 @@ static bool enetc_port_has_pcs(struct enetc_pf *pf)
 	return (pf->if_mode == PHY_INTERFACE_MODE_SGMII ||
 		pf->if_mode == PHY_INTERFACE_MODE_1000BASEX ||
 		pf->if_mode == PHY_INTERFACE_MODE_2500BASEX ||
-		pf->if_mode == PHY_INTERFACE_MODE_USXGMII);
+		pf->if_mode == PHY_INTERFACE_MODE_USXGMII ||
+		pf->if_mode == PHY_INTERFACE_MODE_10GBASER);
 }
 
 int enetc_mdiobus_create(struct enetc_pf *pf, struct device_node *node)
@@ -400,25 +401,42 @@ int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node,
 {
 	struct enetc_pf *pf = enetc_si_priv(priv->si);
 	struct phylink *phylink;
+	unsigned long mac_caps;
 	int err;
 
 	pf->phylink_config.dev = &priv->ndev->dev;
 	pf->phylink_config.type = PHYLINK_NETDEV;
-	pf->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
-		MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
 
 	__set_bit(PHY_INTERFACE_MODE_INTERNAL,
 		  pf->phylink_config.supported_interfaces);
-	__set_bit(PHY_INTERFACE_MODE_SGMII,
-		  pf->phylink_config.supported_interfaces);
-	__set_bit(PHY_INTERFACE_MODE_1000BASEX,
-		  pf->phylink_config.supported_interfaces);
-	__set_bit(PHY_INTERFACE_MODE_2500BASEX,
-		  pf->phylink_config.supported_interfaces);
-	__set_bit(PHY_INTERFACE_MODE_USXGMII,
-		  pf->phylink_config.supported_interfaces);
-	phy_interface_set_rgmii(pf->phylink_config.supported_interfaces);
 
+	mac_caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
+	if (!enetc_is_pseudo_mac(priv->si)) {
+		mac_caps |= MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD;
+
+		__set_bit(PHY_INTERFACE_MODE_SGMII,
+			  pf->phylink_config.supported_interfaces);
+		__set_bit(PHY_INTERFACE_MODE_1000BASEX,
+			  pf->phylink_config.supported_interfaces);
+		__set_bit(PHY_INTERFACE_MODE_2500BASEX,
+			  pf->phylink_config.supported_interfaces);
+		__set_bit(PHY_INTERFACE_MODE_USXGMII,
+			  pf->phylink_config.supported_interfaces);
+
+		if (!is_enetc_rev1(priv->si)) {
+			mac_caps |= MAC_5000FD | MAC_10000FD;
+			__set_bit(PHY_INTERFACE_MODE_10GBASER,
+				  pf->phylink_config.supported_interfaces);
+		}
+
+		phy_interface_set_rgmii(pf->phylink_config.supported_interfaces);
+	} else {
+		mac_caps |= MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD |
+			    MAC_5000FD | MAC_10000FD | MAC_20000FD |
+			    MAC_25000FD;
+	}
+
+	pf->phylink_config.mac_capabilities = mac_caps;
 	phylink = phylink_create(&pf->phylink_config, of_fwnode_handle(node),
 				 pf->if_mode, ops);
 	if (IS_ERR(phylink)) {
-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 net-next 06/14] net: enetc: simplify enetc4_set_port_speed()
From: wei.fang @ 2026-07-07  8:18 UTC (permalink / raw)
  To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, linux, wei.fang, chleroy,
	maxime.chevallier
  Cc: imx, netdev, linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20260707081834.710730-1-wei.fang@oss.nxp.com>

From: Wei Fang <wei.fang@nxp.com>

Since phylink may pass SPEED_UNKNOWN to mac_link_up, handle it
explicitly by defaulting to SPEED_10, then replace the switch statement
with a direct call to PCR_PSPEED_VAL(). Also update PCR_PSPEED_VAL() to
use FIELD_PREP() for proper field masking instead of an open-coded shift.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  2 +-
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 25 +++++++------------
 2 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 6a8f2ed56017..dea1fd0b8175 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -148,7 +148,7 @@
 #define  PCR_L2DOSE			BIT(4)
 #define  PCR_TIMER_CS			BIT(8)
 #define  PCR_PSPEED			GENMASK(29, 16)
-#define  PCR_PSPEED_VAL(speed)		(((speed) / 10 - 1) << 16)
+#define  PCR_PSPEED_VAL(s)		FIELD_PREP(PCR_PSPEED, ((s) / 10 - 1))
 
 /* Port MAC address register 0/1 */
 #define ENETC4_PMAR0			0x4020
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index b966637572a7..f24269a48c26 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -628,26 +628,19 @@ static void enetc4_set_port_speed(struct enetc_ndev_priv *priv, int speed)
 	u32 old_speed = priv->speed;
 	u32 val;
 
+	/* If the speed is unknown, use the minimum value */
+	if (speed == SPEED_UNKNOWN) {
+		speed = SPEED_10;
+		dev_warn(priv->dev, "Speed unknown, default is 10Mbps\n");
+	}
+
 	if (speed == old_speed)
 		return;
 
-	val = enetc_port_rd(&priv->si->hw, ENETC4_PCR);
-	val &= ~PCR_PSPEED;
-
-	switch (speed) {
-	case SPEED_100:
-	case SPEED_1000:
-	case SPEED_2500:
-	case SPEED_10000:
-		val |= (PCR_PSPEED & PCR_PSPEED_VAL(speed));
-		break;
-	case SPEED_10:
-	default:
-		val |= (PCR_PSPEED & PCR_PSPEED_VAL(SPEED_10));
-	}
-
-	priv->speed = speed;
+	val = enetc_port_rd(&priv->si->hw, ENETC4_PCR) & (~PCR_PSPEED);
+	val |= PCR_PSPEED_VAL(speed);
 	enetc_port_wr(&priv->si->hw, ENETC4_PCR, val);
+	priv->speed = speed;
 }
 
 static void enetc4_set_rgmii_mac(struct enetc_pf *pf, int speed, int duplex)
-- 
2.34.1



^ 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