Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] ARM: footbridge: convert to sparse IRQs
From: Dmitry Torokhov @ 2026-06-10 17:03 UTC (permalink / raw)
  To: Ethan Nelson-Moore
  Cc: Arnd Bergmann, linux-arm-kernel, linux-input, linux-serial,
	Russell King, Greg Kroah-Hartman, Jiri Slaby, Russell King,
	Linus Walleij, Kees Cook, Nathan Chancellor,
	Sebastian Andrzej Siewior, Steven Rostedt, Thomas Weißschuh,
	Peter Zijlstra
In-Reply-To: <CADkSEUhh1NdOMTHVsErhqzyCpDGFA-FkNFaWp94e9LnB3njxqw@mail.gmail.com>

On Mon, Jun 08, 2026 at 10:13:50AM -0700, Ethan Nelson-Moore wrote:
> Hi, Arnd,
> 
> On Mon, Jun 8, 2026 at 10:11 AM Arnd Bergmann <arnd@arndb.de> wrote:
> > I think this is correct, as footbridge is the only one that selects
> > CONFIG_ARCH_MIGHT_HAVE_PC_SERIO and defines I8042_KBD_IRQ on arm.
> 
> I came to the same conclusion.

I see. In this case:

Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> # for input

Thanks.

-- 
Dmitry


^ permalink raw reply

* Re: [PATCH] Bluetooth: hci_bcm4377: Use named initializers for pci_device_id array
From: Uwe Kleine-König (The Capable Hub) @ 2026-06-10 16:59 UTC (permalink / raw)
  To: Sven Peter, Janne Grunau, Neal Gompa, Marcel Holtmann,
	Luiz Augusto von Dentz
  Cc: Markus Schneider-Pargmann, asahi, linux-arm-kernel,
	linux-bluetooth, linux-kernel
In-Reply-To: <20260504160940.2168650-2-u.kleine-koenig@baylibre.com>

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

On Mon, May 04, 2026 at 06:09:40PM +0200, Uwe Kleine-König (The Capable Hub) wrote:
> Initializing a struct using list initializers is hard to read, compared
> to that using named initializers is more ideomatic. Convert the macro
> used to assign values in the driver's pci_device_id array accordingly.
> 
> This change doesn't introduce any changes to the compiled array on an
> x86 and an arm64 build.
> 
> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
> ---
> Hello,
> 
> this is a preparing change for making struct pci_device_id::driver_data an
> anonymous union (similar to
> https://lore.kernel.org/all/cover.1776579304.git.u.kleine-koenig@baylibre.com/).
> This requires named initializers for .driver_data. But even without that
> this is a nice cleanup making the macro better readable.
> 
> Gcc is happy with simplifying the assignment further using
> PCI_VDEVICE(BROADCOM, BCM ## id ## _DEVICE_ID), but this is a bit fishy
> because PCI_VDEVICE also assigns .class and .class_mask (using list
> initializers), so I didn't convert that.

In the meantime I learned that doing that would break W=1 builds, so it
was a good choice to not go that path.

> Once all pci_device_id use
> named initializers, the two zeros can be dropped from PCI_VDEVICE and
> this entry simplified accordingly.

Is this patch still on someone's radar? Ideally for application in time
for 7.2-rc1?

Best regards
Uwe

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

^ permalink raw reply

* [PATCH v3] arm64: errata: Workaround NVIDIA Olympus device store/load ordering erratum
From: Shanker Donthineni @ 2026-06-10 16:48 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Vladimir Murzin
  Cc: Jason Gunthorpe, linux-arm-kernel, Mark Rutland, linux-kernel,
	linux-doc, Shanker Donthineni, Vikram Sethi, Jason Sequeira

On systems with NVIDIA Olympus cores, a Device-nGnR* load can be
observed by a peripheral before an older, non-overlapping Device-nGnR*
store to the same peripheral. This breaks the program-order guarantee
that software expects for Device-nGnR* accesses and can leave a
peripheral in an incorrect state, as a load is observed before an
earlier store takes effect.

The erratum can occur only when all of the following apply:

  - A PE executes a Device-nGnR* store followed by a younger
    Device-nGnR* load.
  - The store is not a store-release.
  - The accesses target the same peripheral and do not overlap in bytes.
  - There is at most one intervening Device-nGnR* store in program
    order, and there are no intervening Device-nGnR* loads.
  - There is no DSB, and no DMB that orders loads, between the store and
    the load.
  - Specific micro-architectural and timing conditions occur.

Promote the raw MMIO store helpers (__raw_writeb/w/l/q) from plain str*
to stlr* (Store-Release), which removes the "store is not a
store-release" condition for every device write the kernel issues.
Because writel() and writel_relaxed() are both built on __raw_writel()
in asm-generic/io.h, patching the raw variants covers both the
non-relaxed and relaxed APIs without touching the higher layers. Note
that writel()'s own barrier sits before the store, so it does not order
the store against a subsequent readl(); the store-release promotion is
what provides that ordering.

Like ARM64_ERRATUM_832075 on the load side, the change is gated on a new
ARM64_WORKAROUND_DEVICE_STORE_RELEASE capability and only activated on
parts that match MIDR_NVIDIA_OLYMPUS, so unaffected CPUs continue to use
the plain str* sequence.

Note: stlr* only supports base-register addressing, so affected CPUs use
a base-register stlr* path. Unaffected CPUs keep the original
offset-addressed str* sequence introduced by commit d044d6ba6f02
("arm64: io: permit offset addressing").

The __const_memcpy_toio_aligned32() and __const_memcpy_toio_aligned64()
helpers are left unchanged. These helpers are intended for
write-combining mappings, which are Normal-NC on arm64. Replacing their
contiguous str* groups would defeat the write-combining behavior used to
improve store performance.

Co-developed-by: Vikram Sethi <vsethi@nvidia.com>
Signed-off-by: Vikram Sethi <vsethi@nvidia.com>
Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
---
Changes since v2:
  - Reworked the raw MMIO write helpers so unaffected CPUs keep the
    existing offset-addressed STR sequence, while affected CPUs use the
    base-register STLR path.
  - Updated the commit message to match the code changes.
  - Rebased on top of the arm64 for-next/errata branch:
    https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=for-next/errata

Changes since v1:
  - Updated the commit message based on feedback from Vladimir Murzin.

 Documentation/arch/arm64/silicon-errata.rst |  2 ++
 arch/arm64/Kconfig                          | 23 ++++++++++++++++
 arch/arm64/include/asm/io.h                 | 30 +++++++++++++++++++++
 arch/arm64/kernel/cpu_errata.c              |  8 ++++++
 arch/arm64/tools/cpucaps                    |  1 +
 5 files changed, 64 insertions(+)

diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index ad09bbb10da80..fc45125dc2f80 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -298,6 +298,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | NVIDIA         | Carmel Core     | N/A             | NVIDIA_CARMEL_CNP_ERRATUM   |
 +----------------+-----------------+-----------------+-----------------------------+
+| NVIDIA         | Olympus core    | T410-OLY-1027   | NVIDIA_OLYMPUS_1027_ERRATUM |
++----------------+-----------------+-----------------+-----------------------------+
 | NVIDIA         | Olympus core    | T410-OLY-1029   | ARM64_ERRATUM_4118414       |
 +----------------+-----------------+-----------------+-----------------------------+
 | NVIDIA         | T241 GICv3/4.x  | T241-FABRIC-4   | N/A                         |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c65cef81be86a..d633eb70de1ac 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -564,6 +564,29 @@ config ARM64_ERRATUM_832075
 
 	  If unsure, say Y.
 
+config NVIDIA_OLYMPUS_1027_ERRATUM
+	bool "NVIDIA Olympus: device store/load ordering erratum"
+	default y
+	help
+	  This option adds an alternative code sequence to work around an
+	  NVIDIA Olympus core erratum where a Device-nGnR* store can be
+	  observed by a peripheral after a younger Device-nGnR* load to the
+	  same peripheral. This breaks the program order that drivers rely
+	  on for MMIO and can leave a device in an incorrect state.
+
+	  The workaround promotes the raw MMIO store helpers
+	  (__raw_writeb/w/l/q) to Store-Release (STLR), which restores the
+	  required ordering. Because writel() and writel_relaxed() are built
+	  on __raw_writel(), both are covered without changes to the higher
+	  layers.
+
+	  The fix is applied through the alternatives framework, so enabling
+	  this option does not by itself activate the workaround: it is
+	  patched in only when an affected CPU is detected, and is a no-op on
+	  unaffected CPUs.
+
+	  If unsure, say Y.
+
 config ARM64_ERRATUM_834220
 	bool "Cortex-A57: 834220: Stage 2 translation fault might be incorrectly reported in presence of a Stage 1 fault (rare)"
 	depends on KVM
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 8cbd1e96fd50b..801223e754c90 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -22,10 +22,22 @@
 /*
  * Generic IO read/write.  These perform native-endian accesses.
  */
+static __always_inline bool arm64_needs_device_store_release(void)
+{
+	return alternative_has_cap_unlikely(
+				ARM64_WORKAROUND_DEVICE_STORE_RELEASE);
+}
+
 #define __raw_writeb __raw_writeb
 static __always_inline void __raw_writeb(u8 val, volatile void __iomem *addr)
 {
 	volatile u8 __iomem *ptr = addr;
+
+	if (arm64_needs_device_store_release()) {
+		asm volatile("stlrb %w0, [%1]" : : "rZ" (val), "r" (addr));
+		return;
+	}
+
 	asm volatile("strb %w0, %1" : : "rZ" (val), "Qo" (*ptr));
 }
 
@@ -33,6 +45,12 @@ static __always_inline void __raw_writeb(u8 val, volatile void __iomem *addr)
 static __always_inline void __raw_writew(u16 val, volatile void __iomem *addr)
 {
 	volatile u16 __iomem *ptr = addr;
+
+	if (arm64_needs_device_store_release()) {
+		asm volatile("stlrh %w0, [%1]" : : "rZ" (val), "r" (addr));
+		return;
+	}
+
 	asm volatile("strh %w0, %1" : : "rZ" (val), "Qo" (*ptr));
 }
 
@@ -40,6 +58,12 @@ static __always_inline void __raw_writew(u16 val, volatile void __iomem *addr)
 static __always_inline void __raw_writel(u32 val, volatile void __iomem *addr)
 {
 	volatile u32 __iomem *ptr = addr;
+
+	if (arm64_needs_device_store_release()) {
+		asm volatile("stlr %w0, [%1]" : : "rZ" (val), "r" (addr));
+		return;
+	}
+
 	asm volatile("str %w0, %1" : : "rZ" (val), "Qo" (*ptr));
 }
 
@@ -47,6 +71,12 @@ static __always_inline void __raw_writel(u32 val, volatile void __iomem *addr)
 static __always_inline void __raw_writeq(u64 val, volatile void __iomem *addr)
 {
 	volatile u64 __iomem *ptr = addr;
+
+	if (arm64_needs_device_store_release()) {
+		asm volatile("stlr %x0, [%1]" : : "rZ" (val), "r" (addr));
+		return;
+	}
+
 	asm volatile("str %x0, %1" : : "rZ" (val), "Qo" (*ptr));
 }
 
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index d597896b0f7f3..b096d9acca578 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -838,6 +838,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
 	},
 #endif
+#ifdef CONFIG_NVIDIA_OLYMPUS_1027_ERRATUM
+	{
+		/* NVIDIA Olympus core */
+		.desc = "NVIDIA Olympus device load/store ordering erratum",
+		.capability = ARM64_WORKAROUND_DEVICE_STORE_RELEASE,
+		ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
+	},
+#endif
 #ifdef CONFIG_ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
 	{
 		/*
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 811c2479e82d6..d367257bf7703 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -120,6 +120,7 @@ WORKAROUND_CAVIUM_TX2_219_PRFM
 WORKAROUND_CAVIUM_TX2_219_TVM
 WORKAROUND_CLEAN_CACHE
 WORKAROUND_DEVICE_LOAD_ACQUIRE
+WORKAROUND_DEVICE_STORE_RELEASE
 WORKAROUND_NVIDIA_CARMEL_CNP
 WORKAROUND_PMUV3_IMPDEF_TRAPS
 WORKAROUND_QCOM_FALKOR_E1003
-- 
2.43.0



^ permalink raw reply related

* Re: [PATCH 2/2] ufs: mediatek: Implement get_hba_nortt callback for RTT capability
From: Bart Van Assche @ 2026-06-10 16:46 UTC (permalink / raw)
  To: ed.tsai, alim.akhtar, avri.altman, James.Bottomley,
	martin.petersen, linux-scsi
  Cc: linux-kernel, linux-arm-kernel, linux-mediatek, wsd_upstream,
	peter.wang, alice.chao, naomi.chu, chun-hung.wu
In-Reply-To: <20260609103856.676222-3-ed.tsai@mediatek.com>

On 6/9/26 3:38 AM, ed.tsai@mediatek.com wrote:
> Implement the get_hba_nortt callback to handle platform-specific RTT
> capability differences:

Reviewed-by: Bart Van Assche <bvanassche@acm.org>



^ permalink raw reply

* Re: [PATCH 1/2] ufs: core: Add get_hba_nortt callback for vendor-specific RTT capability
From: Bart Van Assche @ 2026-06-10 16:46 UTC (permalink / raw)
  To: ed.tsai, alim.akhtar, avri.altman, James.Bottomley,
	martin.petersen, linux-scsi
  Cc: linux-kernel, linux-arm-kernel, linux-mediatek, wsd_upstream,
	peter.wang, alice.chao, naomi.chu, chun-hung.wu
In-Reply-To: <20260609103856.676222-2-ed.tsai@mediatek.com>

On 6/9/26 3:38 AM, ed.tsai@mediatek.com wrote:
> diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
> index cfbc75d8df83..13d0d7798294 100644
> --- a/include/ufs/ufshcd.h
> +++ b/include/ufs/ufshcd.h
> @@ -370,7 +370,6 @@ struct ufshcd_tx_eq_params {
>   /**
>    * struct ufs_hba_variant_ops - variant specific callbacks
>    * @name: variant name
> - * @max_num_rtt: maximum RTT supported by the host
>    * @init: called when the driver is initialized
>    * @exit: called to cleanup everything done in init
>    * @set_dma_mask: For setting another DMA mask than indicated by the 64AS
> @@ -415,10 +414,11 @@ struct ufshcd_tx_eq_params {
>    * @get_rx_fom: called to get Figure of Merit (FOM) value.
>    * @tx_eqtr_notify: called before and after TX Equalization Training procedure
>    *	to allow platform vendor specific configs to take place.
> + * @get_hba_nortt: called to get maximum number of outstanding RTTs supported by
> + *	the controller.
>    */
>   struct ufs_hba_variant_ops {
>   	const char *name;
> -	int	max_num_rtt;
>   	int	(*init)(struct ufs_hba *);
>   	void    (*exit)(struct ufs_hba *);
>   	u32	(*get_ufs_hci_version)(struct ufs_hba *);
> @@ -477,6 +477,7 @@ struct ufs_hba_variant_ops {
>   	int	(*tx_eqtr_notify)(struct ufs_hba *hba,
>   				  enum ufs_notify_change_status status,
>   				  struct ufs_pa_layer_attr *pwr_mode);
> +	int	(*get_hba_nortt)(struct ufs_hba *hba);
>   };

A patch series should be bisectable. Removing max_num_rtt from struct
ufs_hba_variant_ops before the code is removed from the MediaTek driver
that sets that variable introduces a build break. Please keep
'max_num_rtt' in this patch and add a third patch to this series that
removes 'max_num_rtt'.

Thanks,

Bart.


^ permalink raw reply

* Re: [PATCH v2 1/2] dt-bindings: arm: rockchip: Add HINLINK H28K
From: Conor Dooley @ 2026-06-10 16:43 UTC (permalink / raw)
  To: Chukun Pan
  Cc: Heiko Stuebner, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	linux-arm-kernel, linux-rockchip, linux-kernel, devicetree
In-Reply-To: <20260610100006.366963-2-amadeus@jmu.edu.cn>

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

Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable

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

^ permalink raw reply

* Re: [PATCH v6 04/20] dma-pool: track decrypted atomic pools and select them via attrs
From: Jason Gunthorpe @ 2026-06-10 16:41 UTC (permalink / raw)
  To: Aneesh Kumar K.V
  Cc: iommu, linux-arm-kernel, linux-kernel, linux-coco, Robin Murphy,
	Marek Szyprowski, Will Deacon, Marc Zyngier, Steven Price,
	Suzuki K Poulose, Catalin Marinas, Jiri Pirko, 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, Jiri Pirko,
	Michael Kelley
In-Reply-To: <yq5afr2uzum9.fsf@kernel.org>

On Wed, Jun 10, 2026 at 01:37:26PM +0530, Aneesh Kumar K.V wrote:
> Jason Gunthorpe <jgg@ziepe.ca> writes:
> 
> > On Thu, Jun 04, 2026 at 02:09:43PM +0530, Aneesh Kumar K.V (Arm) wrote:
> >>  struct page *dma_alloc_from_pool(struct device *dev, size_t size,
> >> -		void **cpu_addr, gfp_t gfp,
> >> +		void **cpu_addr, gfp_t gfp, unsigned long attrs,
> >>  		bool (*phys_addr_ok)(struct device *, phys_addr_t, size_t))
> >>  {
> >> -	struct gen_pool *pool = NULL;
> >> +	struct dma_gen_pool *dma_pool = NULL;
> >>  	struct page *page;
> >>  	bool pool_found = false;
> >>  
> >> -	while ((pool = dma_guess_pool(pool, gfp))) {
> >> +	while ((dma_pool = dma_guess_pool(dma_pool, gfp))) {
> >> +
> >> +		if (dma_pool->unencrypted != !!(attrs & DMA_ATTR_CC_SHARED))
> >> +			continue;
> >
> > I don't think you should be overloading DMA_ATTR_CC_SHARED like this.
> >
> > 	/*
> > 	 * DMA_ATTR_CC_SHARED is not a caller-visible dma_alloc_*()
> > 	 * attribute. The direct allocator uses it internally after it has
> > 	 * decided that the backing pages must be shared/decrypted, so the
> > 	 * rest of the allocation path can consistently select DMA addresses,
> > 	 * choose compatible pools and restore encryption on free.
> > 	 */
> > 	if (attrs & DMA_ATTR_CC_SHARED)
> > 		return NULL;
> >
> > 	if (force_dma_unencrypted(dev)) {
> > 		attrs |= DMA_ATTR_CC_SHARED;
> > 		mark_mem_decrypt = true;
> > 	}
> >
> > It is fine to have a bit inside the attrs that is only used by the
> > internal logic, but it needs to have a clearer name
> > __DMA_ATTR_REQUIRE_CC_SHARED perhaps.
> >
> 
> Are you suggesting adding another attribute in addition to
> DMA_ATTR_CC_SHARED?
> 
> Is the idea that __DMA_ATTR_REQUIRE_CC_SHARED would be used in the
> allocation path to request a CC_SHARED allocation, while
> DMA_ATTR_CC_SHARED would be used in the mapping path to describe the
> attribute of the address?

Yeah, it is a thought at least

Maybe a comment is good enough.

I just find it hard to follow when we have this dual usage. Like the
code above for dma_pool->unencrypted is completely wrong if it is an
"attribute of an address". Easy to cut & paste that into the wrong
context.

Especially if you move things up higher.. having the alloc set both
CC_SHARED and REQUIRE_CC_SHARED or maybe ALLOC_CC_SHARED would make it
clearer that the alloc code lives under that callchain

Jason


^ permalink raw reply

* Re: [PATCH] KVM: arm64: Hold kvm->mmu_lock while initialising vcpu->arch.vncr_tlb
From: Yosry Ahmed @ 2026-06-10 16:39 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: kvmarm, kvm, linux-arm-kernel, Steffen Eiden, Joey Gouly,
	Suzuki K Poulose, Oliver Upton, Zenghui Yu
In-Reply-To: <868q8mu0hr.wl-maz@kernel.org>

On Wed, Jun 10, 2026 at 3:57 AM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 09 Jun 2026 18:57:26 +0100,
> Yosry Ahmed <yosry@kernel.org> wrote:
> >
> > > > If yes, I think the code looks confusing, at least to a layman like
> > > > myself. It initially seems like the lock protects against concurrent
> > > > initializations, but then the NULL check is not done again under the
> > > > lock. The goal of the lock is not clear without the original report.
> > > >
> > > > Mayeb it's clearer to explicitly use barriers if the goal is preventing
> > > > reordering?
> > >
> > > This would require both the initialisation of vncr_tlb to use a store
> > > release, *and* all the other call sites to use a load acquire.
> > >
> > > I really don't think it is worth the churn, nor the (very small)
> > > burden on the readers.
> >
> > That's fair. I was mainly just pointing out my initial confusion and
> > that others may share it. Avoiding the churn on the readers' side is
> > understandable. Maybe a comment here would help explain why the lock
> > needs to be held?
>
> I have added this:
>
>         /*
>          * Taking the lock on assignment ensures that the TLB is
>          * seen as initialised when following the pointer (release
>          * semantics of the unlock), and avoids having acquires on
>          * each user which already take the lock.
>          */

Looks good, thank you!


^ permalink raw reply

* Re: [PATCH 2/3] dt-bindings: arm: rockchip: Add Youyeetoo YY3588
From: Conor Dooley @ 2026-06-10 16:33 UTC (permalink / raw)
  To: Daniele Briguglio
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	devicetree, linux-kernel, linux-arm-kernel, linux-rockchip
In-Reply-To: <20260610-yy3588-board-v1-2-4bb7176b6826@superkali.me>

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

Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable

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

^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: vendor-prefixes: Add youyeetoo
From: Conor Dooley @ 2026-06-10 16:33 UTC (permalink / raw)
  To: Daniele Briguglio
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	devicetree, linux-kernel, linux-arm-kernel, linux-rockchip
In-Reply-To: <20260610-yy3588-board-v1-1-4bb7176b6826@superkali.me>

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

Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable

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

^ permalink raw reply

* Re: [PATCH] ASoC: meson: axg-tdm-formatter: Use guard() for mutex locks
From: Bui Duc Phuc @ 2026-06-10 16:27 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Mark Brown, Liam Girdwood, Neil Armstrong, Kevin Hilman,
	Martin Blumenstingl, Jaroslav Kysela, Takashi Iwai, linux-sound,
	linux-arm-kernel, linux-amlogic, linux-kernel
In-Reply-To: <1j8q8mfte7.fsf@starbuckisacylon.baylibre.com>

Hi Jerome,

Thank you for your feedback,

>
> I suppose it is OK but it does not seem to really clean anything and
> make the code easier to follow in that instance, from my perspective at
> least.
>
> If there is policy to systematically use guard() whenever
> possible then OK, otherwise it seems unnecessary.
>

I have noticed that guard() has been adopted in several subsystems.
Since this appears to be the only place in the Meson ASoC code currently using
mutex_lock()/mutex_unlock(), I converted it for consistency with the
newer style.

Going forward, should new Meson ASoC code use guard(), or should it continue
using the traditional mutex_lock()/mutex_unlock() pattern?

Best regards,
Phuc


^ permalink raw reply

* [PATCH 5.10] spi: meson-spicc: Fix double-put in remove path
From: Alexey Panov @ 2026-06-10 16:11 UTC (permalink / raw)
  To: stable, Greg Kroah-Hartman
  Cc: Alexey Panov, Mark Brown, Kevin Hilman, Neil Armstrong,
	Jerome Brunet, Martin Blumenstingl, Dongliang Mu, linux-spi,
	linux-arm-kernel, linux-amlogic, linux-kernel, Neil Armstrong,
	lvc-project, Felix Gu, Johan Hovold

From: Felix Gu <ustc.gu@gmail.com>

commit 63542bb402b7013171c9f621c28b609eda4dbf1f upstream.

meson_spicc_probe() registers the controller with
devm_spi_register_controller(), so teardown already drops the
controller reference via devm cleanup.

Calling spi_controller_put() again in meson_spicc_remove()
causes a double-put.

Fixes: 8311ee2164c5 ("spi: meson-spicc: fix memory leak in meson_spicc_remove")
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
Reviewed-by: Johan Hovold <johan@kernel.org>
Link: https://patch.msgid.link/20260322-rockchip-v1-1-fac3f0c6dad8@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
[ Alexey: Remove the equivalent legacy spi_master_put() call used in
  linux-5.10.y. ]
Signed-off-by: Alexey Panov <apanov@astralinux.ru>
---
Backport fix for CVE-2026-31489
 drivers/spi/spi-meson-spicc.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
index 6974a1c947aa..ae818e7df791 100644
--- a/drivers/spi/spi-meson-spicc.c
+++ b/drivers/spi/spi-meson-spicc.c
@@ -863,8 +863,6 @@ static int meson_spicc_remove(struct platform_device *pdev)
 	clk_disable_unprepare(spicc->core);
 	clk_disable_unprepare(spicc->pclk);
 
-	spi_master_put(spicc->master);
-
 	return 0;
 }
 
-- 
2.47.3


^ permalink raw reply related

* Re: [PATCH v2] arm64: errata: Workaround NVIDIA Olympus device store/load ordering erratum
From: Jason Gunthorpe @ 2026-06-10 16:11 UTC (permalink / raw)
  To: Shanker Donthineni
  Cc: Will Deacon, Catalin Marinas, linux-arm-kernel, Vladimir Murzin,
	Mark Rutland, linux-kernel, linux-doc, Vikram Sethi,
	Jason Sequeira
In-Reply-To: <223c49ee-528c-4750-9885-fd8e0247151e@nvidia.com>

On Wed, Jun 10, 2026 at 08:20:28AM -0500, Shanker Donthineni wrote:

> Based on the existing code comments and after reviewing this path again,
> __const_memcpy_toio_aligned32() and __const_memcpy_toio_aligned64()
> appear to be intended for WC regions. Since the erratum is scoped to
> Device-nGnR* accesses, and WC mappings are Normal-NC on arm64, I don’t
> think the STLR workaround should apply to these helpers by default.

Hmm, unfortunately I think the APIs mix together IO and WC both as
__iomem things. However I recall when I was looking a this everyone
was using it for WC.

Jason


^ permalink raw reply

* Re: [PATCH] KVM: arm64: vgic: Check the interrupt is still ours before migrating it
From: Marc Zyngier @ 2026-06-10 16:00 UTC (permalink / raw)
  To: Hyunwoo Kim
  Cc: Oliver Upton, joey.gouly, seiden, suzuki.poulose, yuzenghui,
	catalin.marinas, will, Sascha.Bischoff, jic23, timothy.hayes,
	andre.przywara, linux-arm-kernel, kvmarm
In-Reply-To: <ailsCnyoS82r_QRz@v4bel>

On Wed, 10 Jun 2026 14:52:10 +0100,
Hyunwoo Kim <imv4bel@gmail.com> wrote:
> 
> On Fri, Jun 05, 2026 at 01:43:32AM -0700, Oliver Upton wrote:
> > On Fri, Jun 05, 2026 at 08:42:52AM +0100, Marc Zyngier wrote:
> > > On Fri, 05 Jun 2026 07:00:37 +0100,
> > > Oliver Upton <oupton@kernel.org> wrote:
> > > > 
> > > > On Fri, Jun 05, 2026 at 05:59:15AM +0900, Hyunwoo Kim wrote:
> > > > > vgic_prune_ap_list() drops both ap_list_lock and irq_lock while migrating
> > > > > an interrupt to another vCPU. After reacquiring the locks it only checks
> > > > > that the affinity is unchanged (target_vcpu == vgic_target_oracle(irq))
> > > > > before moving the interrupt, which assumes that an interrupt whose affinity
> > > > > is preserved is still queued on this vCPU's ap_list.
> > > > > 
> > > > > That assumption no longer holds if the interrupt is taken off the ap_list
> > > > > while the locks are dropped. vgic_flush_pending_lpis() removes the
> > > > > interrupt from the list and sets irq->vcpu to NULL, but leaves
> > > > > enabled/pending/target_vcpu untouched. As the interrupt is still enabled
> > > > > and pending, vgic_target_oracle() returns the same target_vcpu, so the
> > > > > affinity check passes and list_del() is run a second time on an entry that
> > > > > has already been removed.
> > > > > 
> > > > > Also check that the interrupt is still assigned to this vCPU
> > > > > (irq->vcpu == vcpu) before moving it.
> > > > > 
> > > > > Fixes: 0919e84c0fc1 ("KVM: arm/arm64: vgic-new: Add IRQ sync/flush framework")
> > > > > Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
> > > > 
> > > > Looking at this and the other VGIC patch you sent (which should've been
> > > > a combined series), are you trying to deal with a vCPU writing to
> > > > another vCPU's redistributor? I.e. vCPU B setting GICR_CTLR.EnableLPIs=0
> > > > behind the back of vCPU A?
> > > > 
> > > > That is extremely relevant information as the off-the-cuff reaction is
> > > > that no race exists. But since the GIC architecture is awesome and
> > > > allows for this sort of insanity, it obviously does....
> > > > 
> > > > Anyway, for LPIs resident on a particular RD, there's zero expectation
> > > > that the pending state is preserved when EnableLPIs=0. So I'd rather
> > > > vgic_flush_pending_lpis() just invalidate the pending state.
> > > 
> > > Just clearing the pending state introduces a potential problem as we
> > > now have an interrupt that is neither active nor pending on the AP
> > > list. It is not impossible to solve (we now have similar behaviours
> > > with SPI deactivation from another vcpu), but that requires posting a
> > > KVM_REQ_VGIC_PROCESS_UPDATE to the target vcpu.
> > 
> > Right, I was suggesting that in addition to deleting the LPI from the AP
> > list we actually invalidate the pending state so that someone sitting on
> > a pointer to a to-be-freed LPI sees vgic_target_oracle() returning
> > NULL
> > 
> > > > Beyond that, I see two other fixes for lifetime issues around the
> > > > vgic_irq in the middle of migration. I'd like to see explicit RCU
> > > > protection around the release && reacquire of the ap_list_lock rather
> > > > than depending on the precondition that IRQs are disabled.
> > > 
> > > I'm not sure I follow. Are you suggesting turning the AP list into an
> > > RCU protected list?
> > 
> > No, sorry, I should expand a little.
> > 
> > We store a reference on the vgic_irq struct in the AP list, which is
> > stable so long as the ap_list_lock is held. It should be possible for
> > the refcount to drop to 0 between releasing the ap_list_lock and
> > reacquiring it.
> > 
> > So either vgic_prune_ap_list() takes an additional reference on the
> > vgic_irq before dropping the ap_list_lock or rely on RCU to protect
> > vgic_irq structs observed with a non-zero refcount.
> 
> What are your thoughts on this approach?
> 
> 
> Best regards,
> Hyunwoo Kim
> 
> ---
> 
> diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
> index 933983bb2005..7fb871c3ccd8 100644
> --- a/arch/arm64/kvm/vgic/vgic-init.c
> +++ b/arch/arm64/kvm/vgic/vgic-init.c
> @@ -523,7 +523,7 @@ static void __kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
>  	 * Retire all pending LPIs on this vcpu anyway as we're
>  	 * going to destroy it.
>  	 */
> -	vgic_flush_pending_lpis(vcpu);
> +	vgic_flush_pending_lpis(vcpu, true);
> 
>  	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
>  	kfree(vgic_cpu->private_irqs);
> diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
> index 5913a20d8301..f85d63f17af0 100644
> --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
> +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
> @@ -303,7 +303,7 @@ static void vgic_mmio_write_v3r_ctlr(struct kvm_vcpu *vcpu,
>  		if (ctlr != GICR_CTLR_ENABLE_LPIS)
>  			return;
> 
> -		vgic_flush_pending_lpis(vcpu);
> +		vgic_flush_pending_lpis(vcpu, false);
>  		vgic_its_invalidate_all_caches(vcpu->kvm);
>  		atomic_set_release(&vgic_cpu->ctlr, 0);
>  	} else {
> diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
> index 1e9fe8764584..09629a38fc0a 100644
> --- a/arch/arm64/kvm/vgic/vgic.c
> +++ b/arch/arm64/kvm/vgic/vgic.c
> @@ -192,7 +192,7 @@ static void vgic_release_deleted_lpis(struct kvm *kvm)
>  	xa_unlock_irqrestore(&dist->lpi_xa, flags);
>  }
> 
> -void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu)
> +void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu, bool destroy)
>  {
>  	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
>  	struct vgic_irq *irq, *tmp;
> @@ -204,6 +204,13 @@ void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu)
>  	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
>  		if (irq_is_lpi(vcpu->kvm, irq->intid)) {
>  			raw_spin_lock(&irq->irq_lock);
> +			/* Leave interrupts pending a migration for prune. */
> +			if (!destroy && irq->vcpu != vgic_target_oracle(irq)) {
> +				raw_spin_unlock(&irq->irq_lock);
> +				continue;
> +			}

It's rather unclear to me what the semantics of this are.

If vcpu-a decides to nuke the LPIs of vcpu-b and the LPI had in the
meantime been migrated to vcpu-c, but obviously not observed by vcpu-c
yet as the LPI is still on vcpu-b's AP-list, then I don't see the
point in keeping this state.

Am I missing something obvious?

> +			/* Pending state is not preserved across EnableLPIs=0. */
> +			irq->pending_latch = false;

That part I agree with.

>  			list_del(&irq->ap_list);
>  			irq->vcpu = NULL;
>  			raw_spin_unlock(&irq->irq_lock);
> @@ -797,6 +804,9 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
> 
>  		/* This interrupt looks like it has to be migrated. */
> 
> +		/* Keep the interrupt alive while the locks are dropped. */
> +		vgic_get_irq_ref(irq);
> +
>  		raw_spin_unlock(&irq->irq_lock);
>  		raw_spin_unlock(&vgic_cpu->ap_list_lock);
> 
> @@ -839,6 +849,8 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
>  		raw_spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
>  		raw_spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> 
> +		deleted_lpis |= vgic_put_irq_norelease(vcpu->kvm, irq);
> +
>  		if (target_vcpu_needs_kick) {
>  			kvm_make_request(KVM_REQ_IRQ_PENDING, target_vcpu);
>  			kvm_vcpu_kick(target_vcpu);
> diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
> index 9d941241c8a2..c1ac24ede899 100644
> --- a/arch/arm64/kvm/vgic/vgic.h
> +++ b/arch/arm64/kvm/vgic/vgic.h
> @@ -341,7 +341,7 @@ void vgic_v3_put(struct kvm_vcpu *vcpu);
>  bool vgic_has_its(struct kvm *kvm);
>  int kvm_vgic_register_its_device(void);
>  void vgic_enable_lpis(struct kvm_vcpu *vcpu);
> -void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu);
> +void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu, bool destroy);
>  int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
>  int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
>  int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> 

I reckon this would work just as well with just the pending state
being removed in vgic_flush_pending_lpis(), and the reference holding
hack in gvgic_prune_ap_list().

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


^ permalink raw reply

* ❌ FAIL: Test report for for-kernelci (7.1.0-rc7, upstream-arm-next, 596d152b)
From: cki-project @ 2026-06-10 15:52 UTC (permalink / raw)
  To: catalin.marinas, will, yoyang, linux-arm-kernel

Hi, we tested your kernel and here are the results:

    Overall result: FAILED
             Merge: OK
           Compile: OK
              Test: FAILED


Kernel information:
    Commit message: Merge branch 'for-next/core' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:2591239284

One or more kernel tests failed:
    Unrecognized or new issues:
        xfstests - btrfs
             aarch64
                   Logs: https://datawarehouse.cki-project.org/kcidb/tests/redhat:2591239284_aarch64_kernel_kcidb_tool_21441185_9
                   Non-passing ran subtests:
                       ❌ FAIL generic/301

    We also see the following known issues which are not related to your changes:
        Issue: [upstream] Hardware - Firmware test suite - auto-waive failures
            URL: https://gitlab.com/cki-project/infrastructure/-/issues/779
            Affected tests:
                Hardware - Firmware test suite [aarch64]



If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



^ permalink raw reply

* [PATCH v2 4/9] media: Add tgid and fd to the v4l2-requests trace fields
From: Detlev Casanova @ 2026-06-10 14:33 UTC (permalink / raw)
  To: Daniel Almeida, Mauro Carvalho Chehab, Steven Rostedt,
	Masami Hiramatsu, Mathieu Desnoyers, Nicolas Dufresne,
	Benjamin Gaignard, Philipp Zabel, Heiko Stuebner
  Cc: linux-kernel, linux-media, linux-trace-kernel, linux-rockchip,
	linux-arm-kernel, kernel, Detlev Casanova
In-Reply-To: <20260610-v4l2-add-ftrace-v2-0-9756edf72ac1@collabora.com>

With these fields, userspace can better track which trace event matches
with a given stream.

Even though the trace shows the PID (based on current->tgid), trace
functions could be called from other contexts, therefore showing the wrong
PID, or none at all.

These will ensure that the trace event can be matched with the PID/FD that
opened and configured the video device file.

Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
---
 drivers/media/test-drivers/visl/visl-dec.c |  68 ++--
 include/trace/events/v4l2_controls.h       | 628 +++++++++++++++++++----------
 2 files changed, 445 insertions(+), 251 deletions(-)

diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
index 1c66a1b8d78f..2a065a6249ad 100644
--- a/drivers/media/test-drivers/visl/visl-dec.c
+++ b/drivers/media/test-drivers/visl/visl-dec.c
@@ -489,67 +489,71 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
 static void visl_trace_ctrls(struct visl_ctx *ctx, struct visl_run *run)
 {
 	int i;
+	struct v4l2_fh *fh = &ctx->fh;
 
 	switch (ctx->current_codec) {
 	default:
 	case VISL_CODEC_NONE:
 		break;
 	case VISL_CODEC_FWHT:
-		trace_v4l2_ctrl_fwht_params(run->fwht.params);
+		trace_v4l2_ctrl_fwht_params(fh->tgid, fh->fd, run->fwht.params);
 		break;
 	case VISL_CODEC_MPEG2:
-		trace_v4l2_ctrl_mpeg2_sequence(run->mpeg2.seq);
-		trace_v4l2_ctrl_mpeg2_picture(run->mpeg2.pic);
-		trace_v4l2_ctrl_mpeg2_quantisation(run->mpeg2.quant);
+		trace_v4l2_ctrl_mpeg2_sequence(fh->tgid, fh->fd, run->mpeg2.seq);
+		trace_v4l2_ctrl_mpeg2_picture(fh->tgid, fh->fd, run->mpeg2.pic);
+		trace_v4l2_ctrl_mpeg2_quantisation(fh->tgid, fh->fd, run->mpeg2.quant);
 		break;
 	case VISL_CODEC_VP8:
-		trace_v4l2_ctrl_vp8_frame(run->vp8.frame);
-		trace_v4l2_ctrl_vp8_entropy(run->vp8.frame);
+		trace_v4l2_ctrl_vp8_frame(fh->tgid, fh->fd, run->vp8.frame);
+		trace_v4l2_ctrl_vp8_entropy(fh->tgid, fh->fd, run->vp8.frame);
 		break;
 	case VISL_CODEC_VP9:
-		trace_v4l2_ctrl_vp9_frame(run->vp9.frame);
-		trace_v4l2_ctrl_vp9_compressed_hdr(run->vp9.probs);
-		trace_v4l2_ctrl_vp9_compressed_coeff(run->vp9.probs);
-		trace_v4l2_vp9_mv_probs(&run->vp9.probs->mv);
+		trace_v4l2_ctrl_vp9_frame(fh->tgid, fh->fd, run->vp9.frame);
+		trace_v4l2_ctrl_vp9_compressed_hdr(fh->tgid, fh->fd, run->vp9.probs);
+		trace_v4l2_ctrl_vp9_compressed_coeff(fh->tgid, fh->fd, run->vp9.probs);
+		trace_v4l2_vp9_mv_probs(fh->tgid, fh->fd, &run->vp9.probs->mv);
 		break;
 	case VISL_CODEC_H264:
-		trace_v4l2_ctrl_h264_sps(run->h264.sps);
-		trace_v4l2_ctrl_h264_pps(run->h264.pps);
-		trace_v4l2_ctrl_h264_scaling_matrix(run->h264.sm);
-		trace_v4l2_ctrl_h264_slice_params(run->h264.spram);
+		trace_v4l2_ctrl_h264_sps(fh->tgid, fh->fd, run->h264.sps);
+		trace_v4l2_ctrl_h264_pps(fh->tgid, fh->fd, run->h264.pps);
+		trace_v4l2_ctrl_h264_scaling_matrix(fh->tgid, fh->fd, run->h264.sm);
+		trace_v4l2_ctrl_h264_slice_params(fh->tgid, fh->fd, run->h264.spram);
 
 		for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++)
-			trace_v4l2_h264_ref_pic_list0(&run->h264.spram->ref_pic_list0[i], i);
+			trace_v4l2_h264_ref_pic_list0(fh->tgid, fh->fd,
+						      &run->h264.spram->ref_pic_list0[i], i);
 		for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++)
-			trace_v4l2_h264_ref_pic_list1(&run->h264.spram->ref_pic_list1[i], i);
+			trace_v4l2_h264_ref_pic_list1(fh->tgid, fh->fd,
+						      &run->h264.spram->ref_pic_list1[i], i);
 
-		trace_v4l2_ctrl_h264_decode_params(run->h264.dpram);
+		trace_v4l2_ctrl_h264_decode_params(fh->tgid, fh->fd, run->h264.dpram);
 
 		for (i = 0; i < ARRAY_SIZE(run->h264.dpram->dpb); i++)
-			trace_v4l2_h264_dpb_entry(&run->h264.dpram->dpb[i], i);
+			trace_v4l2_h264_dpb_entry(fh->tgid, fh->fd, &run->h264.dpram->dpb[i], i);
 
-		trace_v4l2_ctrl_h264_pred_weights(run->h264.pwht);
+		trace_v4l2_ctrl_h264_pred_weights(fh->tgid, fh->fd, run->h264.pwht);
 		break;
 	case VISL_CODEC_HEVC:
-		trace_v4l2_ctrl_hevc_sps(run->hevc.sps);
-		trace_v4l2_ctrl_hevc_pps(run->hevc.pps);
-		trace_v4l2_ctrl_hevc_slice_params(run->hevc.spram);
-		trace_v4l2_ctrl_hevc_scaling_matrix(run->hevc.sm);
-		trace_v4l2_ctrl_hevc_decode_params(run->hevc.dpram);
+		trace_v4l2_ctrl_hevc_sps(fh->tgid, fh->fd, run->hevc.sps);
+		trace_v4l2_ctrl_hevc_pps(fh->tgid, fh->fd, run->hevc.pps);
+		trace_v4l2_ctrl_hevc_slice_params(fh->tgid, fh->fd, run->hevc.spram);
+		trace_v4l2_ctrl_hevc_scaling_matrix(fh->tgid, fh->fd, run->hevc.sm);
+		trace_v4l2_ctrl_hevc_decode_params(fh->tgid, fh->fd, run->hevc.dpram);
 
 		for (i = 0; i < ARRAY_SIZE(run->hevc.dpram->dpb); i++)
-			trace_v4l2_hevc_dpb_entry(&run->hevc.dpram->dpb[i]);
+			trace_v4l2_hevc_dpb_entry(fh->tgid, fh->fd, &run->hevc.dpram->dpb[i]);
 
-		trace_v4l2_hevc_pred_weight_table(&run->hevc.spram->pred_weight_table);
-		trace_v4l2_ctrl_hevc_ext_sps_lt_rps(run->hevc.rps_lt);
-		trace_v4l2_ctrl_hevc_ext_sps_st_rps(run->hevc.rps_st);
 
+		trace_v4l2_hevc_pred_weight_table(fh->tgid, fh->fd,
+						  &run->hevc.spram->pred_weight_table);
+		trace_v4l2_ctrl_hevc_ext_sps_lt_rps(fh->tgid, fh->fd, run->hevc.rps_lt);
+		trace_v4l2_ctrl_hevc_ext_sps_st_rps(fh->tgid, fh->fd, run->hevc.rps_st);
 		break;
 	case VISL_CODEC_AV1:
-		trace_v4l2_ctrl_av1_sequence(run->av1.seq);
-		trace_v4l2_ctrl_av1_frame(run->av1.frame);
-		trace_v4l2_ctrl_av1_film_grain(run->av1.grain);
-		trace_v4l2_ctrl_av1_tile_group_entry(run->av1.tge);
+		trace_v4l2_ctrl_av1_sequence(fh->tgid, fh->fd, run->av1.seq);
+		trace_v4l2_ctrl_av1_frame(fh->tgid, fh->fd, run->av1.frame);
+		trace_v4l2_ctrl_av1_film_grain(fh->tgid, fh->fd, run->av1.grain);
+		trace_v4l2_ctrl_av1_tile_group_entry(fh->tgid, fh->fd, run->av1.tge);
 		break;
 	}
 }
diff --git a/include/trace/events/v4l2_controls.h b/include/trace/events/v4l2_controls.h
index 3a9bc75752bf..a7c61c36a025 100644
--- a/include/trace/events/v4l2_controls.h
+++ b/include/trace/events/v4l2_controls.h
@@ -14,27 +14,39 @@
  * They can be identified by the name of the event. All control fields are copied in a TP_STRUCT
  * field so that they can be filtered separately in userspace.
  *
+ * In addition to the controls fields, tgid and fd are also added in each trace events.
+ * This allows to identify controls set by a specific process and to match them with other events
+ * from the same process.
+ * tgid contains the process id that opened the video device.
+ * fd is the file descriptor in the tgid, used in case a process opens multiple video devices.
+ *
  * Currently only the codec controls are supported.
  */
 
 /* AV1 controls */
 DECLARE_EVENT_CLASS(v4l2_ctrl_av1_seq_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_av1_sequence *s),
-	TP_ARGS(s),
-	TP_STRUCT__entry(__field(__u32, flags)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_sequence *s),
+	TP_ARGS(tgid, fd, s),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u32, flags)
 			 __field(__u8, seq_profile)
 			 __field(__u8, order_hint_bits)
 			 __field(__u8, bit_depth)
 			 __field(__u16, max_frame_width_minus_1)
 			 __field(__u16, max_frame_height_minus_1)),
-	TP_fast_assign(__entry->flags = s->flags;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->flags = s->flags;
 		       __entry->seq_profile = s->seq_profile;
 		       __entry->order_hint_bits = s->order_hint_bits;
 		       __entry->bit_depth = s->bit_depth;
 		       __entry->max_frame_width_minus_1 = s->max_frame_width_minus_1;
 		       __entry->max_frame_height_minus_1 = s->max_frame_height_minus_1;),
-	TP_printk("\nflags %s\nseq_profile: %u\norder_hint_bits: %u\nbit_depth: %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nflags %s\nseq_profile: %u\norder_hint_bits: %u\nbit_depth: %u\n"
 		  "max_frame_width_minus_1: %u\nmax_frame_height_minus_1: %u\n",
+		  __entry->tgid, __entry->fd,
 		  __print_flags(__entry->flags, "|",
 		  {V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE, "STILL_PICTURE"},
 		  {V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK, "USE_128X128_SUPERBLOCK"},
@@ -65,17 +77,23 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_seq_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_av1_tge_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_av1_tile_group_entry *t),
-	TP_ARGS(t),
-	TP_STRUCT__entry(__field(__u32, tile_offset)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_tile_group_entry *t),
+	TP_ARGS(tgid, fd, t),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u32, tile_offset)
 			 __field(__u32, tile_size)
 			 __field(__u32, tile_row)
 			 __field(__u32, tile_col)),
-	TP_fast_assign(__entry->tile_offset = t->tile_offset;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->tile_offset = t->tile_offset;
 		       __entry->tile_size = t->tile_size;
 		       __entry->tile_row = t->tile_row;
 		       __entry->tile_col = t->tile_col;),
-	TP_printk("\ntile_offset: %u\n tile_size: %u\n tile_row: %u\ntile_col: %u\n",
+	TP_printk("tgid = %u, fd = %u, "
+		  "\ntile_offset: %u\n tile_size: %u\n tile_row: %u\ntile_col: %u\n",
+		  __entry->tgid, __entry->fd,
 		  __entry->tile_offset,
 		  __entry->tile_size,
 		  __entry->tile_row,
@@ -84,9 +102,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_tge_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_av1_frame_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_av1_frame *f),
-	TP_ARGS(f),
-	TP_STRUCT__entry(__field(u8, tile_info_flags)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_frame *f),
+	TP_ARGS(tgid, fd, f),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(u8, tile_info_flags)
 			 __field(u8, tile_info_context_update_tile_id)
 			 __field(u8, tile_info_tile_cols)
 			 __field(u8, tile_info_tile_rows)
@@ -144,7 +164,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_frame_tmpl,
 			 __array(u64, reference_frame_ts, V4L2_AV1_TOTAL_REFS_PER_FRAME)
 			 __array(s8, ref_frame_idx, V4L2_AV1_REFS_PER_FRAME)
 			 __field(u8, refresh_frame_flags)),
-	TP_fast_assign(__entry->tile_info_flags = f->tile_info.flags;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->tile_info_flags = f->tile_info.flags;
 		       __entry->tile_info_context_update_tile_id =
 				f->tile_info.context_update_tile_id;
 		       __entry->tile_info_tile_cols = f->tile_info.tile_cols;
@@ -226,7 +248,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_frame_tmpl,
 		       memcpy(__entry->ref_frame_idx, f->ref_frame_idx,
 			      sizeof(__entry->ref_frame_idx));
 		       __entry->refresh_frame_flags = f->refresh_frame_flags;),
-	TP_printk("\ntile_info.flags: %s\ntile_info.context_update_tile_id: %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\ntile_info.flags: %s\ntile_info.context_update_tile_id: %u\n"
 		  "tile_info.tile_cols: %u\ntile_info.tile_rows: %u\n"
 		  "tile_info.mi_col_starts: %s\ntile_info.mi_row_starts: %s\n"
 		  "tile_info.width_in_sbs_minus_1: %s\ntile_info.height_in_sbs_minus_1: %s\n"
@@ -250,6 +273,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_frame_tmpl,
 		  "render_width_minus_1: %u\nrender_height_minus_1: %u\ncurrent_frame_id: %u\n"
 		  "buffer_removal_time: %s\norder_hints: %s\nreference_frame_ts: %s\n"
 		  "ref_frame_idx: %s\nrefresh_frame_flags: %u\n",
+		  __entry->tgid, __entry->fd,
 		  __print_flags(__entry->tile_info_flags, "|",
 		  {V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING, "UNIFORM_TILE_SPACING"}),
 		  __entry->tile_info_context_update_tile_id,
@@ -385,9 +409,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_frame_tmpl,
 
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_av1_film_grain_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_av1_film_grain *f),
-	TP_ARGS(f),
-	TP_STRUCT__entry(__field(__u8, flags)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_film_grain *f),
+	TP_ARGS(tgid, fd, f),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u8, flags)
 			 __field(__u8, cr_mult)
 			 __field(__u16, grain_seed)
 			 __field(__u8, film_grain_params_ref_idx)
@@ -412,7 +438,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_film_grain_tmpl,
 			 __field(__u8, cr_luma_mult)
 			 __field(__u16, cb_offset)
 			 __field(__u16, cr_offset)),
-	TP_fast_assign(__entry->flags = f->flags;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->flags = f->flags;
 		       __entry->cr_mult = f->cr_mult;
 		       __entry->grain_seed = f->grain_seed;
 		       __entry->film_grain_params_ref_idx = f->film_grain_params_ref_idx;
@@ -446,7 +474,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_film_grain_tmpl,
 		       __entry->cr_luma_mult = f->cr_luma_mult;
 		       __entry->cb_offset = f->cb_offset;
 		       __entry->cr_offset = f->cr_offset;),
-	TP_printk("\nflags %s\ncr_mult: %u\ngrain_seed: %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nflags %s\ncr_mult: %u\ngrain_seed: %u\n"
 		  "film_grain_params_ref_idx: %u\nnum_y_points: %u\npoint_y_value: %s\n"
 		  "point_y_scaling: %s\nnum_cb_points: %u\npoint_cb_value: %s\n"
 		  "point_cb_scaling: %s\nnum_cr_points: %u\npoint_cr_value: %s\n"
@@ -455,6 +484,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_film_grain_tmpl,
 		  "ar_coeffs_cr_plus_128: %s\nar_coeff_shift_minus_6: %u\n"
 		  "grain_scale_shift: %u\ncb_mult: %u\ncb_luma_mult: %u\ncr_luma_mult: %u\n"
 		  "cb_offset: %u\ncr_offset: %u\n",
+		  __entry->tgid, __entry->fd,
 		  __print_flags(__entry->flags, "|",
 		  {V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN, "APPLY_GRAIN"},
 		  {V4L2_AV1_FILM_GRAIN_FLAG_UPDATE_GRAIN, "UPDATE_GRAIN"},
@@ -507,31 +537,32 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_film_grain_tmpl,
 )
 
 DEFINE_EVENT(v4l2_ctrl_av1_seq_tmpl, v4l2_ctrl_av1_sequence,
-	TP_PROTO(const struct v4l2_ctrl_av1_sequence *s),
-	TP_ARGS(s)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_sequence *s),
+	TP_ARGS(tgid, fd, s)
 );
 
 DEFINE_EVENT(v4l2_ctrl_av1_frame_tmpl, v4l2_ctrl_av1_frame,
-	TP_PROTO(const struct v4l2_ctrl_av1_frame *f),
-	TP_ARGS(f)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_frame *f),
+	TP_ARGS(tgid, fd, f)
 );
 
 DEFINE_EVENT(v4l2_ctrl_av1_tge_tmpl, v4l2_ctrl_av1_tile_group_entry,
-	TP_PROTO(const struct v4l2_ctrl_av1_tile_group_entry *t),
-	TP_ARGS(t)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_tile_group_entry *t),
+	TP_ARGS(tgid, fd, t)
 );
 
 DEFINE_EVENT(v4l2_ctrl_av1_film_grain_tmpl, v4l2_ctrl_av1_film_grain,
-	TP_PROTO(const struct v4l2_ctrl_av1_film_grain *f),
-	TP_ARGS(f)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_film_grain *f),
+	TP_ARGS(tgid, fd, f)
 );
 
 /* FWHT controls */
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_fwht_params *p),
-	TP_ARGS(p),
-	TP_STRUCT__entry(
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_fwht_params *p),
+	TP_ARGS(tgid, fd, p),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
 			 __field(u64, backward_ref_ts)
 			 __field(u32, version)
 			 __field(u32, width)
@@ -542,7 +573,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
 			 __field(u32, ycbcr_enc)
 			 __field(u32, quantization)
 			 ),
-	TP_fast_assign(
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
 		       __entry->backward_ref_ts = p->backward_ref_ts;
 		       __entry->version = p->version;
 		       __entry->width = p->width;
@@ -553,8 +585,10 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
 		       __entry->ycbcr_enc = p->ycbcr_enc;
 		       __entry->quantization = p->quantization;
 		       ),
-	TP_printk("backward_ref_ts %llu version %u width %u height %u flags %s colorspace %u "
+	TP_printk("tgid = %u, fd = %u, "
+		  "backward_ref_ts %llu version %u width %u height %u flags %s colorspace %u "
 		  "xfer_func %u ycbcr_enc %u quantization %u",
+		  __entry->tgid, __entry->fd,
 		  __entry->backward_ref_ts, __entry->version, __entry->width, __entry->height,
 		  __print_flags(__entry->flags, "|",
 		  {V4L2_FWHT_FL_IS_INTERLACED, "IS_INTERLACED"},
@@ -574,16 +608,18 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
 );
 
 DEFINE_EVENT(v4l2_ctrl_fwht_params_tmpl, v4l2_ctrl_fwht_params,
-	TP_PROTO(const struct v4l2_ctrl_fwht_params *p),
-	TP_ARGS(p)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_fwht_params *p),
+	TP_ARGS(tgid, fd, p)
 );
 
 /* H264 controls */
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_h264_sps_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_h264_sps *s),
-	TP_ARGS(s),
-	TP_STRUCT__entry(__field(u8, profile_idc)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_sps *s),
+	TP_ARGS(tgid, fd, s),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(u8, profile_idc)
 			 __field(u8, constraint_set_flags)
 			 __field(u8, level_idc)
 			 __field(u8, seq_parameter_set_id)
@@ -601,7 +637,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_sps_tmpl,
 			 __field(u16, pic_width_in_mbs_minus1)
 			 __field(u16, pic_height_in_map_units_minus1)
 			 __field(u32, flags)),
-	TP_fast_assign(__entry->profile_idc = s->profile_idc;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->profile_idc = s->profile_idc;
 		       __entry->constraint_set_flags = s->constraint_set_flags;
 		       __entry->level_idc = s->level_idc;
 		       __entry->seq_parameter_set_id = s->seq_parameter_set_id;
@@ -622,7 +660,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_sps_tmpl,
 		       __entry->pic_width_in_mbs_minus1 = s->pic_width_in_mbs_minus1;
 		       __entry->pic_height_in_map_units_minus1 = s->pic_height_in_map_units_minus1;
 		       __entry->flags = s->flags),
-	TP_printk("\nprofile_idc %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nprofile_idc %u\n"
 		  "constraint_set_flags %s\n"
 		  "level_idc %u\n"
 		  "seq_parameter_set_id %u\n"
@@ -640,6 +679,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_sps_tmpl,
 		  "pic_width_in_mbs_minus1 %u\n"
 		  "pic_height_in_map_units_minus1 %u\n"
 		  "flags %s",
+		  __entry->tgid, __entry->fd,
 		  __entry->profile_idc,
 		  __print_flags(__entry->constraint_set_flags, "|",
 		  {V4L2_H264_SPS_CONSTRAINT_SET0_FLAG, "CONSTRAINT_SET0_FLAG"},
@@ -679,9 +719,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_sps_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pps_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_h264_pps *p),
-	TP_ARGS(p),
-	TP_STRUCT__entry(__field(u8, pic_parameter_set_id)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_pps *p),
+	TP_ARGS(tgid, fd, p),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(u8, pic_parameter_set_id)
 			 __field(u8, seq_parameter_set_id)
 			 __field(u8, num_slice_groups_minus1)
 			 __field(u8, num_ref_idx_l0_default_active_minus1)
@@ -692,7 +734,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pps_tmpl,
 			 __field(__s8, chroma_qp_index_offset)
 			 __field(__s8, second_chroma_qp_index_offset)
 			 __field(u16, flags)),
-	TP_fast_assign(__entry->pic_parameter_set_id = p->pic_parameter_set_id;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->pic_parameter_set_id = p->pic_parameter_set_id;
 		       __entry->seq_parameter_set_id = p->seq_parameter_set_id;
 		       __entry->num_slice_groups_minus1 = p->num_slice_groups_minus1;
 		       __entry->num_ref_idx_l0_default_active_minus1 =
@@ -705,7 +749,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pps_tmpl,
 		       __entry->chroma_qp_index_offset = p->chroma_qp_index_offset;
 		       __entry->second_chroma_qp_index_offset = p->second_chroma_qp_index_offset;
 		       __entry->flags = p->flags),
-	TP_printk("\npic_parameter_set_id %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\npic_parameter_set_id %u\n"
 		  "seq_parameter_set_id %u\n"
 		  "num_slice_groups_minus1 %u\n"
 		  "num_ref_idx_l0_default_active_minus1 %u\n"
@@ -716,6 +761,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pps_tmpl,
 		  "chroma_qp_index_offset %d\n"
 		  "second_chroma_qp_index_offset %d\n"
 		  "flags %s",
+		  __entry->tgid, __entry->fd,
 		  __entry->pic_parameter_set_id,
 		  __entry->seq_parameter_set_id,
 		  __entry->num_slice_groups_minus1,
@@ -741,15 +787,21 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pps_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_h264_scaling_matrix_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_h264_scaling_matrix *s),
-	TP_ARGS(s),
-	TP_STRUCT__entry(__array(u8, scaling_list_4x4, 6 * 16)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_scaling_matrix *s),
+	TP_ARGS(tgid, fd, s),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __array(u8, scaling_list_4x4, 6 * 16)
 			 __array(u8, scaling_list_8x8, 6 * 64)),
-	TP_fast_assign(memcpy(__entry->scaling_list_4x4, s->scaling_list_4x4,
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       memcpy(__entry->scaling_list_4x4, s->scaling_list_4x4,
 			      sizeof(__entry->scaling_list_4x4));
 		       memcpy(__entry->scaling_list_8x8, s->scaling_list_8x8,
 			      sizeof(__entry->scaling_list_8x8))),
-	TP_printk("\nscaling_list_4x4 {%s}\nscaling_list_8x8 {%s}",
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nscaling_list_4x4 {%s}\nscaling_list_8x8 {%s}",
+		  __entry->tgid, __entry->fd,
 		  __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
 				   __entry->scaling_list_4x4,
 				   sizeof(__entry->scaling_list_4x4),
@@ -762,9 +814,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_scaling_matrix_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pred_weights_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_h264_pred_weights *p),
-	TP_ARGS(p),
-	TP_STRUCT__entry(__field(u16, luma_log2_weight_denom)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_pred_weights *p),
+	TP_ARGS(tgid, fd, p),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(u16, luma_log2_weight_denom)
 			 __field(u16, chroma_log2_weight_denom)
 			 __array(__s16, weight_factors_0_luma_weight, 32)
 			 __array(__s16, weight_factors_0_luma_offset, 32)
@@ -774,7 +828,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pred_weights_tmpl,
 			 __array(__s16, weight_factors_1_luma_offset, 32)
 			 __array(__s16, weight_factors_1_chroma_weight, 32 * 2)
 			 __array(__s16, weight_factors_1_chroma_offset, 32 * 2)),
-	TP_fast_assign(__entry->luma_log2_weight_denom = p->luma_log2_weight_denom;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->luma_log2_weight_denom = p->luma_log2_weight_denom;
 		       __entry->chroma_log2_weight_denom = p->chroma_log2_weight_denom;
 		       memcpy(__entry->weight_factors_0_luma_weight,
 			      p->weight_factors[0].luma_weight,
@@ -800,7 +856,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pred_weights_tmpl,
 		       memcpy(__entry->weight_factors_1_chroma_offset,
 			      p->weight_factors[1].chroma_offset,
 			      sizeof(__entry->weight_factors_1_chroma_offset))),
-	TP_printk("\nluma_log2_weight_denom %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nluma_log2_weight_denom %u\n"
 		  "chroma_log2_weight_denom %u\n"
 		  "weight_factor[0].luma_weight %s\n"
 		  "weight_factor[0].luma_offset %s\n"
@@ -810,6 +867,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pred_weights_tmpl,
 		  "weight_factor[1].luma_offset %s\n"
 		  "weight_factor[1].chroma_weight {%s}\n"
 		  "weight_factor[1].chroma_offset {%s}\n",
+		  __entry->tgid, __entry->fd,
 		  __entry->luma_log2_weight_denom,
 		  __entry->chroma_log2_weight_denom,
 		  __print_array(__entry->weight_factors_0_luma_weight,
@@ -844,9 +902,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pred_weights_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_h264_slice_params_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_h264_slice_params *s),
-	TP_ARGS(s),
-	TP_STRUCT__entry(__field(u32, header_bit_size)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_slice_params *s),
+	TP_ARGS(tgid, fd, s),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(u32, header_bit_size)
 			 __field(u32, first_mb_in_slice)
 			 __field(u8, slice_type)
 			 __field(u8, colour_plane_id)
@@ -860,7 +920,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_slice_params_tmpl,
 			 __field(u8, num_ref_idx_l0_active_minus1)
 			 __field(u8, num_ref_idx_l1_active_minus1)
 			 __field(u32, flags)),
-	TP_fast_assign(__entry->header_bit_size = s->header_bit_size;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->header_bit_size = s->header_bit_size;
 		       __entry->first_mb_in_slice = s->first_mb_in_slice;
 		       __entry->slice_type = s->slice_type;
 		       __entry->colour_plane_id = s->colour_plane_id;
@@ -874,7 +936,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_slice_params_tmpl,
 		       __entry->num_ref_idx_l0_active_minus1 = s->num_ref_idx_l0_active_minus1;
 		       __entry->num_ref_idx_l1_active_minus1 = s->num_ref_idx_l1_active_minus1;
 		       __entry->flags = s->flags),
-	TP_printk("\nheader_bit_size %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nheader_bit_size %u\n"
 		  "first_mb_in_slice %u\n"
 		  "slice_type %s\n"
 		  "colour_plane_id %u\n"
@@ -888,6 +951,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_slice_params_tmpl,
 		  "num_ref_idx_l0_active_minus1 %u\n"
 		  "num_ref_idx_l1_active_minus1 %u\n"
 		  "flags %s",
+		  __entry->tgid, __entry->fd,
 		  __entry->header_bit_size,
 		  __entry->first_mb_in_slice,
 		  __print_symbolic(__entry->slice_type,
@@ -913,15 +977,21 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_slice_params_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_h264_reference_tmpl,
-	TP_PROTO(const struct v4l2_h264_reference *r, int i),
-	TP_ARGS(r, i),
-	TP_STRUCT__entry(__field(u8, fields)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_reference *r, int i),
+	TP_ARGS(tgid, fd, r, i),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(u8, fields)
 			 __field(u8, index)
 			 __field(int, i)),
-	TP_fast_assign(__entry->fields = r->fields;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->fields = r->fields;
 		       __entry->index = r->index;
 		       __entry->i = i;),
-	TP_printk("[%d]: fields %s index %u",
+	TP_printk("tgid = %u, fd = %u, "
+		  "[%d]: fields %s index %u",
+		  __entry->tgid, __entry->fd,
 		  __entry->i,
 		  __print_flags(__entry->fields, "|",
 		  {V4L2_H264_TOP_FIELD_REF, "TOP_FIELD_REF"},
@@ -932,9 +1002,11 @@ DECLARE_EVENT_CLASS(v4l2_h264_reference_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_h264_decode_params_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_h264_decode_params *d),
-	TP_ARGS(d),
-	TP_STRUCT__entry(__field(u16, nal_ref_idc)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_decode_params *d),
+	TP_ARGS(tgid, fd, d),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(u16, nal_ref_idc)
 			 __field(u16, frame_num)
 			 __field(__s32, top_field_order_cnt)
 			 __field(__s32, bottom_field_order_cnt)
@@ -947,7 +1019,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_decode_params_tmpl,
 			 __field(u32, pic_order_cnt_bit_size)
 			 __field(u32, slice_group_change_cycle)
 			 __field(u32, flags)),
-	TP_fast_assign(__entry->nal_ref_idc = d->nal_ref_idc;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->nal_ref_idc = d->nal_ref_idc;
 		       __entry->frame_num = d->frame_num;
 		       __entry->top_field_order_cnt = d->top_field_order_cnt;
 		       __entry->bottom_field_order_cnt = d->bottom_field_order_cnt;
@@ -960,7 +1034,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_decode_params_tmpl,
 		       __entry->pic_order_cnt_bit_size = d->pic_order_cnt_bit_size;
 		       __entry->slice_group_change_cycle = d->slice_group_change_cycle;
 		       __entry->flags = d->flags),
-	TP_printk("\nnal_ref_idc %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nnal_ref_idc %u\n"
 		  "frame_num %u\n"
 		  "top_field_order_cnt %d\n"
 		  "bottom_field_order_cnt %d\n"
@@ -973,6 +1048,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_decode_params_tmpl,
 		  "pic_order_cnt_bit_size %u\n"
 		  "slice_group_change_cycle %u\n"
 		  "flags %s\n",
+		  __entry->tgid, __entry->fd,
 		  __entry->nal_ref_idc,
 		  __entry->frame_num,
 		  __entry->top_field_order_cnt,
@@ -995,9 +1071,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_decode_params_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_h264_dpb_entry_tmpl,
-	TP_PROTO(const struct v4l2_h264_dpb_entry *e, int i),
-	TP_ARGS(e, i),
-	TP_STRUCT__entry(__field(u64, reference_ts)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_dpb_entry *e, int i),
+	TP_ARGS(tgid, fd, e, i),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(u64, reference_ts)
 			 __field(u32, pic_num)
 			 __field(u16, frame_num)
 			 __field(u8, fields)
@@ -1005,7 +1083,9 @@ DECLARE_EVENT_CLASS(v4l2_h264_dpb_entry_tmpl,
 			 __field(__s32, bottom_field_order_cnt)
 			 __field(u32, flags)
 			 __field(int, i)),
-	TP_fast_assign(__entry->reference_ts = e->reference_ts;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->reference_ts = e->reference_ts;
 		       __entry->pic_num = e->pic_num;
 		       __entry->frame_num = e->frame_num;
 		       __entry->fields = e->fields;
@@ -1013,8 +1093,10 @@ DECLARE_EVENT_CLASS(v4l2_h264_dpb_entry_tmpl,
 		       __entry->bottom_field_order_cnt = e->bottom_field_order_cnt;
 		       __entry->flags = e->flags;
 		       __entry->i = i;),
-	TP_printk("[%d]: reference_ts %llu, pic_num %u frame_num %u fields %s "
+	TP_printk("tgid = %u, fd = %u, "
+		  "[%d]: reference_ts %llu, pic_num %u frame_num %u fields %s "
 		  "top_field_order_cnt %d bottom_field_order_cnt %d flags %s",
+		  __entry->tgid, __entry->fd,
 		  __entry->i,
 		  __entry->reference_ts,
 		  __entry->pic_num,
@@ -1035,56 +1117,58 @@ DECLARE_EVENT_CLASS(v4l2_h264_dpb_entry_tmpl,
 );
 
 DEFINE_EVENT(v4l2_ctrl_h264_sps_tmpl, v4l2_ctrl_h264_sps,
-	TP_PROTO(const struct v4l2_ctrl_h264_sps *s),
-	TP_ARGS(s)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_sps *s),
+	TP_ARGS(tgid, fd, s)
 );
 
 DEFINE_EVENT(v4l2_ctrl_h264_pps_tmpl, v4l2_ctrl_h264_pps,
-	TP_PROTO(const struct v4l2_ctrl_h264_pps *p),
-	TP_ARGS(p)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_pps *p),
+	TP_ARGS(tgid, fd, p)
 );
 
 DEFINE_EVENT(v4l2_ctrl_h264_scaling_matrix_tmpl, v4l2_ctrl_h264_scaling_matrix,
-	TP_PROTO(const struct v4l2_ctrl_h264_scaling_matrix *s),
-	TP_ARGS(s)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_scaling_matrix *s),
+	TP_ARGS(tgid, fd, s)
 );
 
 DEFINE_EVENT(v4l2_ctrl_h264_pred_weights_tmpl, v4l2_ctrl_h264_pred_weights,
-	TP_PROTO(const struct v4l2_ctrl_h264_pred_weights *p),
-	TP_ARGS(p)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_pred_weights *p),
+	TP_ARGS(tgid, fd, p)
 );
 
 DEFINE_EVENT(v4l2_ctrl_h264_slice_params_tmpl, v4l2_ctrl_h264_slice_params,
-	TP_PROTO(const struct v4l2_ctrl_h264_slice_params *s),
-	TP_ARGS(s)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_slice_params *s),
+	TP_ARGS(tgid, fd, s)
 );
 
 DEFINE_EVENT(v4l2_h264_reference_tmpl, v4l2_h264_ref_pic_list0,
-	TP_PROTO(const struct v4l2_h264_reference *r, int i),
-	TP_ARGS(r, i)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_reference *r, int i),
+	TP_ARGS(tgid, fd, r, i)
 );
 
 DEFINE_EVENT(v4l2_h264_reference_tmpl, v4l2_h264_ref_pic_list1,
-	TP_PROTO(const struct v4l2_h264_reference *r, int i),
-	TP_ARGS(r, i)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_reference *r, int i),
+	TP_ARGS(tgid, fd, r, i)
 );
 
 DEFINE_EVENT(v4l2_ctrl_h264_decode_params_tmpl, v4l2_ctrl_h264_decode_params,
-	TP_PROTO(const struct v4l2_ctrl_h264_decode_params *d),
-	TP_ARGS(d)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_decode_params *d),
+	TP_ARGS(tgid, fd, d)
 );
 
 DEFINE_EVENT(v4l2_h264_dpb_entry_tmpl, v4l2_h264_dpb_entry,
-	TP_PROTO(const struct v4l2_h264_dpb_entry *e, int i),
-	TP_ARGS(e, i)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_dpb_entry *e, int i),
+	TP_ARGS(tgid, fd, e, i)
 );
 
 /* HEVC controls */
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_sps_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_hevc_sps *s),
-	TP_ARGS(s),
-	TP_STRUCT__entry(__field(__u8, video_parameter_set_id)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_sps *s),
+	TP_ARGS(tgid, fd, s),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u8, video_parameter_set_id)
 			 __field(__u8, seq_parameter_set_id)
 			 __field(__u16, pic_width_in_luma_samples)
 			 __field(__u16, pic_height_in_luma_samples)
@@ -1109,7 +1193,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_sps_tmpl,
 			 __field(__u8, chroma_format_idc)
 			 __field(__u8, sps_max_sub_layers_minus1)
 			 __field(__u64, flags)),
-	TP_fast_assign(__entry->video_parameter_set_id = s->video_parameter_set_id;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->video_parameter_set_id = s->video_parameter_set_id;
 		       __entry->seq_parameter_set_id = s->seq_parameter_set_id;
 		       __entry->pic_width_in_luma_samples = s->pic_width_in_luma_samples;
 		       __entry->pic_height_in_luma_samples = s->pic_height_in_luma_samples;
@@ -1146,7 +1232,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_sps_tmpl,
 		       __entry->chroma_format_idc = s->chroma_format_idc;
 		       __entry->sps_max_sub_layers_minus1 = s->sps_max_sub_layers_minus1;
 		       __entry->flags = s->flags;),
-	TP_printk("\nvideo_parameter_set_id %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nvideo_parameter_set_id %u\n"
 		  "seq_parameter_set_id %u\n"
 		  "pic_width_in_luma_samples %u\n"
 		  "pic_height_in_luma_samples %u\n"
@@ -1171,6 +1258,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_sps_tmpl,
 		  "chroma_format_idc %u\n"
 		  "sps_max_sub_layers_minus1 %u\n"
 		  "flags %s",
+		  __entry->tgid, __entry->fd,
 		  __entry->video_parameter_set_id,
 		  __entry->seq_parameter_set_id,
 		  __entry->pic_width_in_luma_samples,
@@ -1213,9 +1301,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_sps_tmpl,
 
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_pps_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_hevc_pps *p),
-	TP_ARGS(p),
-	TP_STRUCT__entry(__field(__u8, pic_parameter_set_id)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_pps *p),
+	TP_ARGS(tgid, fd, p),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u8, pic_parameter_set_id)
 			 __field(__u8, num_extra_slice_header_bits)
 			 __field(__u8, num_ref_idx_l0_default_active_minus1)
 			 __field(__u8, num_ref_idx_l1_default_active_minus1)
@@ -1231,7 +1321,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_pps_tmpl,
 			 __field(__s8, pps_tc_offset_div2)
 			 __field(__u8, log2_parallel_merge_level_minus2)
 			 __field(__u64, flags)),
-	TP_fast_assign(__entry->pic_parameter_set_id = p->pic_parameter_set_id;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->pic_parameter_set_id = p->pic_parameter_set_id;
 		       __entry->num_extra_slice_header_bits = p->num_extra_slice_header_bits;
 		       __entry->num_ref_idx_l0_default_active_minus1 =
 				p->num_ref_idx_l0_default_active_minus1;
@@ -1252,7 +1344,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_pps_tmpl,
 		       __entry->log2_parallel_merge_level_minus2 =
 				p->log2_parallel_merge_level_minus2;
 		       __entry->flags = p->flags;),
-	TP_printk("\npic_parameter_set_id %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\npic_parameter_set_id %u\n"
 		  "num_extra_slice_header_bits %u\n"
 		  "num_ref_idx_l0_default_active_minus1 %u\n"
 		  "num_ref_idx_l1_default_active_minus1 %u\n"
@@ -1268,6 +1361,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_pps_tmpl,
 		  "pps_tc_offset_div2 %d\n"
 		  "log2_parallel_merge_level_minus2 %u\n"
 		  "flags %s",
+		  __entry->tgid, __entry->fd,
 		  __entry->pic_parameter_set_id,
 		  __entry->num_extra_slice_header_bits,
 		  __entry->num_ref_idx_l0_default_active_minus1,
@@ -1322,9 +1416,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_pps_tmpl,
 
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_slice_params_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_hevc_slice_params *s),
-	TP_ARGS(s),
-	TP_STRUCT__entry(__field(__u32, bit_size)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_slice_params *s),
+	TP_ARGS(tgid, fd, s),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u32, bit_size)
 			 __field(__u32, data_byte_offset)
 			 __field(__u32, num_entry_point_offsets)
 			 __field(__u8, nal_unit_type)
@@ -1351,7 +1447,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_slice_params_tmpl,
 			 __field(__u16, short_term_ref_pic_set_size)
 			 __field(__u16, long_term_ref_pic_set_size)
 			 __field(__u64, flags)),
-	TP_fast_assign(__entry->bit_size = s->bit_size;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->bit_size = s->bit_size;
 		       __entry->data_byte_offset = s->data_byte_offset;
 		       __entry->num_entry_point_offsets = s->num_entry_point_offsets;
 		       __entry->nal_unit_type = s->nal_unit_type;
@@ -1378,7 +1476,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_slice_params_tmpl,
 		       __entry->short_term_ref_pic_set_size = s->short_term_ref_pic_set_size;
 		       __entry->long_term_ref_pic_set_size = s->long_term_ref_pic_set_size;
 		       __entry->flags = s->flags;),
-	TP_printk("\nbit_size %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nbit_size %u\n"
 		  "data_byte_offset %u\n"
 		  "num_entry_point_offsets %u\n"
 		  "nal_unit_type %u\n"
@@ -1405,6 +1504,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_slice_params_tmpl,
 		  "short_term_ref_pic_set_size %u\n"
 		  "long_term_ref_pic_set_size %u\n"
 		  "flags %s",
+		  __entry->tgid, __entry->fd,
 		  __entry->bit_size,
 		  __entry->data_byte_offset,
 		  __entry->num_entry_point_offsets,
@@ -1454,9 +1554,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_slice_params_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_hevc_pred_weight_table_tmpl,
-	TP_PROTO(const struct v4l2_hevc_pred_weight_table *p),
-	TP_ARGS(p),
-	TP_STRUCT__entry(__array(__s8, delta_luma_weight_l0, V4L2_HEVC_DPB_ENTRIES_NUM_MAX)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_hevc_pred_weight_table *p),
+	TP_ARGS(tgid, fd, p),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __array(__s8, delta_luma_weight_l0, V4L2_HEVC_DPB_ENTRIES_NUM_MAX)
 			 __array(__s8, luma_offset_l0, V4L2_HEVC_DPB_ENTRIES_NUM_MAX)
 			 __array(__s8, delta_chroma_weight_l0, V4L2_HEVC_DPB_ENTRIES_NUM_MAX * 2)
 			 __array(__s8, chroma_offset_l0, V4L2_HEVC_DPB_ENTRIES_NUM_MAX * 2)
@@ -1466,7 +1568,9 @@ DECLARE_EVENT_CLASS(v4l2_hevc_pred_weight_table_tmpl,
 			 __array(__s8, chroma_offset_l1, V4L2_HEVC_DPB_ENTRIES_NUM_MAX * 2)
 			 __field(__u8, luma_log2_weight_denom)
 			 __field(__s8, delta_chroma_log2_weight_denom)),
-	TP_fast_assign(memcpy(__entry->delta_luma_weight_l0, p->delta_luma_weight_l0,
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       memcpy(__entry->delta_luma_weight_l0, p->delta_luma_weight_l0,
 			      sizeof(__entry->delta_luma_weight_l0));
 		       memcpy(__entry->luma_offset_l0, p->luma_offset_l0,
 			      sizeof(__entry->luma_offset_l0));
@@ -1485,7 +1589,8 @@ DECLARE_EVENT_CLASS(v4l2_hevc_pred_weight_table_tmpl,
 		       __entry->luma_log2_weight_denom = p->luma_log2_weight_denom;
 		       __entry->delta_chroma_log2_weight_denom =
 				p->delta_chroma_log2_weight_denom;),
-	TP_printk("\ndelta_luma_weight_l0 %s\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\ndelta_luma_weight_l0 %s\n"
 		  "luma_offset_l0 %s\n"
 		  "delta_chroma_weight_l0 {%s}\n"
 		  "chroma_offset_l0 {%s}\n"
@@ -1495,6 +1600,7 @@ DECLARE_EVENT_CLASS(v4l2_hevc_pred_weight_table_tmpl,
 		  "chroma_offset_l1 {%s}\n"
 		  "luma_log2_weight_denom %d\n"
 		  "delta_chroma_log2_weight_denom %d\n",
+		  __entry->tgid, __entry->fd,
 		  __print_array(__entry->delta_luma_weight_l0,
 				ARRAY_SIZE(__entry->delta_luma_weight_l0),
 				sizeof(__entry->delta_luma_weight_l0[0])),
@@ -1529,15 +1635,19 @@ DECLARE_EVENT_CLASS(v4l2_hevc_pred_weight_table_tmpl,
 	))
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_scaling_matrix_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_hevc_scaling_matrix *s),
-	TP_ARGS(s),
-	TP_STRUCT__entry(__array(__u8, scaling_list_4x4, 6 * 16)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_scaling_matrix *s),
+	TP_ARGS(tgid, fd, s),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __array(__u8, scaling_list_4x4, 6 * 16)
 			 __array(__u8, scaling_list_8x8, 6 * 64)
 			 __array(__u8, scaling_list_16x16, 6 * 64)
 			 __array(__u8, scaling_list_32x32, 2 * 64)
 			 __array(__u8, scaling_list_dc_coef_16x16, 6)
 			 __array(__u8, scaling_list_dc_coef_32x32, 2)),
-	TP_fast_assign(memcpy(__entry->scaling_list_4x4,
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       memcpy(__entry->scaling_list_4x4,
 			      s->scaling_list_4x4, sizeof(__entry->scaling_list_4x4));
 		       memcpy(__entry->scaling_list_8x8,
 			      s->scaling_list_8x8, sizeof(__entry->scaling_list_8x8));
@@ -1551,12 +1661,14 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_scaling_matrix_tmpl,
 		       memcpy(__entry->scaling_list_dc_coef_32x32,
 			      s->scaling_list_dc_coef_32x32,
 			      sizeof(__entry->scaling_list_dc_coef_32x32));),
-	TP_printk("\nscaling_list_4x4 {%s}\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nscaling_list_4x4 {%s}\n"
 		  "scaling_list_8x8 {%s}\n"
 		  "scaling_list_16x16 {%s}\n"
 		  "scaling_list_32x32 {%s}\n"
 		  "scaling_list_dc_coef_16x16 %s\n"
 		  "scaling_list_dc_coef_32x32 %s\n",
+		  __entry->tgid, __entry->fd,
 		  __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
 				   __entry->scaling_list_4x4,
 				   sizeof(__entry->scaling_list_4x4),
@@ -1582,9 +1694,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_scaling_matrix_tmpl,
 	))
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_hevc_decode_params *d),
-	TP_ARGS(d),
-	TP_STRUCT__entry(__field(__s32, pic_order_cnt_val)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_decode_params *d),
+	TP_ARGS(tgid, fd, d),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__s32, pic_order_cnt_val)
 			 __field(__u16, short_term_ref_pic_set_size)
 			 __field(__u16, long_term_ref_pic_set_size)
 			 __field(__u8, num_active_dpb_entries)
@@ -1595,7 +1709,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl,
 			 __array(__u8, poc_st_curr_after, V4L2_HEVC_DPB_ENTRIES_NUM_MAX)
 			 __array(__u8, poc_lt_curr, V4L2_HEVC_DPB_ENTRIES_NUM_MAX)
 			 __field(__u64, flags)),
-	TP_fast_assign(__entry->pic_order_cnt_val = d->pic_order_cnt_val;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->pic_order_cnt_val = d->pic_order_cnt_val;
 		       __entry->short_term_ref_pic_set_size = d->short_term_ref_pic_set_size;
 		       __entry->long_term_ref_pic_set_size = d->long_term_ref_pic_set_size;
 		       __entry->num_active_dpb_entries = d->num_active_dpb_entries;
@@ -1608,7 +1724,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl,
 			      sizeof(__entry->poc_st_curr_after));
 		       memcpy(__entry->poc_lt_curr, d->poc_lt_curr, sizeof(__entry->poc_lt_curr));
 		       __entry->flags = d->flags;),
-	TP_printk("\npic_order_cnt_val %d\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\npic_order_cnt_val %d\n"
 		  "short_term_ref_pic_set_size %u\n"
 		  "long_term_ref_pic_set_size %u\n"
 		  "num_active_dpb_entries %u\n"
@@ -1619,6 +1736,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl,
 		  "poc_st_curr_after %s\n"
 		  "poc_lt_curr %s\n"
 		  "flags %s",
+		  __entry->tgid, __entry->fd,
 		  __entry->pic_order_cnt_val,
 		  __entry->short_term_ref_pic_set_size,
 		  __entry->long_term_ref_pic_set_size,
@@ -1643,14 +1761,20 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_lt_rps_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt),
-	TP_ARGS(lt),
-	TP_STRUCT__entry(__field(__u8, flags)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt),
+	TP_ARGS(tgid, fd, lt),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u8, flags)
 			 __field(__u32, lt_ref_pic_poc_lsb_sps)),
-	TP_fast_assign(__entry->flags = lt->flags;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->flags = lt->flags;
 		       __entry->lt_ref_pic_poc_lsb_sps = lt->lt_ref_pic_poc_lsb_sps;),
-	TP_printk("\nflags %s\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nflags %s\n"
 		  "lt_ref_pic_poc_lsb_sps %x\n",
+		  __entry->tgid, __entry->fd,
 		  __print_flags(__entry->flags, "|",
 		  {V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT, "USED_LT"}
 		  ),
@@ -1659,9 +1783,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_lt_rps_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_st_rps *st),
-	TP_ARGS(st),
-	TP_STRUCT__entry(__field(__u8, flags)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_ext_sps_st_rps *st),
+	TP_ARGS(tgid, fd, st),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u8, flags)
 			 __field(__u8, delta_idx_minus1)
 			 __field(__u8, delta_rps_sign)
 			 __field(__u16, abs_delta_rps_minus1)
@@ -1671,7 +1797,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl,
 			 __field(__u32, use_delta_flag)
 			 __array(__u32, delta_poc_s0_minus1, 16)
 			 __array(__u32, delta_poc_s1_minus1, 16)),
-	TP_fast_assign(__entry->flags = st->flags;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->flags = st->flags;
 		       __entry->delta_idx_minus1 = st->delta_idx_minus1;
 		       __entry->delta_rps_sign = st->delta_rps_sign;
 		       __entry->abs_delta_rps_minus1 = st->abs_delta_rps_minus1;
@@ -1683,7 +1811,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl,
 			      sizeof(__entry->delta_poc_s0_minus1));
 		       memcpy(__entry->delta_poc_s1_minus1, st->delta_poc_s1_minus1,
 			      sizeof(__entry->delta_poc_s1_minus1));),
-	TP_printk("\nflags %s\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nflags %s\n"
 		  "delta_idx_minus1: %u\n"
 		  "delta_rps_sign: %u\n"
 		  "abs_delta_rps_minus1: %u\n"
@@ -1693,6 +1822,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl,
 		  "use_delta_flag: %08x\n"
 		  "delta_poc_s0_minus1: %s\n"
 		  "delta_poc_s1_minus1: %s\n",
+		  __entry->tgid, __entry->fd,
 		  __print_flags(__entry->flags, "|",
 		  {V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED, "INTER_REF_PIC_SET_PRED"}
 		  ),
@@ -1713,20 +1843,26 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_hevc_dpb_entry_tmpl,
-	TP_PROTO(const struct v4l2_hevc_dpb_entry *e),
-	TP_ARGS(e),
-	TP_STRUCT__entry(__field(__u64, timestamp)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_hevc_dpb_entry *e),
+	TP_ARGS(tgid, fd, e),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u64, timestamp)
 			 __field(__u8, flags)
 			 __field(__u8, field_pic)
 			 __field(__s32, pic_order_cnt_val)),
-	TP_fast_assign(__entry->timestamp = e->timestamp;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->timestamp = e->timestamp;
 		       __entry->flags = e->flags;
 		       __entry->field_pic = e->field_pic;
 		       __entry->pic_order_cnt_val = e->pic_order_cnt_val;),
-	TP_printk("\ntimestamp %llu\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\ntimestamp %llu\n"
 		  "flags %s\n"
 		  "field_pic %u\n"
 		  "pic_order_cnt_val %d\n",
+		  __entry->tgid, __entry->fd,
 		__entry->timestamp,
 		__print_flags(__entry->flags, "|",
 		{V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE, "LONG_TERM_REFERENCE"}
@@ -1736,69 +1872,75 @@ DECLARE_EVENT_CLASS(v4l2_hevc_dpb_entry_tmpl,
 	))
 
 DEFINE_EVENT(v4l2_ctrl_hevc_sps_tmpl, v4l2_ctrl_hevc_sps,
-	TP_PROTO(const struct v4l2_ctrl_hevc_sps *s),
-	TP_ARGS(s)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_sps *s),
+	TP_ARGS(tgid, fd, s)
 );
 
 DEFINE_EVENT(v4l2_ctrl_hevc_pps_tmpl, v4l2_ctrl_hevc_pps,
-	TP_PROTO(const struct v4l2_ctrl_hevc_pps *p),
-	TP_ARGS(p)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_pps *p),
+	TP_ARGS(tgid, fd, p)
 );
 
 DEFINE_EVENT(v4l2_ctrl_hevc_slice_params_tmpl, v4l2_ctrl_hevc_slice_params,
-	TP_PROTO(const struct v4l2_ctrl_hevc_slice_params *s),
-	TP_ARGS(s)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_slice_params *s),
+	TP_ARGS(tgid, fd, s)
 );
 
 DEFINE_EVENT(v4l2_hevc_pred_weight_table_tmpl, v4l2_hevc_pred_weight_table,
-	TP_PROTO(const struct v4l2_hevc_pred_weight_table *p),
-	TP_ARGS(p)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_hevc_pred_weight_table *p),
+	TP_ARGS(tgid, fd, p)
 );
 
 DEFINE_EVENT(v4l2_ctrl_hevc_scaling_matrix_tmpl, v4l2_ctrl_hevc_scaling_matrix,
-	TP_PROTO(const struct v4l2_ctrl_hevc_scaling_matrix *s),
-	TP_ARGS(s)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_scaling_matrix *s),
+	TP_ARGS(tgid, fd, s)
 );
 
 DEFINE_EVENT(v4l2_ctrl_hevc_decode_params_tmpl, v4l2_ctrl_hevc_decode_params,
-	TP_PROTO(const struct v4l2_ctrl_hevc_decode_params *d),
-	TP_ARGS(d)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_decode_params *d),
+	TP_ARGS(tgid, fd, d)
 );
 
 DEFINE_EVENT(v4l2_ctrl_hevc_ext_sps_lt_rps_tmpl, v4l2_ctrl_hevc_ext_sps_lt_rps,
-	TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt),
-	TP_ARGS(lt)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt),
+	TP_ARGS(tgid, fd, lt)
 );
 
 DEFINE_EVENT(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl, v4l2_ctrl_hevc_ext_sps_st_rps,
-	TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_st_rps *st),
-	TP_ARGS(st)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_ext_sps_st_rps *st),
+	TP_ARGS(tgid, fd, st)
 );
 
 DEFINE_EVENT(v4l2_hevc_dpb_entry_tmpl, v4l2_hevc_dpb_entry,
-	TP_PROTO(const struct v4l2_hevc_dpb_entry *e),
-	TP_ARGS(e)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_hevc_dpb_entry *e),
+	TP_ARGS(tgid, fd, e)
 );
 
 /* MPEG2 controls */
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_seq_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_mpeg2_sequence *s),
-	TP_ARGS(s),
-	TP_STRUCT__entry(__field(__u16, horizontal_size)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_sequence *s),
+	TP_ARGS(tgid, fd, s),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u16, horizontal_size)
 			 __field(__u16, vertical_size)
 			 __field(__u32, vbv_buffer_size)
 			 __field(__u16, profile_and_level_indication)
 			 __field(__u8, chroma_format)
 			 __field(__u8, flags)),
-	TP_fast_assign(__entry->horizontal_size = s->horizontal_size;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->horizontal_size = s->horizontal_size;
 		       __entry->vertical_size = s->vertical_size;
 		       __entry->vbv_buffer_size = s->vbv_buffer_size;
 		       __entry->profile_and_level_indication = s->profile_and_level_indication;
 		       __entry->chroma_format = s->chroma_format;
 		       __entry->flags = s->flags;),
-	TP_printk("\nhorizontal_size %u\nvertical_size %u\nvbv_buffer_size %u\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nhorizontal_size %u\nvertical_size %u\nvbv_buffer_size %u\n"
 		  "profile_and_level_indication %u\nchroma_format %u\nflags %s\n",
+		  __entry->tgid, __entry->fd,
 		  __entry->horizontal_size,
 		  __entry->vertical_size,
 		  __entry->vbv_buffer_size,
@@ -1810,24 +1952,30 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_seq_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_pic_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_mpeg2_picture *p),
-	TP_ARGS(p),
-	TP_STRUCT__entry(__field(__u64, backward_ref_ts)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_picture *p),
+	TP_ARGS(tgid, fd, p),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u64, backward_ref_ts)
 			 __field(__u64, forward_ref_ts)
 			 __field(__u32, flags)
 			 __array(__u8, f_code, 4)
 			 __field(__u8, picture_coding_type)
 			 __field(__u8, picture_structure)
 			 __field(__u8, intra_dc_precision)),
-	TP_fast_assign(__entry->backward_ref_ts = p->backward_ref_ts;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->backward_ref_ts = p->backward_ref_ts;
 		       __entry->forward_ref_ts = p->forward_ref_ts;
 		       __entry->flags = p->flags;
 		       memcpy(__entry->f_code, p->f_code, sizeof(__entry->f_code));
 		       __entry->picture_coding_type = p->picture_coding_type;
 		       __entry->picture_structure = p->picture_structure;
 		       __entry->intra_dc_precision = p->intra_dc_precision;),
-	TP_printk("\nbackward_ref_ts %llu\nforward_ref_ts %llu\nflags %s\nf_code {%s}\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nbackward_ref_ts %llu\nforward_ref_ts %llu\nflags %s\nf_code {%s}\n"
 		  "picture_coding_type: %u\npicture_structure %u\nintra_dc_precision %u\n",
+		  __entry->tgid, __entry->fd,
 		  __entry->backward_ref_ts,
 		  __entry->forward_ref_ts,
 		  __print_flags(__entry->flags, "|",
@@ -1850,13 +1998,17 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_pic_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_quant_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_mpeg2_quantisation *q),
-	TP_ARGS(q),
-	TP_STRUCT__entry(__array(__u8, intra_quantiser_matrix, 64)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_quantisation *q),
+	TP_ARGS(tgid, fd, q),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __array(__u8, intra_quantiser_matrix, 64)
 			 __array(__u8, non_intra_quantiser_matrix, 64)
 			 __array(__u8, chroma_intra_quantiser_matrix, 64)
 			 __array(__u8, chroma_non_intra_quantiser_matrix, 64)),
-	TP_fast_assign(memcpy(__entry->intra_quantiser_matrix, q->intra_quantiser_matrix,
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       memcpy(__entry->intra_quantiser_matrix, q->intra_quantiser_matrix,
 			      sizeof(__entry->intra_quantiser_matrix));
 		       memcpy(__entry->non_intra_quantiser_matrix, q->non_intra_quantiser_matrix,
 			      sizeof(__entry->non_intra_quantiser_matrix));
@@ -1866,8 +2018,10 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_quant_tmpl,
 		       memcpy(__entry->chroma_non_intra_quantiser_matrix,
 			      q->chroma_non_intra_quantiser_matrix,
 			      sizeof(__entry->chroma_non_intra_quantiser_matrix));),
-	TP_printk("\nintra_quantiser_matrix %s\nnon_intra_quantiser_matrix %s\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nintra_quantiser_matrix %s\nnon_intra_quantiser_matrix %s\n"
 		  "chroma_intra_quantiser_matrix %s\nchroma_non_intra_quantiser_matrix %s\n",
+		  __entry->tgid, __entry->fd,
 		  __print_array(__entry->intra_quantiser_matrix,
 				ARRAY_SIZE(__entry->intra_quantiser_matrix),
 				sizeof(__entry->intra_quantiser_matrix[0])),
@@ -1884,30 +2038,34 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_quant_tmpl,
 )
 
 DEFINE_EVENT(v4l2_ctrl_mpeg2_seq_tmpl, v4l2_ctrl_mpeg2_sequence,
-	TP_PROTO(const struct v4l2_ctrl_mpeg2_sequence *s),
-	TP_ARGS(s)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_sequence *s),
+	TP_ARGS(tgid, fd, s)
 );
 
 DEFINE_EVENT(v4l2_ctrl_mpeg2_pic_tmpl, v4l2_ctrl_mpeg2_picture,
-	TP_PROTO(const struct v4l2_ctrl_mpeg2_picture *p),
-	TP_ARGS(p)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_picture *p),
+	TP_ARGS(tgid, fd, p)
 );
 
 DEFINE_EVENT(v4l2_ctrl_mpeg2_quant_tmpl, v4l2_ctrl_mpeg2_quantisation,
-	TP_PROTO(const struct v4l2_ctrl_mpeg2_quantisation *q),
-	TP_ARGS(q)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_quantisation *q),
+	TP_ARGS(tgid, fd, q)
 );
 
 /* VP8 controls */
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_entropy_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_vp8_frame *f),
-	TP_ARGS(f),
-	TP_STRUCT__entry(__array(__u8, entropy_coeff_probs, 4 * 8 * 3 * V4L2_VP8_COEFF_PROB_CNT)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp8_frame *f),
+	TP_ARGS(tgid, fd, f),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __array(__u8, entropy_coeff_probs, 4 * 8 * 3 * V4L2_VP8_COEFF_PROB_CNT)
 			 __array(__u8, entropy_y_mode_probs, 4)
 			 __array(__u8, entropy_uv_mode_probs, 3)
 			 __array(__u8, entropy_mv_probs, 2 * 19)),
-	TP_fast_assign(memcpy(__entry->entropy_coeff_probs, f->entropy.coeff_probs,
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       memcpy(__entry->entropy_coeff_probs, f->entropy.coeff_probs,
 			      sizeof(__entry->entropy_coeff_probs));
 		       memcpy(__entry->entropy_y_mode_probs, f->entropy.y_mode_probs,
 			      sizeof(__entry->entropy_y_mode_probs));
@@ -1915,10 +2073,12 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_entropy_tmpl,
 			      sizeof(__entry->entropy_uv_mode_probs));
 		       memcpy(__entry->entropy_mv_probs, f->entropy.mv_probs,
 			      sizeof(__entry->entropy_mv_probs));),
-	TP_printk("\nentropy.coeff_probs {%s}\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nentropy.coeff_probs {%s}\n"
 		  "entropy.y_mode_probs %s\n"
 		  "entropy.uv_mode_probs %s\n"
 		  "entropy.mv_probs {%s}",
+		  __entry->tgid, __entry->fd,
 		  __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
 				   __entry->entropy_coeff_probs,
 				   sizeof(__entry->entropy_coeff_probs),
@@ -1937,9 +2097,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_entropy_tmpl,
 )
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_frame_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_vp8_frame *f),
-	TP_ARGS(f),
-	TP_STRUCT__entry(__array(__s8, segment_quant_update, 4)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp8_frame *f),
+	TP_ARGS(tgid, fd, f),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __array(__s8, segment_quant_update, 4)
 			 __array(__s8, segment_lf_update, 4)
 			 __array(__u8, segment_segment_probs, 3)
 			 __field(__u32, segment_flags)
@@ -1974,7 +2136,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_frame_tmpl,
 			 __field(__u64, golden_frame_ts)
 			 __field(__u64, alt_frame_ts)
 			 __field(__u64, flags)),
-	TP_fast_assign(memcpy(__entry->segment_quant_update, f->segment.quant_update,
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       memcpy(__entry->segment_quant_update, f->segment.quant_update,
 			      sizeof(__entry->segment_quant_update));
 		       memcpy(__entry->segment_lf_update, f->segment.lf_update,
 			      sizeof(__entry->segment_lf_update));
@@ -2015,7 +2179,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_frame_tmpl,
 		       __entry->golden_frame_ts = f->golden_frame_ts;
 		       __entry->alt_frame_ts = f->alt_frame_ts;
 		       __entry->flags = f->flags;),
-	TP_printk("\nsegment.quant_update %s\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nsegment.quant_update %s\n"
 		  "segment.lf_update %s\n"
 		  "segment.segment_probs %s\n"
 		  "segment.flags %s\n"
@@ -2050,6 +2215,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_frame_tmpl,
 		  "golden_frame_ts %llu\n"
 		  "alt_frame_ts %llu\n"
 		  "flags %s",
+		  __entry->tgid, __entry->fd,
 		  __print_array(__entry->segment_quant_update,
 				ARRAY_SIZE(__entry->segment_quant_update),
 				sizeof(__entry->segment_quant_update[0])),
@@ -2114,21 +2280,23 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_frame_tmpl,
 );
 
 DEFINE_EVENT(v4l2_ctrl_vp8_frame_tmpl, v4l2_ctrl_vp8_frame,
-	TP_PROTO(const struct v4l2_ctrl_vp8_frame *f),
-	TP_ARGS(f)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp8_frame *f),
+	TP_ARGS(tgid, fd, f)
 );
 
 DEFINE_EVENT(v4l2_ctrl_vp8_entropy_tmpl, v4l2_ctrl_vp8_entropy,
-	TP_PROTO(const struct v4l2_ctrl_vp8_frame *f),
-	TP_ARGS(f)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp8_frame *f),
+	TP_ARGS(tgid, fd, f)
 );
 
 /* VP9 controls */
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_frame_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_vp9_frame *f),
-	TP_ARGS(f),
-	TP_STRUCT__entry(__array(__s8, lf_ref_deltas, 4)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_frame *f),
+	TP_ARGS(tgid, fd, f),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __array(__s8, lf_ref_deltas, 4)
 			 __array(__s8, lf_mode_deltas, 2)
 			 __field(__u8, lf_level)
 			 __field(__u8, lf_sharpness)
@@ -2161,7 +2329,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_frame_tmpl,
 			 __field(__u8, tile_cols_log2)
 			 __field(__u8, tile_rows_log2)
 			 __field(__u8, reference_mode)),
-	TP_fast_assign(memcpy(__entry->lf_ref_deltas, f->lf.ref_deltas,
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       memcpy(__entry->lf_ref_deltas, f->lf.ref_deltas,
 			      sizeof(__entry->lf_ref_deltas));
 		       memcpy(__entry->lf_mode_deltas, f->lf.mode_deltas,
 			      sizeof(__entry->lf_mode_deltas));
@@ -2200,7 +2370,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_frame_tmpl,
 		       __entry->tile_cols_log2 = f->tile_cols_log2;
 		       __entry->tile_rows_log2 = f->tile_rows_log2;
 		       __entry->reference_mode = f->reference_mode;),
-	TP_printk("\nlf.ref_deltas %s\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\nlf.ref_deltas %s\n"
 		  "lf.mode_deltas %s\n"
 		  "lf.level %u\n"
 		  "lf.sharpness %u\n"
@@ -2233,6 +2404,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_frame_tmpl,
 		  "tile_cols_log2 %u\n"
 		  "tile_rows_log_2 %u\n"
 		  "reference_mode %s\n",
+		  __entry->tgid, __entry->fd,
 		  __print_array(__entry->lf_ref_deltas,
 				ARRAY_SIZE(__entry->lf_ref_deltas),
 				sizeof(__entry->lf_ref_deltas[0])),
@@ -2313,9 +2485,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_frame_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_hdr_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_vp9_compressed_hdr *h),
-	TP_ARGS(h),
-	TP_STRUCT__entry(__field(__u8, tx_mode)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_compressed_hdr *h),
+	TP_ARGS(tgid, fd, h),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __field(__u8, tx_mode)
 			 __array(__u8, tx8, 2 * 1)
 			 __array(__u8, tx16, 2 * 2)
 			 __array(__u8, tx32, 2 * 3)
@@ -2329,7 +2503,9 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_hdr_tmpl,
 			 __array(__u8, y_mode, 4 * 9)
 			 __array(__u8, uv_mode, 10 * 9)
 			 __array(__u8, partition, 16 * 3)),
-	TP_fast_assign(__entry->tx_mode = h->tx_mode;
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       __entry->tx_mode = h->tx_mode;
 		       memcpy(__entry->tx8, h->tx8, sizeof(__entry->tx8));
 		       memcpy(__entry->tx16, h->tx16, sizeof(__entry->tx16));
 		       memcpy(__entry->tx32, h->tx32, sizeof(__entry->tx32));
@@ -2344,7 +2520,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_hdr_tmpl,
 		       memcpy(__entry->y_mode, h->y_mode, sizeof(__entry->y_mode));
 		       memcpy(__entry->uv_mode, h->uv_mode, sizeof(__entry->uv_mode));
 		       memcpy(__entry->partition, h->partition, sizeof(__entry->partition));),
-	TP_printk("\ntx_mode %s\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\ntx_mode %s\n"
 		  "tx8 {%s}\n"
 		  "tx16 {%s}\n"
 		  "tx32 {%s}\n"
@@ -2358,6 +2535,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_hdr_tmpl,
 		  "y_mode {%s}\n"
 		  "uv_mode {%s}\n"
 		  "partition {%s}\n",
+		  __entry->tgid, __entry->fd,
 		  __print_symbolic(__entry->tx_mode,
 		  {V4L2_VP9_TX_MODE_ONLY_4X4, "TX_MODE_ONLY_4X4"},
 		  {V4L2_VP9_TX_MODE_ALLOW_8X8, "TX_MODE_ALLOW_8X8"},
@@ -2416,11 +2594,17 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_hdr_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_coef_tmpl,
-	TP_PROTO(const struct v4l2_ctrl_vp9_compressed_hdr *h),
-	TP_ARGS(h),
-	TP_STRUCT__entry(__array(__u8, coef, 4 * 2 * 2 * 6 * 6 * 3)),
-	TP_fast_assign(memcpy(__entry->coef, h->coef, sizeof(__entry->coef));),
-	TP_printk("\n coef {%s}",
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_compressed_hdr *h),
+	TP_ARGS(tgid, fd, h),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __array(__u8, coef, 4 * 2 * 2 * 6 * 6 * 3)),
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       memcpy(__entry->coef, h->coef, sizeof(__entry->coef));),
+	TP_printk("tgid = %u, fd = %u, "
+		  "\n coef {%s}",
+		  __entry->tgid, __entry->fd,
 		  __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
 				   __entry->coef,
 				   sizeof(__entry->coef),
@@ -2429,9 +2613,11 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_coef_tmpl,
 );
 
 DECLARE_EVENT_CLASS(v4l2_vp9_mv_probs_tmpl,
-	TP_PROTO(const struct v4l2_vp9_mv_probs *p),
-	TP_ARGS(p),
-	TP_STRUCT__entry(__array(__u8, joint, 3)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_vp9_mv_probs *p),
+	TP_ARGS(tgid, fd, p),
+	TP_STRUCT__entry(__field(u32, tgid)
+			 __field(u32, fd)
+			 __array(__u8, joint, 3)
 			 __array(__u8, sign, 2)
 			 __array(__u8, classes, 2 * 10)
 			 __array(__u8, class0_bit, 2)
@@ -2440,7 +2626,9 @@ DECLARE_EVENT_CLASS(v4l2_vp9_mv_probs_tmpl,
 			 __array(__u8, fr, 2 * 3)
 			 __array(__u8, class0_hp, 2)
 			 __array(__u8, hp, 2)),
-	TP_fast_assign(memcpy(__entry->joint, p->joint, sizeof(__entry->joint));
+	TP_fast_assign(__entry->tgid = tgid;
+		       __entry->fd = fd;
+		       memcpy(__entry->joint, p->joint, sizeof(__entry->joint));
 		       memcpy(__entry->sign, p->sign, sizeof(__entry->sign));
 		       memcpy(__entry->classes, p->classes, sizeof(__entry->classes));
 		       memcpy(__entry->class0_bit, p->class0_bit, sizeof(__entry->class0_bit));
@@ -2449,7 +2637,8 @@ DECLARE_EVENT_CLASS(v4l2_vp9_mv_probs_tmpl,
 		       memcpy(__entry->fr, p->fr, sizeof(__entry->fr));
 		       memcpy(__entry->class0_hp, p->class0_hp, sizeof(__entry->class0_hp));
 		       memcpy(__entry->hp, p->hp, sizeof(__entry->hp));),
-	TP_printk("\n joint %s\n"
+	TP_printk("tgid = %u, fd = %u, "
+		  "\n joint %s\n"
 		  "sign %s\n"
 		  "classes {%s}\n"
 		  "class0_bit %s\n"
@@ -2458,6 +2647,7 @@ DECLARE_EVENT_CLASS(v4l2_vp9_mv_probs_tmpl,
 		  "fr {%s}\n"
 		  "class0_hp %s\n"
 		  "hp %s\n",
+		  __entry->tgid, __entry->fd,
 		  __print_array(__entry->joint,
 				ARRAY_SIZE(__entry->joint),
 				sizeof(__entry->joint[0])),
@@ -2493,24 +2683,24 @@ DECLARE_EVENT_CLASS(v4l2_vp9_mv_probs_tmpl,
 );
 
 DEFINE_EVENT(v4l2_ctrl_vp9_frame_tmpl, v4l2_ctrl_vp9_frame,
-	TP_PROTO(const struct v4l2_ctrl_vp9_frame *f),
-	TP_ARGS(f)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_frame *f),
+	TP_ARGS(tgid, fd, f)
 );
 
 DEFINE_EVENT(v4l2_ctrl_vp9_compressed_hdr_tmpl, v4l2_ctrl_vp9_compressed_hdr,
-	TP_PROTO(const struct v4l2_ctrl_vp9_compressed_hdr *h),
-	TP_ARGS(h)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_compressed_hdr *h),
+	TP_ARGS(tgid, fd, h)
 );
 
 DEFINE_EVENT(v4l2_ctrl_vp9_compressed_coef_tmpl, v4l2_ctrl_vp9_compressed_coeff,
-	TP_PROTO(const struct v4l2_ctrl_vp9_compressed_hdr *h),
-	TP_ARGS(h)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_compressed_hdr *h),
+	TP_ARGS(tgid, fd, h)
 );
 
 
 DEFINE_EVENT(v4l2_vp9_mv_probs_tmpl, v4l2_vp9_mv_probs,
-	TP_PROTO(const struct v4l2_vp9_mv_probs *p),
-	TP_ARGS(p)
+	TP_PROTO(u32 tgid, u32 fd, const struct v4l2_vp9_mv_probs *p),
+	TP_ARGS(tgid, fd, p)
 );
 
 #endif /* if !defined(_TRACE_V4L2_CONTROLS_H_) || defined(TRACE_HEADER_MULTI_READ) */

-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH] ASoC: meson: axg-tdm-formatter: Use guard() for mutex locks
From: Mark Brown @ 2026-06-10 15:46 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: phucduc.bui, Liam Girdwood, Neil Armstrong, Kevin Hilman,
	Martin Blumenstingl, Jaroslav Kysela, Takashi Iwai, linux-sound,
	linux-arm-kernel, linux-amlogic, linux-kernel
In-Reply-To: <1j8q8mfte7.fsf@starbuckisacylon.baylibre.com>

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

On Wed, Jun 10, 2026 at 02:54:08PM +0200, Jerome Brunet wrote:
> On mer. 10 juin 2026 at 17:21, phucduc.bui@gmail.com wrote:

> > Clean up the code using guard() for mutex locks.
> > Merely code refactoring, and no behavior change.

> I suppose it is OK but it does not seem to really clean anything and
> make the code easier to follow in that instance, from my perspective at
> least.

> If there is policy to systematically use guard() whenever
> possible then OK, otherwise it seems unnecessary.

I don't know about policy but there's definitely people who are keen on
converting things to this pattern.

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

^ permalink raw reply

* [GIT PULL] i.MX arm64 device tree changes for v7.2 (part2)
From: Frank.Li @ 2026-06-10 15:39 UTC (permalink / raw)
  To: soc, arm; +Cc: Frank.Li, kernel, imx, linux-arm-kernel

From: Frank.Li@nxp.com

The following changes since commit c10cfc952215644956284a42fa7b7860dfbcb5f5:

  arm64: dts: imx{91,93}-phyboard-segin: Add peb-av-18 overlays (2026-06-05 13:21:22 -0400)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/frank.li/linux.git tags/imx-dt64-7.2-part2

for you to fetch changes up to de8c602d5a2180c737e55dcd3dbcbf9dcc4af292:

  arm64: dts: lx2160a-rev2: avoid 32-bit pcie window system ram overlap (2026-06-10 11:27:22 -0400)

----------------------------------------------------------------
i.MX arm64 device tree changes for v7.2 (part2)

- Revert the 32-bit non-prefetchable PCIe window from 3 GiB back to 1 GiB
to prevent overlap between inbound DMA address space and low system RAM.
Such overlap can cause DMA transactions to be routed to a BAR on the same
host bridge instead of system memory.

----------------------------------------------------------------
Josua Mayer (1):
      arm64: dts: lx2160a-rev2: avoid 32-bit pcie window system ram overlap

 arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)


^ permalink raw reply

* [PATCH 2/2] pinctrl: meson: restore non-sleeping GPIO access
From: Viacheslav Bocharov @ 2026-06-10 15:32 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	Marek Szyprowski, Robin Murphy, Diederik de Haas, linux-gpio,
	linux-arm-kernel, linux-amlogic, linux-kernel
In-Reply-To: <20260610153329.937833-1-v@baodeep.com>

Commit 28f240683871 ("pinctrl: meson: mark the GPIO controller as
sleeping") set gpio_chip.can_sleep = true to work around
gpio-shared-proxy holding a spinlock across a sleeping pinctrl config
path. That locking bug is now fixed in the shared-proxy itself ("gpio:
shared-proxy: always serialize with a sleeping mutex"), so the
controller-wide workaround is no longer needed; the meson GPIO
controller does not sleep.

meson_gpio_get/set/direction_* access MMIO through regmap. The
regmap_mmio bus uses fast I/O (spinlock) locking, so these value
callbacks do not contain sleeping operations. Since gpio_chip.can_sleep
describes the get/set value path, restore can_sleep = false.

Marking the controller sleeping also broke atomic value consumers such
as w1-gpio (1-Wire bitbang): w1_io.c runs its read time slot under
local_irq_save() and uses the non-cansleep gpiod_set_value() /
gpiod_get_value(), which with can_sleep=true trigger WARN_ON(can_sleep)
in gpiolib on every transferred bit (from w1_gpio_write_bit() /
w1_gpio_read_bit() via w1_reset_bus() and w1_search()). The printk and
stack dump inside the IRQs-off, microsecond-scale time slot destroy the
bit timing, so reset/presence detection and ROM search fail: the bus
master registers but w1_master_slave_count stays at 0 and no devices
are found. Verified on an Amlogic A113X board (DS18B20 on GPIOA_14):
with can_sleep restored to false the warnings are gone and the sensor
is detected and read again.

This must not be applied or backported without the shared-proxy locking
fix above; otherwise the original Khadas VIM3 splat returns on boards
that genuinely share a meson GPIO.

Fixes: 28f240683871 ("pinctrl: meson: mark the GPIO controller as sleeping")
Link: https://lore.kernel.org/all/20260105150509.56537-1-bartosz.golaszewski@oss.qualcomm.com/
Signed-off-by: Viacheslav Bocharov <v@baodeep.com>
---


 drivers/pinctrl/meson/pinctrl-meson.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 4507dc8b5563..18295b15ecd9 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -619,7 +619,7 @@ static int meson_gpiolib_register(struct meson_pinctrl *pc)
 	pc->chip.set = meson_gpio_set;
 	pc->chip.base = -1;
 	pc->chip.ngpio = pc->data->num_pins;
-	pc->chip.can_sleep = true;
+	pc->chip.can_sleep = false;
 
 	ret = gpiochip_add_data(&pc->chip, pc);
 	if (ret) {
-- 
2.54.0



^ permalink raw reply related

* [PATCH 1/2] gpio: shared-proxy: always serialize with a sleeping mutex
From: Viacheslav Bocharov @ 2026-06-10 15:32 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	Marek Szyprowski, Robin Murphy, Diederik de Haas, linux-gpio,
	linux-arm-kernel, linux-amlogic, linux-kernel
In-Reply-To: <20260610153329.937833-1-v@baodeep.com>

The shared GPIO descriptor used either a mutex or a spinlock, chosen at
runtime from the underlying chip's can_sleep:

	shared_desc->can_sleep = gpiod_cansleep(shared_desc->desc);
	... if (can_sleep) mutex_lock(); else spin_lock_irqsave();

can_sleep describes only the value path (->get/->set). Under the same
lock, however, the proxy may call gpiod_set_config() and
gpiod_direction_*(), which can reach pinctrl paths that take a mutex
(e.g. gpiod_set_config() -> gpiochip_generic_config() ->
pinctrl_gpio_set_config()), independent of can_sleep. On a controller
with non-sleeping MMIO value ops the descriptor lock was a spinlock, so
the sleeping pinctrl call ran from atomic context. Reproduced on an
Amlogic A113X board with the workaround from commit 28f240683871
("pinctrl: meson: mark the GPIO controller as sleeping") reverted; the
original Khadas VIM3 report hit the same path:

	BUG: sleeping function called from invalid context
	  __mutex_lock
	  pinctrl_get_device_gpio_range
	  pinctrl_gpio_set_config
	  gpiochip_generic_config
	  gpiod_set_config
	  gpio_shared_proxy_set_config   <- voting spinlock held
	  ...
	  mmc_pwrseq_simple_probe

The spinlock existed to take the value vote from atomic context, but the
vote and the (possibly sleeping) control operations share the same state
and lock, so this scheme cannot serialize config under a mutex and still
offer atomic value access. Always serialize the shared descriptor with a
mutex instead and mark the proxy a sleeping gpiochip, driving the
underlying GPIO through the cansleep value accessors: those are valid
for both sleeping and non-sleeping chips, so value access keeps working
on fast controllers, at the cost of no longer being atomic.

This is observable: consumers gating on gpiod_cansleep() take their
sleeping branch on a proxied GPIO (mmc-pwrseq-emmc skips its
emergency-restart reset handler; its normal reset is unaffected), and
consumers that reject sleeping GPIOs (pwm-gpio, ps2-gpio, ...) would
fail to probe. Such atomic users do not share a pin through the proxy,
whose purpose is voting on shared reset/enable lines. The same narrowing
already applies on Amlogic since that workaround, and rockchip
addressed the identical splat per-driver in commit 7ca497be0016 ("gpio:
rockchip: Stop calling pinctrl for set_direction"); fixing the proxy
addresses the locking error once, for every controller.

The lock type was added by commit a060b8c511ab ("gpiolib: implement
low-level, shared GPIO support"); the sleeping call under it arrived with
the proxy driver.

Fixes: e992d54c6f97 ("gpio: shared-proxy: implement the shared GPIO proxy driver")
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Closes: https://lore.kernel.org/all/00107523-7737-4b92-a785-14ce4e93b8cb@samsung.com/
Signed-off-by: Viacheslav Bocharov <v@baodeep.com>
---

 drivers/gpio/gpio-shared-proxy.c | 43 +++++++-------------------------
 drivers/gpio/gpiolib-shared.c    |  9 ++-----
 drivers/gpio/gpiolib-shared.h    | 31 +++++++++--------------
 3 files changed, 23 insertions(+), 60 deletions(-)

diff --git a/drivers/gpio/gpio-shared-proxy.c b/drivers/gpio/gpio-shared-proxy.c
index 6941e4be6cf1..856e5b9d6163 100644
--- a/drivers/gpio/gpio-shared-proxy.c
+++ b/drivers/gpio/gpio-shared-proxy.c
@@ -109,7 +109,7 @@ static void gpio_shared_proxy_free(struct gpio_chip *gc, unsigned int offset)
 
 	if (proxy->voted_high) {
 		ret = gpio_shared_proxy_set_unlocked(proxy,
-			shared_desc->can_sleep ? gpiod_set_value_cansleep : gpiod_set_value, 0);
+			gpiod_set_value_cansleep, 0);
 		if (ret)
 			dev_err(proxy->dev,
 				"Failed to unset the shared GPIO value on release: %d\n", ret);
@@ -222,13 +222,6 @@ static int gpio_shared_proxy_direction_output(struct gpio_chip *gc,
 	return gpio_shared_proxy_set_unlocked(proxy, gpiod_direction_output, value);
 }
 
-static int gpio_shared_proxy_get(struct gpio_chip *gc, unsigned int offset)
-{
-	struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc);
-
-	return gpiod_get_value(proxy->shared_desc->desc);
-}
-
 static int gpio_shared_proxy_get_cansleep(struct gpio_chip *gc,
 					  unsigned int offset)
 {
@@ -237,29 +230,15 @@ static int gpio_shared_proxy_get_cansleep(struct gpio_chip *gc,
 	return gpiod_get_value_cansleep(proxy->shared_desc->desc);
 }
 
-static int gpio_shared_proxy_do_set(struct gpio_shared_proxy_data *proxy,
-				    int (*set_func)(struct gpio_desc *desc, int value),
-				    int value)
-{
-	guard(gpio_shared_desc_lock)(proxy->shared_desc);
-
-	return gpio_shared_proxy_set_unlocked(proxy, set_func, value);
-}
-
-static int gpio_shared_proxy_set(struct gpio_chip *gc, unsigned int offset,
-				 int value)
-{
-	struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc);
-
-	return gpio_shared_proxy_do_set(proxy, gpiod_set_value, value);
-}
-
 static int gpio_shared_proxy_set_cansleep(struct gpio_chip *gc,
 					  unsigned int offset, int value)
 {
 	struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc);
 
-	return gpio_shared_proxy_do_set(proxy, gpiod_set_value_cansleep, value);
+	guard(gpio_shared_desc_lock)(proxy->shared_desc);
+
+	return gpio_shared_proxy_set_unlocked(proxy, gpiod_set_value_cansleep,
+					      value);
 }
 
 static int gpio_shared_proxy_get_direction(struct gpio_chip *gc,
@@ -302,20 +281,16 @@ static int gpio_shared_proxy_probe(struct auxiliary_device *adev,
 	gc->label = dev_name(dev);
 	gc->parent = dev;
 	gc->owner = THIS_MODULE;
-	gc->can_sleep = shared_desc->can_sleep;
+	/* Always a sleeping gpiochip: see the lock comment in gpiolib-shared.h. */
+	gc->can_sleep = true;
 
 	gc->request = gpio_shared_proxy_request;
 	gc->free = gpio_shared_proxy_free;
 	gc->set_config = gpio_shared_proxy_set_config;
 	gc->direction_input = gpio_shared_proxy_direction_input;
 	gc->direction_output = gpio_shared_proxy_direction_output;
-	if (gc->can_sleep) {
-		gc->set = gpio_shared_proxy_set_cansleep;
-		gc->get = gpio_shared_proxy_get_cansleep;
-	} else {
-		gc->set = gpio_shared_proxy_set;
-		gc->get = gpio_shared_proxy_get;
-	}
+	gc->set = gpio_shared_proxy_set_cansleep;
+	gc->get = gpio_shared_proxy_get_cansleep;
 	gc->get_direction = gpio_shared_proxy_get_direction;
 	gc->to_irq = gpio_shared_proxy_to_irq;
 
diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
index de72776fb154..495bd3d0ddf0 100644
--- a/drivers/gpio/gpiolib-shared.c
+++ b/drivers/gpio/gpiolib-shared.c
@@ -627,8 +627,7 @@ static void gpio_shared_release(struct kref *kref)
 
 	shared_desc = entry->shared_desc;
 	gpio_device_put(shared_desc->desc->gdev);
-	if (shared_desc->can_sleep)
-		mutex_destroy(&shared_desc->mutex);
+	mutex_destroy(&shared_desc->mutex);
 	kfree(shared_desc);
 	entry->shared_desc = NULL;
 }
@@ -659,11 +658,7 @@ gpiod_shared_desc_create(struct gpio_shared_entry *entry)
 	}
 
 	shared_desc->desc = &gdev->descs[entry->offset];
-	shared_desc->can_sleep = gpiod_cansleep(shared_desc->desc);
-	if (shared_desc->can_sleep)
-		mutex_init(&shared_desc->mutex);
-	else
-		spin_lock_init(&shared_desc->spinlock);
+	mutex_init(&shared_desc->mutex);
 
 	return shared_desc;
 }
diff --git a/drivers/gpio/gpiolib-shared.h b/drivers/gpio/gpiolib-shared.h
index 15e72a8dcdb1..5c725118b1af 100644
--- a/drivers/gpio/gpiolib-shared.h
+++ b/drivers/gpio/gpiolib-shared.h
@@ -6,7 +6,6 @@
 #include <linux/cleanup.h>
 #include <linux/lockdep.h>
 #include <linux/mutex.h>
-#include <linux/spinlock.h>
 
 struct gpio_device;
 struct gpio_desc;
@@ -42,35 +41,29 @@ static inline int gpio_shared_add_proxy_lookup(struct device *consumer,
 
 struct gpio_shared_desc {
 	struct gpio_desc *desc;
-	bool can_sleep;
 	unsigned long cfg;
 	unsigned int usecnt;
 	unsigned int highcnt;
-	union {
-		struct mutex mutex;
-		spinlock_t spinlock;
-	};
+	struct mutex mutex; /* serializes all proxy operations on this descriptor */
 };
 
 struct gpio_shared_desc *devm_gpiod_shared_get(struct device *dev);
 
+/*
+ * Under this lock the proxy may call gpiod_set_config()/gpiod_direction_*(),
+ * which can reach pinctrl paths that take a mutex (e.g. gpiod_set_config() ->
+ * gpiochip_generic_config() -> pinctrl_gpio_set_config()), independent of the
+ * underlying chip's can_sleep. A spinlock would run that sleeping call from
+ * atomic context, so the descriptor lock must be a mutex and the proxy
+ * gpiochip is therefore sleeping (can_sleep=true).
+ */
 DEFINE_LOCK_GUARD_1(gpio_shared_desc_lock, struct gpio_shared_desc,
-	if (_T->lock->can_sleep)
-		mutex_lock(&_T->lock->mutex);
-	else
-		spin_lock_irqsave(&_T->lock->spinlock, _T->flags),
-	if (_T->lock->can_sleep)
-		mutex_unlock(&_T->lock->mutex);
-	else
-		spin_unlock_irqrestore(&_T->lock->spinlock, _T->flags),
-	unsigned long flags)
+	mutex_lock(&_T->lock->mutex),
+	mutex_unlock(&_T->lock->mutex))
 
 static inline void gpio_shared_lockdep_assert(struct gpio_shared_desc *shared_desc)
 {
-	if (shared_desc->can_sleep)
-		lockdep_assert_held(&shared_desc->mutex);
-	else
-		lockdep_assert_held(&shared_desc->spinlock);
+	lockdep_assert_held(&shared_desc->mutex);
 }
 
 #endif /* __LINUX_GPIO_SHARED_H */
-- 
2.54.0



^ permalink raw reply related

* [PATCH 0/2] gpio: fix sleeping-in-atomic in shared-proxy; restore meson non-sleeping
From: Viacheslav Bocharov @ 2026-06-10 15:32 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	Marek Szyprowski, Robin Murphy, Diederik de Haas, linux-gpio,
	linux-arm-kernel, linux-amlogic, linux-kernel

gpio-shared-proxy chooses its descriptor lock (mutex vs spinlock) from
the underlying chip's can_sleep, but under that lock it calls config and
direction ops that reach sleeping pinctrl paths. On a controller with
non-sleeping MMIO value ops the lock is a spinlock, so a sleeping call
runs from atomic context:

  BUG: sleeping function called from invalid context
    ... pinctrl_gpio_set_config <- gpiochip_generic_config
    <- gpio_shared_proxy_set_config (voting spinlock held)
    <- ... <- mmc_pwrseq_simple_probe

This was reported on Khadas VIM3 and worked around for Amlogic by
commit 28f240683871 ("pinctrl: meson: mark the GPIO controller as
sleeping"), which marked the whole meson controller sleeping. That
workaround broke atomic value-path consumers: w1-gpio (1-Wire bitbang)
no longer detects devices, because its IRQ-disabled read slot calls the
non-cansleep gpiod_*_value() and now hits WARN_ON(can_sleep) per bit.

Patch 1 fixes the proxy locking generically (always a sleeping mutex).
Patch 2 then restores meson can_sleep=false, fixing 1-Wire.

Patch 1 has a trade-off: a proxied GPIO becomes sleeping, so consumers
gating on gpiod_cansleep() change behaviour. No current device needs
atomic (non-cansleep) value access on a shared GPIO -- every report
(Khadas VIM3, ODROID-M1, my test on JetHub D1+) is a shared reset line
(eMMC/SDIO pwrseq or PCIe reset) driven through the cansleep accessors,
which is what the proxy exists to vote on. An alternative that keeps
atomic value access (split locking) is possible but adds a second lock
and new race windows. I went with the simpler, verified approach and
would appreciate guidance on whether the atomic value path must be
preserved.

The two are a unit: patch 2 must not be applied without patch 1,
otherwise the original VIM3 splat returns on boards that share a meson
GPIO -- please keep the order. I have not Cc'd stable; I will request
stable backports separately once both patches have landed.

Viacheslav Bocharov (2):
  gpio: shared-proxy: always serialize with a sleeping mutex
  pinctrl: meson: restore non-sleeping GPIO access

 drivers/gpio/gpio-shared-proxy.c      | 43 ++++++---------------------
 drivers/gpio/gpiolib-shared.c         |  9 ++----
 drivers/gpio/gpiolib-shared.h         | 31 ++++++++-----------
 drivers/pinctrl/meson/pinctrl-meson.c |  2 +-
 4 files changed, 24 insertions(+), 61 deletions(-)

-- 
2.54.0



^ permalink raw reply

* Re: [PATCH V3 0/8] PCI: imx6: Integrate pwrctrl API and update device trees
From: Manivannan Sadhasivam @ 2026-06-10 15:29 UTC (permalink / raw)
  To: Sherry Sun (OSS)
  Cc: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
	lpieralisi, kwilczynski, bhelgaas, hongxing.zhu, l.stach, imx,
	linux-pci, linux-arm-kernel, devicetree, linux-kernel, sherry.sun
In-Reply-To: <20260520084904.2424253-1-sherry.sun@oss.nxp.com>

On Wed, May 20, 2026 at 04:48:56PM +0800, Sherry Sun (OSS) wrote:
> From: Sherry Sun <sherry.sun@nxp.com>
> 
> This series integrates the PCI pwrctrl framework into the pci-imx6
> driver and updates i.MX EVK board device trees to support it.
> 
> Patches 2-8 update device trees for i.MX EVK boards which maintained
> by NXP to move power supply properties from the PCIe controller node
> to the Root Port child node, which is required for pwrctrl framework.
> Affected boards:
> - i.MX6Q/DL SABRESD
> - i.MX6SX SDB
> - i.MX8MM EVK
> - i.MX8MP EVK
> - i.MX8MQ EVK
> - i.MX8DXL/QM/QXP EVK
> - i.MX95 15x15/19x19 EVK
> 
> The driver maintains legacy regulator handling for device trees that
> haven't been updated yet. Both old and new device tree structures are
> supported.
> 
> Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
> ---
> Changes in V3:
> 1. Rebased on top of latest 7.1.0-rc4
> 
> Changes in V2:
> 1. After commit 2d8c5098b847 ("PCI/pwrctrl: Do not power off on pwrctrl
>    device removal"), the pwrctrl drivers no longer power off devices
>    during removal. Update pci-imx6 driver's shutdown callback in patch#1
>    to explicitly call pci_pwrctrl_power_off_devices() before 
>    pci_pwrctrl_destroy_devices() to ensure devices are properly powered
>    off.
> ---
> 
> Sherry Sun (8):
>   PCI: imx6: Integrate new pwrctrl API for pci-imx6
>   arm: dts: imx6qdl-sabresd: Move power supply property to Root Port
>     node
>   arm: dts: imx6sx-sdb: Move power supply property to Root Port node
>   arm64: dts: imx8mm-evk: Move power supply property to Root Port node
>   arm64: dts: imx8mp-evk: Move power supply properties to Root Port node
>   arm64: dts: imx8mq-evk: Move power supply properties to Root Port node
>   arm64: dts: imx8dxl/qm/qxp: Move power supply properties to Root Port
>     node
>   arm64: dts: imx95: Move power supply properties to Root Port node

Acked-by: Manivannan Sadhasivam <mani@kernel.org>

- Mani

> 
>  .../arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi |  2 +-
>  arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi     |  2 +-
>  arch/arm64/boot/dts/freescale/imx8dxl-evk.dts |  4 ++--
>  arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi |  2 +-
>  arch/arm64/boot/dts/freescale/imx8mp-evk.dts  |  4 ++--
>  arch/arm64/boot/dts/freescale/imx8mq-evk.dts  |  4 ++--
>  arch/arm64/boot/dts/freescale/imx8qm-mek.dts  |  4 ++--
>  arch/arm64/boot/dts/freescale/imx8qxp-mek.dts |  4 ++--
>  .../boot/dts/freescale/imx95-15x15-evk.dts    |  4 ++--
>  .../boot/dts/freescale/imx95-19x19-evk.dts    |  8 +++----
>  drivers/pci/controller/dwc/Kconfig            |  1 +
>  drivers/pci/controller/dwc/pci-imx6.c         | 24 ++++++++++++++++++-
>  12 files changed, 43 insertions(+), 20 deletions(-)
> 
> -- 
> 2.37.1
> 

-- 
மணிவண்ணன் சதாசிவம்


^ permalink raw reply

* Re: [PATCH V3 0/8] PCI: imx6: Integrate pwrctrl API and update device trees
From: Manivannan Sadhasivam @ 2026-06-10 15:25 UTC (permalink / raw)
  To: Sherry Sun
  Cc: Hongxing Zhu (OSS), Sherry Sun (OSS), robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, Frank Li,
	s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com,
	lpieralisi@kernel.org, kwilczynski@kernel.org,
	bhelgaas@google.com, l.stach@pengutronix.de, imx@lists.linux.dev,
	linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <VI0PR04MB12114B321EB4DFD68B7030F76920E2@VI0PR04MB12114.eurprd04.prod.outlook.com>

On Thu, May 21, 2026 at 04:40:35AM +0000, Sherry Sun wrote:
> 
> > > -----Original Message-----
> > > From: Sherry Sun (OSS) <sherry.sun@oss.nxp.com>
> > > Sent: Wednesday, May 20, 2026 4:49 PM
> > > To: robh@kernel.org; krzk+dt@kernel.org; conor+dt@kernel.org; Frank Li
> > > <frank.li@nxp.com>; s.hauer@pengutronix.de; kernel@pengutronix.de;
> > > festevam@gmail.com; lpieralisi@kernel.org; kwilczynski@kernel.org;
> > > mani@kernel.org; bhelgaas@google.com; Hongxing Zhu
> > > <hongxing.zhu@nxp.com>; l.stach@pengutronix.de
> > > Cc: imx@lists.linux.dev; linux-pci@vger.kernel.org; linux-arm-
> > > kernel@lists.infradead.org; devicetree@vger.kernel.org; linux-
> > > kernel@vger.kernel.org; Sherry Sun <sherry.sun@nxp.com>
> > > Subject: [PATCH V3 0/8] PCI: imx6: Integrate pwrctrl API and update
> > > device trees
> > >
> > > From: Sherry Sun <sherry.sun@nxp.com>
> > >
> > > This series integrates the PCI pwrctrl framework into the pci-imx6
> > > driver and updates i.MX EVK board device trees to support it.
> > >
> > > Patches 2-8 update device trees for i.MX EVK boards which maintained
> > > by NXP to move power supply properties from the PCIe controller node
> > > to the Root Port child node, which is required for pwrctrl framework.
> > > Affected boards:
> > > - i.MX6Q/DL SABRESD
> > > - i.MX6SX SDB
> > > - i.MX8MM EVK
> > > - i.MX8MP EVK
> > > - i.MX8MQ EVK
> > > - i.MX8DXL/QM/QXP EVK
> > > - i.MX95 15x15/19x19 EVK
> > >
> > > The driver maintains legacy regulator handling for device trees that
> > > haven't been updated yet. Both old and new device tree structures are
> > supported.
> > >
> > > Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
> > Hi Sherry:
> > Since the vpcie3v3aux is used to power up the WAKE#, it is always on in this
> > pwrctrl framework whatever the system is in suspend or not, right?
> > 
> 
> Hi Richard,
> Currently the new pwrctrl framework doesn't support vpcie3v3aux, it handles all
> regulators with of_regulator_bulk_get_all() and regulator_bulk_enable/disable().
> The vpcie3v3aux now only works with pci-imx6 driver.
> 

PWRCTRL_GENERIC driver can handle both vpcie3v3 and vpcie3v3aux, but not
POWER_SEQUENCING_PCIE_M2 driver, as there is no 3.3Vaux defined in M.2 spec.

- Mani

-- 
மணிவண்ணன் சதாசிவம்


^ permalink raw reply

* [PATCH v5 phy-next 15/16] phy: lynx-10g: new driver
From: Vladimir Oltean @ 2026-06-10 15:19 UTC (permalink / raw)
  To: linux-phy
  Cc: Ioana Ciornei, Vinod Koul, Neil Armstrong, Tanjeff Moos,
	linux-kernel, devicetree, Conor Dooley, Krzysztof Kozlowski,
	Rob Herring, linux-arm-kernel, chleroy, linuxppc-dev
In-Reply-To: <20260610151952.2141019-1-vladimir.oltean@nxp.com>

Introduce a driver for the networking lanes of the 10G Lynx SerDes
block, present on the majority of Layerscape and QorIQ (Freescale/NXP)
SoCs.

As with the 28G Lynx, the SerDes lanes come pre-initialized out of
reset and the consumers use them that way outside the Generic PHY
framework (for networking, the static configuration remains for the
entire SoC lifetime, whereas for SATA and PCIe, the hardware
reconfigures itself automatically for other link speeds).

The need for the Generic PHY framework comes specifically for networking
use cases where a static lane configuration is not sufficient. For
example a network MAC is connected to an SFP cage, where various SFP or
SFP+ modules can be connected. Each of them may require a different
SerDes protocol (SGMII, 1000Base-X, 10GBase-R), which phylink + sfp-bus
are responsible of figuring out. The phylink drivers are:
- enetc
- felix
- dpaa_eth (fman_memac)
- dpaa2-eth
- dpaa2-switch

and they all need to reconfigure the SerDes for the requested link mode,
using phy_set_mode_ext() (and phy_validate() to see if it is supported
in the first place).

Note that SerDes 2 on LS1088A is exclusively non-networking, so there is
currently no need for this driver. Therefore we skip matching on its
compatible string and do not probe on that device.

Co-developed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
Cc: devicetree@vger.kernel.org
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: chleroy@kernel.org
Cc: linuxppc-dev@lists.ozlabs.org

v4->v5:
- add comments around default_pccr so that Sashiko understands what is
  the idea and why the code is correct (and the assumptions being made)
- replace testing of the non-zero quality of lane->default_pccr[mode]
  with the lynx_10g_pccr_val_enabled() helper which ignores the KX bit.
  A lane starting with PCCR8_SGMIIa_KX=1 and PCCR8_SGMIIa_CFG=0 is
  disabled, not enabled (although this is unusual and never a hardware
  reset value).
- express PCCR8_SGMIIa_CFG(), PCCR9_QSGMIIa_CFG(), PCCR9_QXGMIIa_CFG(),
  PCCRB_XFIa_CFG(), PCCRB_SXGMIIa_CFG() using GENMASK(2, 0) to make it
  clear that the field width is not 1
v3->v4:
- none
v2->v3:
- fix lynx_10g_power_on() procedure
- include <linux/of.h> instead of <linux/of_device.h>
- fix build warning introduced in v2 in lynx_10g_lane_set_nrate()
v1->v2:
- move lynx_lane_restrict_fixed_mode_change() to lynx-core, even though
  the 28G Lynx as instantiated in LX2 does not have QSGMII.
- lynx_10g_validate() now calls the new lynx_phy_mode_to_lane_mode()
  which does verify that the current lane mode is supported
- avoid line size checkpatch warnings in lynx_10g_lane_set_nrate() by
  saving the nrate to a variable and calling lynx_lane_rmw() only once
- remove redundant "if (!lane->powered_up)" checks from
  lynx_10g_lane_halt() and lynx_10g_lane_reset() - also checked at
  the only call site, lynx_10g_set_mode(), as in lynx-28g
- expand CC list (flagged by Patchwork)
---
 drivers/phy/freescale/Kconfig             |   10 +
 drivers/phy/freescale/Makefile            |    1 +
 drivers/phy/freescale/phy-fsl-lynx-10g.c  | 1321 +++++++++++++++++++++
 drivers/phy/freescale/phy-fsl-lynx-core.c |   38 +
 drivers/phy/freescale/phy-fsl-lynx-core.h |    4 +
 include/soc/fsl/phy-fsl-lynx.h            |   27 +
 6 files changed, 1401 insertions(+)
 create mode 100644 drivers/phy/freescale/phy-fsl-lynx-10g.c

diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index ac575d531db7..5bf3864fbe64 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -54,6 +54,16 @@ endif
 config PHY_FSL_LYNX_CORE
 	tristate
 
+config PHY_FSL_LYNX_10G
+	tristate "Freescale Layerscape Lynx 10G SerDes PHY support"
+	depends on OF
+	depends on ARCH_LAYERSCAPE || COMPILE_TEST
+	select GENERIC_PHY
+	select PHY_FSL_LYNX_CORE
+	help
+	  Enable this to add support for the Lynx 10G SerDes PHY as found on
+	  NXP's Layerscape platform such as LS1088A or LS1028A.
+
 config PHY_FSL_LYNX_28G
 	tristate "Freescale Layerscape Lynx 28G SerDes PHY support"
 	depends on OF
diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
index d7aa62cdeb39..5b0e180d6972 100644
--- a/drivers/phy/freescale/Makefile
+++ b/drivers/phy/freescale/Makefile
@@ -5,5 +5,6 @@ obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY)	+= phy-fsl-imx8-mipi-dphy.o
 obj-$(CONFIG_PHY_FSL_IMX8M_PCIE)	+= phy-fsl-imx8m-pcie.o
 obj-$(CONFIG_PHY_FSL_IMX8QM_HSIO)	+= phy-fsl-imx8qm-hsio.o
 obj-$(CONFIG_PHY_FSL_LYNX_CORE)		+= phy-fsl-lynx-core.o
+obj-$(CONFIG_PHY_FSL_LYNX_10G)		+= phy-fsl-lynx-10g.o
 obj-$(CONFIG_PHY_FSL_LYNX_28G)		+= phy-fsl-lynx-28g.o
 obj-$(CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY)	+= phy-fsl-samsung-hdmi.o
diff --git a/drivers/phy/freescale/phy-fsl-lynx-10g.c b/drivers/phy/freescale/phy-fsl-lynx-10g.c
new file mode 100644
index 000000000000..38def160ef1a
--- /dev/null
+++ b/drivers/phy/freescale/phy-fsl-lynx-10g.c
@@ -0,0 +1,1321 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2021-2026 NXP */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+
+#include "phy-fsl-lynx-core.h"
+
+/* SoC IP wrapper for protocol converters */
+#define PCCR8				0x220
+#define PCCR8_SGMIIa_KX			BIT(3)
+#define PCCR8_SGMIIa_CFG		GENMASK(2, 0)
+
+#define PCCR9				0x224
+#define PCCR9_QSGMIIa_CFG		GENMASK(2, 0)
+#define PCCR9_QXGMIIa_CFG		GENMASK(2, 0)
+
+#define PCCRB				0x22c
+#define PCCRB_XFIa_CFG			GENMASK(2, 0)
+#define PCCRB_SXGMIIa_CFG		GENMASK(2, 0)
+
+#define SGMII_CFG(id)			(28 - (id) * 4)
+#define QSGMII_CFG(id)			(28 - (id) * 4)
+#define SXGMII_CFG(id)			(28 - (id) * 4)
+#define QXGMII_CFG(id)			(12 - (id) * 4)
+#define XFI_CFG(id)			(28 - (id) * 4)
+
+#define CR(x)				((x) * 4)
+
+#define A				0
+#define B				1
+#define C				2
+#define D				3
+#define E				4
+#define F				5
+#define G				6
+#define H				7
+
+#define SGMIIaCR0(id)			(0x1800 + (id) * 0x10)
+#define QSGMIIaCR0(id)			(0x1880 + (id) * 0x10)
+#define XAUIaCR0(id)			(0x1900 + (id) * 0x10)
+#define XFIaCR0(id)			(0x1980 + (id) * 0x10)
+#define SXGMIIaCR0(id)			(0x1a80 + (id) * 0x10)
+#define QXGMIIaCR0(id)			(0x1b00 + (id) * 0x20)
+
+#define SGMIIaCR0_RST_SGM		BIT(31)
+#define SGMIIaCR0_RST_SGM_OFF		SGMIIaCR0_RST_SGM
+#define SGMIIaCR0_RST_SGM_ON		0
+#define SGMIIaCR0_PD_SGM		BIT(30)
+#define SGMIIaCR1_SGPCS_EN		BIT(11)
+#define SGMIIaCR1_SGPCS_DIS		0x0
+
+#define QSGMIIaCR0_RST_QSGM		BIT(31)
+#define QSGMIIaCR0_RST_QSGM_OFF		QSGMIIaCR0_RST_QSGM
+#define QSGMIIaCR0_RST_QSGM_ON		0
+#define QSGMIIaCR0_PD_QSGM		BIT(30)
+
+/* Per PLL registers */
+#define PLLnCR0(pll)			((pll) * 0x20 + 0x4)
+
+#define PLLnCR0_POFF			BIT(31)
+
+#define PLLnCR0_REFCLK_SEL		GENMASK(30, 28)
+#define PLLnCR0_REFCLK_SEL_100MHZ	0x0
+#define PLLnCR0_REFCLK_SEL_125MHZ	0x1
+#define PLLnCR0_REFCLK_SEL_156MHZ	0x2
+#define PLLnCR0_REFCLK_SEL_150MHZ	0x3
+#define PLLnCR0_REFCLK_SEL_161MHZ	0x4
+#define PLLnCR0_PLL_LCK			BIT(23)
+#define PLLnCR0_FRATE_SEL		GENMASK(19, 16)
+#define PLLnCR0_FRATE_5G		0x0
+#define PLLnCR0_FRATE_5_15625G		0x6
+#define PLLnCR0_FRATE_4G		0x7
+#define PLLnCR0_FRATE_3_125G		0x9
+#define PLLnCR0_FRATE_3G		0xa
+
+/* Per SerDes lane registers */
+
+/* Lane a Protocol Select status register */
+#define LNaPSSR0(lane)			(0x100 + (lane) * 0x20)
+#define LNaPSSR0_TYPE			GENMASK(30, 26)
+#define LNaPSSR0_IS_QUAD		GENMASK(25, 24)
+#define LNaPSSR0_MAC			GENMASK(19, 16)
+#define LNaPSSR0_PCS			GENMASK(10, 8)
+#define LNaPSSR0_LANE			GENMASK(2, 0)
+
+/* Lane a General Control Register */
+#define LNaGCR0(lane)			(0x800 + (lane) * 0x40 + 0x0)
+#define LNaGCR0_RPLL_PLLF		BIT(31)
+#define LNaGCR0_RPLL_PLLS		0x0
+#define LNaGCR0_RPLL_MSK		BIT(31)
+#define LNaGCR0_RRAT_SEL		GENMASK(29, 28)
+#define LNaGCR0_TRAT_SEL		GENMASK(25, 24)
+#define LNaGCR0_TPLL_PLLF		BIT(27)
+#define LNaGCR0_TPLL_PLLS		0x0
+#define LNaGCR0_TPLL_MSK		BIT(27)
+#define LNaGCR0_RRST_OFF		LNaGCR0_RRST
+#define LNaGCR0_TRST_OFF		LNaGCR0_TRST
+#define LNaGCR0_RRST_ON			0x0
+#define LNaGCR0_TRST_ON			0x0
+#define LNaGCR0_RRST			BIT(22)
+#define LNaGCR0_TRST			BIT(21)
+#define LNaGCR0_RX_PD			BIT(20)
+#define LNaGCR0_TX_PD			BIT(19)
+#define LNaGCR0_IF20BIT_EN		BIT(18)
+#define LNaGCR0_PROTS			GENMASK(11, 7)
+
+#define LNaGCR1(lane)			(0x800 + (lane) * 0x40 + 0x4)
+#define LNaGCR1_RDAT_INV		BIT(31)
+#define LNaGCR1_TDAT_INV		BIT(30)
+#define LNaGCR1_OPAD_CTL		BIT(26)
+#define LNaGCR1_REIDL_TH		GENMASK(22, 20)
+#define LNaGCR1_REIDL_EX_SEL		GENMASK(19, 18)
+#define LNaGCR1_REIDL_ET_SEL		GENMASK(17, 16)
+#define LNaGCR1_REIDL_EX_MSB		BIT(15)
+#define LNaGCR1_REIDL_ET_MSB		BIT(14)
+#define LNaGCR1_REQ_CTL_SNP		BIT(13)
+#define LNaGCR1_REQ_CDR_SNP		BIT(12)
+#define LNaGCR1_TRSTDIR			BIT(7)
+#define LNaGCR1_REQ_BIN_SNP		BIT(6)
+#define LNaGCR1_ISLEW_RCTL		GENMASK(5, 4)
+#define LNaGCR1_OSLEW_RCTL		GENMASK(1, 0)
+
+#define LNaRECR0(lane)			(0x800 + (lane) * 0x40 + 0x10)
+#define LNaRECR0_RXEQ_BST		BIT(28)
+#define LNaRECR0_GK2OVD			GENMASK(27, 24)
+#define LNaRECR0_GK3OVD			GENMASK(19, 16)
+#define LNaRECR0_GK2OVD_EN		BIT(15)
+#define LNaRECR0_GK3OVD_EN		BIT(14)
+#define LNaRECR0_OSETOVD_EN		BIT(13)
+#define LNaRECR0_BASE_WAND		GENMASK(11, 10)
+#define LNaRECR0_OSETOVD		GENMASK(6, 0)
+
+#define LNaTECR0(lane)			(0x800 + (lane) * 0x40 + 0x18)
+#define LNaTECR0_TEQ_TYPE		GENMASK(29, 28)
+#define LNaTECR0_SGN_PREQ		BIT(26)
+#define LNaTECR0_RATIO_PREQ		GENMASK(25, 22)
+#define LNaTECR0_SGN_POST1Q		BIT(21)
+#define LNaTECR0_RATIO_PST1Q		GENMASK(20, 16)
+#define LNaTECR0_ADPT_EQ		GENMASK(13, 8)
+#define LNaTECR0_AMP_RED		GENMASK(5, 0)
+
+#define LNaTTLCR0(lane)			(0x800 + (lane) * 0x40 + 0x20)
+#define LNaTTLCR1(lane)			(0x800 + (lane) * 0x40 + 0x24)
+#define LNaTTLCR2(lane)			(0x800 + (lane) * 0x40 + 0x28)
+
+#define LNaTCSR3(lane)			(0x800 + (lane) * 0x40 + 0x3C)
+#define LNaTCSR3_CDR_LCK		BIT(27)
+
+enum lynx_10g_rat_sel {
+	RAT_SEL_FULL = 0x0,
+	RAT_SEL_HALF = 0x1,
+	RAT_SEL_QUARTER = 0x2,
+	RAT_SEL_DOUBLE = 0x3,
+};
+
+enum lynx_10g_eq_type {
+	EQ_TYPE_NO_EQ = 0,
+	EQ_TYPE_2TAP = 1,
+	EQ_TYPE_3TAP = 2,
+};
+
+enum lynx_10g_proto_sel {
+	PROTO_SEL_PCIE = 0,
+	PROTO_SEL_SGMII_BASEX_KX_QSGMII = 1,
+	PROTO_SEL_SATA = 2,
+	PROTO_SEL_XAUI = 4,
+	PROTO_SEL_XFI_10GBASER_KR_SXGMII = 0xa,
+};
+
+struct lynx_10g_proto_conf {
+	int proto_sel;
+	int if20bit_en;
+	int reidl_th;
+	int reidl_et_msb;
+	int reidl_et_sel;
+	int reidl_ex_msb;
+	int reidl_ex_sel;
+	int islew_rctl;
+	int oslew_rctl;
+	int rxeq_bst;
+	int gk2ovd;
+	int gk3ovd;
+	int gk2ovd_en;
+	int gk3ovd_en;
+	int base_wand;
+	int teq_type;
+	int sgn_preq;
+	int ratio_preq;
+	int sgn_post1q;
+	int ratio_post1q;
+	int adpt_eq;
+	int amp_red;
+	int ttlcr0;
+};
+
+static const struct lynx_10g_proto_conf lynx_10g_proto_conf[LANE_MODE_MAX] = {
+	[LANE_MODE_1000BASEX_SGMII] = {
+		.proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
+		.reidl_th = 1,
+		.reidl_ex_sel = 3,
+		.reidl_et_msb = 1,
+		.islew_rctl = 1,
+		.oslew_rctl = 1,
+		.gk2ovd = 15,
+		.gk3ovd = 15,
+		.gk2ovd_en = 1,
+		.gk3ovd_en = 1,
+		.teq_type = EQ_TYPE_NO_EQ,
+		.adpt_eq = 48,
+		.amp_red = 6,
+		.ttlcr0 = 0x39000400,
+	},
+	[LANE_MODE_2500BASEX] = {
+		.proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
+		.islew_rctl = 2,
+		.oslew_rctl = 2,
+		.teq_type = EQ_TYPE_2TAP,
+		.sgn_post1q = 1,
+		.ratio_post1q = 6,
+		.adpt_eq = 48,
+		.ttlcr0 = 0x00000400,
+	},
+	[LANE_MODE_QSGMII] = {
+		.proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
+		.islew_rctl = 1,
+		.oslew_rctl = 1,
+		.teq_type = EQ_TYPE_2TAP,
+		.sgn_post1q = 1,
+		.ratio_post1q = 6,
+		.adpt_eq = 48,
+		.amp_red = 2,
+		.ttlcr0 = 0x00000400,
+	},
+	[LANE_MODE_10G_QXGMII] = {
+		.proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
+		.if20bit_en = 1,
+		.islew_rctl = 1,
+		.oslew_rctl = 1,
+		.base_wand = 1,
+		.teq_type = EQ_TYPE_NO_EQ,
+		.adpt_eq = 48,
+		.ttlcr0 = 0x00000400,
+	},
+	[LANE_MODE_USXGMII] = {
+		.proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
+		.if20bit_en = 1,
+		.islew_rctl = 1,
+		.oslew_rctl = 1,
+		.base_wand = 1,
+		.teq_type = EQ_TYPE_NO_EQ,
+		.sgn_post1q = 1,
+		.adpt_eq = 48,
+		.ttlcr0 = 0x00000400,
+	},
+	[LANE_MODE_10GBASER] = {
+		.proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
+		.if20bit_en = 1,
+		.islew_rctl = 2,
+		.oslew_rctl = 2,
+		.rxeq_bst = 1,
+		.base_wand = 1,
+		.teq_type = EQ_TYPE_2TAP,
+		.sgn_post1q = 1,
+		.ratio_post1q = 3,
+		.adpt_eq = 48,
+		.amp_red = 7,
+		.ttlcr0 = 0x00000400,
+	},
+};
+
+static void lynx_10g_cdr_lock_check(struct lynx_lane *lane)
+{
+	u32 tcsr3 = lynx_lane_read(lane, LNaTCSR3);
+
+	if (tcsr3 & LNaTCSR3_CDR_LCK)
+		return;
+
+	dev_dbg(&lane->phy->dev,
+		"Lane %c CDR unlocked, resetting receiver...\n",
+		'A' + lane->id);
+
+	lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_ON, LNaGCR0_RRST);
+	usleep_range(1, 2);
+	lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_OFF, LNaGCR0_RRST);
+
+	usleep_range(1, 2);
+}
+
+static void lynx_10g_pll_read_configuration(struct lynx_pll *pll)
+{
+	u32 val;
+
+	val = lynx_pll_read(pll, PLLnCR0);
+	pll->frate_sel = FIELD_GET(PLLnCR0_FRATE_SEL, val);
+	pll->refclk_sel = FIELD_GET(PLLnCR0_REFCLK_SEL, val);
+	pll->enabled = !(val & PLLnCR0_POFF);
+	pll->locked = !!(val & PLLnCR0_PLL_LCK);
+
+	if (!pll->enabled)
+		return;
+
+	switch (pll->frate_sel) {
+	case PLLnCR0_FRATE_5G:
+		/* 5GHz clock net */
+		__set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported);
+		__set_bit(LANE_MODE_QSGMII, pll->supported);
+		break;
+	case PLLnCR0_FRATE_3_125G:
+		__set_bit(LANE_MODE_2500BASEX, pll->supported);
+		break;
+	case PLLnCR0_FRATE_5_15625G:
+		/* 10.3125GHz clock net */
+		__set_bit(LANE_MODE_10GBASER, pll->supported);
+		__set_bit(LANE_MODE_USXGMII, pll->supported);
+		__set_bit(LANE_MODE_10G_QXGMII, pll->supported);
+		break;
+	default:
+		break;
+	}
+}
+
+/* On LS1028A, SGMIIA_CFG, SGMIIB_CFG, and SGMIIC_CFG from PCCR8 have the
+ * ability to map either an ENETC PCS (PCCR8_SGMIIa_CFG=2) or a Felix switch
+ * PCS (PCCR8_SGMIIa_CFG=1) to the same lane.
+ *
+ * On LS1088A, the same QSGMII PCS B can be connected to SerDes lane 1
+ * (PCCR9_QSGMIIa_CFG=1) or to lane 3 (PCCR9_QSGMIIa_CFG=2).
+ *
+ * The PHY API lacks the capability to distinguish anything about the consumer,
+ * so we don't support changing the initial muxing done by the RCW.
+ *
+ * However, after disabling a PCS through PCCR8, we need to properly restore
+ * the original value to keep the same muxing, and for that we need to back
+ * it up (here).
+ */
+static void lynx_10g_backup_pccr_val(struct lynx_lane *lane)
+{
+	u32 val;
+	int err;
+
+	if (lane->mode == LANE_MODE_UNKNOWN)
+		return;
+
+	err = lynx_pccr_read(lane, lane->mode, &val);
+	if (err) {
+		dev_warn(&lane->phy->dev,
+			 "The driver doesn't know how to access the PCCR for lane mode %s\n",
+			 lynx_lane_mode_str(lane->mode));
+		lane->mode = LANE_MODE_UNKNOWN;
+		return;
+	}
+
+	lane->default_pccr[lane->mode] = val;
+
+	/* 1000Base-X, 1000Base-KX, 2500Base-KX and SGMII use the same PCCR8.
+	 * Only the KX bit differs (set for 1000Base-KX). Since we back up PCCR
+	 * values per lane mode, make sure to not back up the PCCR8 value with
+	 * the KX bit set for the non-KX modes, if the lane was in KX mode at
+	 * boot time. Just preserve bits 2:0, which tell whether the (and
+	 * which) 1G PCS was enabled.
+	 */
+	switch (lane->mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		lane->default_pccr[LANE_MODE_1000BASEX_SGMII] = val & ~PCCR8_SGMIIa_KX;
+		lane->default_pccr[LANE_MODE_2500BASEX] = val & ~PCCR8_SGMIIa_KX;
+		break;
+	default:
+		break;
+	}
+}
+
+/* Is the PCS enabled, according to the value backed up from the PCCR register
+ * for this lane mode?
+ *
+ * Normally we'd need to ask "what lane mode are we talking about?", but the
+ * answer is invariably the same regardless - PCCR8_SGMIIa_CFG has the same
+ * layout as PCCR9_QSGMIIa_CFG, PCCRB_XFIa_CFG etc etc, and the value 0
+ * universally means "PCS disabled". So this is just a shorthand answer.
+ */
+static bool lynx_10g_pccr_val_enabled(u32 pccr)
+{
+	return FIELD_PREP(PCCR8_SGMIIa_CFG, pccr) != 0;
+}
+
+static bool lynx_10g_lane_is_3_125g(struct lynx_lane *lane)
+{
+	struct lynx_priv *priv = lane->priv;
+	struct lynx_pll *pll;
+	u32 gcr0;
+
+	gcr0 = lynx_lane_read(lane, LNaGCR0);
+
+	if (gcr0 & LNaGCR0_TPLL_PLLF)
+		pll = &priv->pll[0];
+	else
+		pll = &priv->pll[1];
+
+	if (pll->frate_sel != PLLnCR0_FRATE_3_125G)
+		return false;
+
+	if (FIELD_GET(LNaGCR0_TRAT_SEL, gcr0) != RAT_SEL_FULL ||
+	    FIELD_GET(LNaGCR0_RRAT_SEL, gcr0) != RAT_SEL_FULL)
+		return false;
+
+	return true;
+}
+
+static void lynx_10g_lane_read_configuration(struct lynx_lane *lane)
+{
+	u32 pssr0 = lynx_lane_read(lane, LNaPSSR0);
+	struct lynx_priv *priv = lane->priv;
+	int proto;
+
+	proto = FIELD_GET(LNaPSSR0_TYPE, pssr0);
+	switch (proto) {
+	case PROTO_SEL_SGMII_BASEX_KX_QSGMII:
+		if (lynx_10g_lane_is_3_125g(lane))
+			lane->mode = LANE_MODE_2500BASEX;
+		else if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0))
+			lane->mode = LANE_MODE_QSGMII;
+		else
+			lane->mode = LANE_MODE_1000BASEX_SGMII;
+		break;
+	case PROTO_SEL_XFI_10GBASER_KR_SXGMII:
+		if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0))
+			lane->mode = LANE_MODE_10G_QXGMII;
+		else if (priv->info->quirks & LYNX_QUIRK_HAS_HARDCODED_USXGMII)
+			lane->mode = LANE_MODE_USXGMII;
+		else
+			lane->mode = LANE_MODE_10GBASER;
+		break;
+	case PROTO_SEL_PCIE:
+	case PROTO_SEL_SATA:
+	case PROTO_SEL_XAUI:
+		break;
+	default:
+		dev_warn(&lane->phy->dev, "Unknown lane protocol 0x%x\n",
+			 proto);
+	}
+
+	lynx_10g_backup_pccr_val(lane);
+}
+
+static int ls1028a_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+			    struct lynx_pccr *pccr)
+{
+	switch (lane_mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		pccr->offset = PCCR8;
+		pccr->width = 4;
+		pccr->shift = SGMII_CFG(lane);
+		break;
+	case LANE_MODE_QSGMII:
+		if (lane != 1)
+			return -EINVAL;
+
+		pccr->offset = PCCR9;
+		pccr->width = 3;
+		pccr->shift = QSGMII_CFG(A);
+		break;
+	case LANE_MODE_10G_QXGMII:
+		if (lane != 1)
+			return -EINVAL;
+
+		pccr->offset = PCCR9;
+		pccr->width = 3;
+		pccr->shift = QXGMII_CFG(A);
+		break;
+	case LANE_MODE_USXGMII:
+		if (lane != 0)
+			return -EINVAL;
+
+		pccr->offset = PCCRB;
+		pccr->width = 3;
+		pccr->shift = SXGMII_CFG(A);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ls1028a_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		return SGMIIaCR0(lane);
+	case LANE_MODE_QSGMII:
+		return lane == 1 ? QSGMIIaCR0(A) : -EINVAL;
+	case LANE_MODE_USXGMII:
+		return lane == 0 ? SXGMIIaCR0(A) : -EINVAL;
+	case LANE_MODE_10G_QXGMII:
+		return lane == 1 ? QXGMIIaCR0(A) : -EINVAL;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct lynx_info lynx_info_ls1028a = {
+	.get_pccr = ls1028a_get_pccr,
+	.get_pcvt_offset = ls1028a_get_pcvt_offset,
+	.pll_read_configuration = lynx_10g_pll_read_configuration,
+	.lane_read_configuration = lynx_10g_lane_read_configuration,
+	.cdr_lock_check = lynx_10g_cdr_lock_check,
+	.num_lanes = 4,
+	.index = 1,
+	.quirks = LYNX_QUIRK_HAS_HARDCODED_USXGMII,
+};
+
+static int ls1046a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+				    struct lynx_pccr *pccr)
+{
+	switch (lane_mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		pccr->offset = PCCR8;
+		pccr->width = 4;
+		pccr->shift = SGMII_CFG(lane);
+		break;
+	case LANE_MODE_QSGMII:
+		if (lane != 1)
+			return -EINVAL;
+
+		pccr->offset = PCCR9;
+		pccr->width = 3;
+		pccr->shift = QSGMII_CFG(B);
+		break;
+	case LANE_MODE_10GBASER:
+		switch (lane) {
+		case 2:
+			pccr->shift = XFI_CFG(A);
+			break;
+		case 3:
+			pccr->shift = XFI_CFG(B);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		pccr->offset = PCCRB;
+		pccr->width = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ls1046a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		return SGMIIaCR0(lane);
+	case LANE_MODE_QSGMII:
+		if (lane != 1)
+			return -EINVAL;
+
+		return QSGMIIaCR0(B);
+	case LANE_MODE_10GBASER:
+		switch (lane) {
+		case 2:
+			return XFIaCR0(A);
+		case 3:
+			return XFIaCR0(B);
+		default:
+			return -EINVAL;
+		}
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct lynx_info lynx_info_ls1046a_serdes1 = {
+	.get_pccr = ls1046a_serdes1_get_pccr,
+	.get_pcvt_offset = ls1046a_serdes1_get_pcvt_offset,
+	.pll_read_configuration = lynx_10g_pll_read_configuration,
+	.lane_read_configuration = lynx_10g_lane_read_configuration,
+	.cdr_lock_check = lynx_10g_cdr_lock_check,
+	.num_lanes = 4,
+	.index = 1,
+};
+
+static int ls1046a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+				    struct lynx_pccr *pccr)
+{
+	switch (lane_mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		if (lane != 1)
+			return -EINVAL;
+
+		pccr->offset = PCCR8;
+		pccr->width = 4;
+		pccr->shift = SGMII_CFG(B);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ls1046a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		if (lane != 1)
+			return -EINVAL;
+
+		return SGMIIaCR0(B);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct lynx_info lynx_info_ls1046a_serdes2 = {
+	.get_pccr = ls1046a_serdes2_get_pccr,
+	.get_pcvt_offset = ls1046a_serdes2_get_pcvt_offset,
+	.pll_read_configuration = lynx_10g_pll_read_configuration,
+	.lane_read_configuration = lynx_10g_lane_read_configuration,
+	.cdr_lock_check = lynx_10g_cdr_lock_check,
+	.num_lanes = 4,
+	.index = 2,
+};
+
+static int ls1088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+				    struct lynx_pccr *pccr)
+{
+	switch (lane_mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+		pccr->offset = PCCR8;
+		pccr->width = 4;
+		pccr->shift = SGMII_CFG(lane);
+		break;
+	case LANE_MODE_QSGMII:
+		switch (lane) {
+		case 0:
+			pccr->shift = QSGMII_CFG(A);
+			break;
+		case 1:
+		case 3:
+			pccr->shift = QSGMII_CFG(B);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		pccr->offset = PCCR9;
+		pccr->width = 3;
+		break;
+	case LANE_MODE_10GBASER:
+		switch (lane) {
+		case 2:
+			pccr->shift = XFI_CFG(A);
+			break;
+		case 3:
+			pccr->shift = XFI_CFG(B);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		pccr->offset = PCCRB;
+		pccr->width = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ls1088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+		return SGMIIaCR0(lane);
+	case LANE_MODE_QSGMII:
+		switch (lane) {
+		case 0:
+			return QSGMIIaCR0(A);
+		case 1:
+		case 3:
+			return QSGMIIaCR0(B);
+		default:
+			return -EINVAL;
+		}
+	case LANE_MODE_10GBASER:
+		switch (lane) {
+		case 2:
+			return XFIaCR0(A);
+		case 3:
+			return XFIaCR0(B);
+		default:
+			return -EINVAL;
+		}
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct lynx_info lynx_info_ls1088a_serdes1 = {
+	.get_pccr = ls1088a_serdes1_get_pccr,
+	.get_pcvt_offset = ls1088a_serdes1_get_pcvt_offset,
+	.pll_read_configuration = lynx_10g_pll_read_configuration,
+	.lane_read_configuration = lynx_10g_lane_read_configuration,
+	.cdr_lock_check = lynx_10g_cdr_lock_check,
+	.num_lanes = 4,
+	.index = 1,
+};
+
+static int ls2088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+				    struct lynx_pccr *pccr)
+{
+	switch (lane_mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		pccr->offset = PCCR8;
+		pccr->width = 4;
+		pccr->shift = SGMII_CFG(lane);
+		break;
+	case LANE_MODE_QSGMII:
+		switch (lane) {
+		case 2:
+		case 6:
+			pccr->shift = QSGMII_CFG(A);
+			break;
+		case 7:
+			pccr->shift = QSGMII_CFG(B);
+			break;
+		case 0:
+		case 4:
+			pccr->shift = QSGMII_CFG(C);
+			break;
+		case 1:
+		case 5:
+			pccr->shift = QSGMII_CFG(D);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		pccr->offset = PCCR9;
+		pccr->width = 3;
+		break;
+	case LANE_MODE_10GBASER:
+		pccr->offset = PCCRB;
+		pccr->width = 3;
+		pccr->shift = XFI_CFG(lane);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ls2088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		return SGMIIaCR0(lane);
+	case LANE_MODE_QSGMII:
+		switch (lane) {
+		case 2:
+		case 6:
+			return QSGMIIaCR0(A);
+		case 7:
+			return QSGMIIaCR0(B);
+		case 0:
+		case 4:
+			return QSGMIIaCR0(C);
+		case 1:
+		case 5:
+			return QSGMIIaCR0(D);
+		default:
+			return -EINVAL;
+		}
+	case LANE_MODE_10GBASER:
+		return XFIaCR0(lane);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct lynx_info lynx_info_ls2088a_serdes1 = {
+	.get_pccr = ls2088a_serdes1_get_pccr,
+	.get_pcvt_offset = ls2088a_serdes1_get_pcvt_offset,
+	.pll_read_configuration = lynx_10g_pll_read_configuration,
+	.lane_read_configuration = lynx_10g_lane_read_configuration,
+	.cdr_lock_check = lynx_10g_cdr_lock_check,
+	.num_lanes = 8,
+	.index = 1,
+};
+
+static int ls2088a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane,
+				    struct lynx_pccr *pccr)
+{
+	switch (lane_mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		pccr->offset = PCCR8;
+		pccr->width = 4;
+		pccr->shift = SGMII_CFG(lane);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ls2088a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
+{
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		return SGMIIaCR0(lane);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct lynx_info lynx_info_ls2088a_serdes2 = {
+	.get_pccr = ls2088a_serdes2_get_pccr,
+	.get_pcvt_offset = ls2088a_serdes2_get_pcvt_offset,
+	.pll_read_configuration = lynx_10g_pll_read_configuration,
+	.lane_read_configuration = lynx_10g_lane_read_configuration,
+	.cdr_lock_check = lynx_10g_cdr_lock_check,
+	.num_lanes = 8,
+	.index = 2,
+};
+
+/* Halting puts the lane in a mode in which it can be reconfigured */
+static void lynx_10g_lane_halt(struct phy *phy)
+{
+	struct lynx_lane *lane = phy_get_drvdata(phy);
+
+	/* Issue a reset request */
+	lynx_lane_rmw(lane, LNaGCR0,
+		      LNaGCR0_RRST_ON | LNaGCR0_TRST_ON,
+		      LNaGCR0_RRST | LNaGCR0_TRST);
+
+	/* The RM says to wait for at least 50ns */
+	usleep_range(1, 2);
+}
+
+static void lynx_10g_lane_reset(struct phy *phy)
+{
+	struct lynx_lane *lane = phy_get_drvdata(phy);
+
+	/* Finalize the reset request */
+	lynx_lane_rmw(lane, LNaGCR0,
+		      LNaGCR0_RRST_OFF | LNaGCR0_TRST_OFF,
+		      LNaGCR0_RRST | LNaGCR0_TRST);
+}
+
+static int lynx_10g_power_off(struct phy *phy)
+{
+	struct lynx_lane *lane = phy_get_drvdata(phy);
+
+	if (!lane->powered_up)
+		return 0;
+
+	/* Issue a reset request with the power down bits set */
+	lynx_lane_rmw(lane, LNaGCR0,
+		      LNaGCR0_RRST_ON | LNaGCR0_TRST_ON |
+		      LNaGCR0_RX_PD | LNaGCR0_TX_PD,
+		      LNaGCR0_RRST | LNaGCR0_TRST |
+		      LNaGCR0_RX_PD | LNaGCR0_TX_PD);
+
+	/* The RM says to wait for at least 50ns */
+	usleep_range(1, 2);
+
+	lane->powered_up = false;
+
+	return 0;
+}
+
+static int lynx_10g_power_on(struct phy *phy)
+{
+	struct lynx_lane *lane = phy_get_drvdata(phy);
+
+	if (lane->powered_up)
+		return 0;
+
+	/* RM says that to enable a previously powered down lane, set
+	 * LNmGCR0[{R,T}X_PD]=0, wait 15 us, then set LNmGCR0[{R,T}RST]=1.
+	 */
+	lynx_lane_rmw(lane, LNaGCR0, 0, LNaGCR0_RX_PD | LNaGCR0_TX_PD);
+	usleep_range(150, 300);
+	lynx_10g_lane_reset(phy);
+
+	lane->powered_up = true;
+
+	return 0;
+}
+
+static void lynx_10g_lane_set_nrate(struct lynx_lane *lane,
+				    struct lynx_pll *pll,
+				    enum lynx_lane_mode mode)
+{
+	enum lynx_10g_rat_sel nrate;
+
+	switch (pll->frate_sel) {
+	case PLLnCR0_FRATE_5G:
+		switch (mode) {
+		case LANE_MODE_1000BASEX_SGMII:
+			nrate = RAT_SEL_QUARTER;
+			break;
+		case LANE_MODE_QSGMII:
+			nrate = RAT_SEL_FULL;
+			break;
+		default:
+			return;
+		}
+		break;
+	case PLLnCR0_FRATE_3_125G:
+		switch (mode) {
+		case LANE_MODE_2500BASEX:
+			nrate = RAT_SEL_FULL;
+			break;
+		default:
+			return;
+		}
+		break;
+	case PLLnCR0_FRATE_5_15625G:
+		switch (mode) {
+		case LANE_MODE_10GBASER:
+		case LANE_MODE_USXGMII:
+		case LANE_MODE_10G_QXGMII:
+			nrate = RAT_SEL_DOUBLE;
+			break;
+		default:
+			return;
+		}
+		break;
+	default:
+		return;
+	}
+
+	lynx_lane_rmw(lane, LNaGCR0,
+		      FIELD_PREP(LNaGCR0_TRAT_SEL, nrate) |
+		      FIELD_PREP(LNaGCR0_RRAT_SEL, nrate),
+		      LNaGCR0_RRAT_SEL | LNaGCR0_TRAT_SEL);
+}
+
+static void lynx_10g_lane_set_pll(struct lynx_lane *lane,
+				  struct lynx_pll *pll)
+{
+	if (pll->id == 0) {
+		lynx_lane_rmw(lane, LNaGCR0,
+			      LNaGCR0_RPLL_PLLF | LNaGCR0_TPLL_PLLF,
+			      LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK);
+	} else {
+		lynx_lane_rmw(lane, LNaGCR0,
+			      LNaGCR0_RPLL_PLLS | LNaGCR0_TPLL_PLLS,
+			      LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK);
+	}
+}
+
+static void lynx_10g_lane_remap_pll(struct lynx_lane *lane,
+				    enum lynx_lane_mode lane_mode)
+{
+	struct lynx_priv *priv = lane->priv;
+	struct lynx_pll *pll;
+
+	/* Switch to the PLL that works with this interface type */
+	pll = lynx_pll_get(priv, lane_mode);
+	if (unlikely(!pll))
+		return;
+
+	lynx_10g_lane_set_pll(lane, pll);
+
+	/* Choose the portion of clock net to be used on this lane */
+	lynx_10g_lane_set_nrate(lane, pll, lane_mode);
+}
+
+static void lynx_10g_lane_change_proto_conf(struct lynx_lane *lane,
+					    enum lynx_lane_mode mode)
+{
+	const struct lynx_10g_proto_conf *conf = &lynx_10g_proto_conf[mode];
+
+	lynx_lane_rmw(lane, LNaGCR0,
+		      FIELD_PREP(LNaGCR0_PROTS, conf->proto_sel) |
+		      FIELD_PREP(LNaGCR0_IF20BIT_EN, conf->if20bit_en),
+		      LNaGCR0_PROTS | LNaGCR0_IF20BIT_EN);
+	lynx_lane_rmw(lane, LNaGCR1,
+		      FIELD_PREP(LNaGCR1_REIDL_TH, conf->reidl_th) |
+		      FIELD_PREP(LNaGCR1_REIDL_ET_MSB, conf->reidl_et_msb) |
+		      FIELD_PREP(LNaGCR1_REIDL_ET_SEL, conf->reidl_et_sel) |
+		      FIELD_PREP(LNaGCR1_REIDL_EX_MSB, conf->reidl_ex_msb) |
+		      FIELD_PREP(LNaGCR1_REIDL_EX_SEL, conf->reidl_ex_sel) |
+		      FIELD_PREP(LNaGCR1_ISLEW_RCTL, conf->islew_rctl) |
+		      FIELD_PREP(LNaGCR1_OSLEW_RCTL, conf->oslew_rctl),
+		      LNaGCR1_REIDL_TH |
+		      LNaGCR1_REIDL_ET_MSB | LNaGCR1_REIDL_ET_SEL |
+		      LNaGCR1_REIDL_EX_MSB | LNaGCR1_REIDL_EX_SEL |
+		      LNaGCR1_ISLEW_RCTL | LNaGCR1_OSLEW_RCTL);
+	lynx_lane_rmw(lane, LNaRECR0,
+		      FIELD_PREP(LNaRECR0_RXEQ_BST, conf->rxeq_bst) |
+		      FIELD_PREP(LNaRECR0_GK2OVD, conf->gk2ovd) |
+		      FIELD_PREP(LNaRECR0_GK3OVD, conf->gk3ovd) |
+		      FIELD_PREP(LNaRECR0_GK2OVD_EN, conf->gk2ovd_en) |
+		      FIELD_PREP(LNaRECR0_GK3OVD_EN, conf->gk3ovd_en) |
+		      FIELD_PREP(LNaRECR0_BASE_WAND, conf->base_wand),
+		      LNaRECR0_RXEQ_BST | LNaRECR0_GK2OVD | LNaRECR0_GK3OVD |
+		      LNaRECR0_GK2OVD_EN | LNaRECR0_GK3OVD_EN |
+		      LNaRECR0_BASE_WAND);
+	lynx_lane_rmw(lane, LNaTECR0,
+		      FIELD_PREP(LNaTECR0_TEQ_TYPE, conf->teq_type) |
+		      FIELD_PREP(LNaTECR0_SGN_PREQ, conf->sgn_preq) |
+		      FIELD_PREP(LNaTECR0_RATIO_PREQ, conf->ratio_preq) |
+		      FIELD_PREP(LNaTECR0_SGN_POST1Q, conf->sgn_post1q) |
+		      FIELD_PREP(LNaTECR0_RATIO_PST1Q, conf->ratio_post1q) |
+		      FIELD_PREP(LNaTECR0_ADPT_EQ, conf->adpt_eq) |
+		      FIELD_PREP(LNaTECR0_AMP_RED, conf->amp_red),
+		      LNaTECR0_TEQ_TYPE | LNaTECR0_SGN_PREQ |
+		      LNaTECR0_RATIO_PREQ | LNaTECR0_SGN_POST1Q |
+		      LNaTECR0_RATIO_PST1Q | LNaTECR0_ADPT_EQ |
+		      LNaTECR0_AMP_RED);
+	lynx_lane_write(lane, LNaTTLCR0, conf->ttlcr0);
+}
+
+static int lynx_10g_lane_disable_pcvt(struct lynx_lane *lane,
+				      enum lynx_lane_mode mode)
+{
+	struct lynx_priv *priv = lane->priv;
+	int err;
+
+	spin_lock(&priv->pcc_lock);
+
+	err = lynx_pccr_write(lane, mode, 0);
+	if (err)
+		goto out;
+
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_DIS,
+				    SGMIIaCR1_SGPCS_EN);
+		if (err)
+			goto out;
+
+		lynx_pcvt_rmw(lane, mode, CR(0),
+			      SGMIIaCR0_RST_SGM_ON | SGMIIaCR0_PD_SGM,
+			      SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM);
+		break;
+	case LANE_MODE_QSGMII:
+		err = lynx_pcvt_rmw(lane, mode, CR(0),
+				    QSGMIIaCR0_RST_QSGM_ON | QSGMIIaCR0_PD_QSGM,
+				    QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM);
+		if (err)
+			goto out;
+		break;
+	default:
+		err = 0;
+	}
+
+out:
+	spin_unlock(&priv->pcc_lock);
+
+	return err;
+}
+
+static int lynx_10g_lane_enable_pcvt(struct lynx_lane *lane,
+				     enum lynx_lane_mode mode)
+{
+	struct lynx_priv *priv = lane->priv;
+	u32 val;
+	int err;
+
+	spin_lock(&priv->pcc_lock);
+
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_EN,
+				    SGMIIaCR1_SGPCS_EN);
+		if (err)
+			goto out;
+
+		lynx_pcvt_rmw(lane, mode, CR(0), SGMIIaCR0_RST_SGM_OFF,
+			      SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM);
+		break;
+	case LANE_MODE_QSGMII:
+		err = lynx_pcvt_rmw(lane, mode, CR(0), QSGMIIaCR0_RST_QSGM_OFF,
+				    QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM);
+		if (err)
+			goto out;
+		break;
+	default:
+		err = 0;
+	}
+
+	/* If the PCS was enabled at boot time, use the backed up PCCR value to
+	 * re-enable it here, to preserve the muxing.
+	 */
+	if (lynx_10g_pccr_val_enabled(lane->default_pccr[mode])) {
+		err = lynx_pccr_write(lane, mode, lane->default_pccr[mode]);
+		goto out;
+	}
+
+	/* If the PCS was not enabled, set the PCCR to a default value which
+	 * enables it (1). The assumption is that this is the only PCS <->
+	 * SerDes lane muxing value possible.
+	 *
+	 * This is mostly useful for SGMII <-> 10GBase-R major protocol
+	 * reconfiguration, where at boot time, either the SGMII or the
+	 * 10GBase-R PCS is enabled for the lane, but not both.
+	 *
+	 * In fact, if there are multiple lane muxing options, this function
+	 * will most likely not choose the right one. For correct functionality
+	 * there, we assume that the PCS we are enabling here was found enabled
+	 * at boot time (reset default, or through PBL, or...), and we preserve
+	 * its muxing through the default_pccr branch above.
+	 */
+	val = 0;
+
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+		val |= FIELD_PREP(PCCR8_SGMIIa_CFG, 1);
+		break;
+	case LANE_MODE_QSGMII:
+		val |= FIELD_PREP(PCCR9_QSGMIIa_CFG, 1);
+		break;
+	case LANE_MODE_10G_QXGMII:
+		val |= FIELD_PREP(PCCR9_QXGMIIa_CFG, 1);
+		break;
+	case LANE_MODE_10GBASER:
+		val |= FIELD_PREP(PCCRB_XFIa_CFG, 1);
+		break;
+	case LANE_MODE_USXGMII:
+		val |= FIELD_PREP(PCCRB_SXGMIIa_CFG, 1);
+		break;
+	default:
+		err = 0;
+		goto out;
+	}
+
+	err = lynx_pccr_write(lane, mode, val);
+out:
+	spin_unlock(&priv->pcc_lock);
+
+	return err;
+}
+
+static bool lynx_10g_lane_mode_needs_rcw_override(struct lynx_lane *lane,
+						  enum lynx_lane_mode new)
+{
+	enum lynx_lane_mode curr = lane->mode;
+
+	/* Major protocol changes, which involve changing the PCS connection to
+	 * the GMII MAC with the one to the XGMII MAC, require an RCW override
+	 * procedure to reconfigure an internal mux, as documented here:
+	 * https://lore.kernel.org/linux-phy/20230810102631.bvozjer3t67r67iy@skbuf/
+	 * This is SoC-specific, and not yet implemented in drivers/soc/fsl/guts.c.
+	 *
+	 * So the supported set of protocols depends on the initial lane mode.
+	 *
+	 * Minor protocol changes (SGMII <-> 1000Base-X <-> 2500Base-X or
+	 * 10GBase-R <-> USXGMII) are supported.
+	 */
+	if ((lynx_lane_mode_uses_gmii_mac(curr) &&
+	     lynx_lane_mode_uses_xgmii_mac(new)) ||
+	    (lynx_lane_mode_uses_xgmii_mac(curr) &&
+	     lynx_lane_mode_uses_gmii_mac(new)))
+		return true;
+
+	return false;
+}
+
+static int lynx_10g_validate(struct phy *phy, enum phy_mode mode, int submode,
+			     union phy_configure_opts *opts)
+{
+	struct lynx_lane *lane = phy_get_drvdata(phy);
+	enum lynx_lane_mode lane_mode;
+	int err;
+
+	err = lynx_phy_mode_to_lane_mode(phy, mode, submode, &lane_mode);
+	if (err)
+		return err;
+
+	if (lynx_10g_lane_mode_needs_rcw_override(lane, lane_mode))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int lynx_10g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+	struct lynx_lane *lane = phy_get_drvdata(phy);
+	bool powered_up = lane->powered_up;
+	enum lynx_lane_mode lane_mode;
+	int err;
+
+	err = lynx_10g_validate(phy, mode, submode, NULL);
+	if (err)
+		return err;
+
+	lane_mode = phy_interface_to_lane_mode(submode);
+	/* lynx_10g_validate() already made sure the lane_mode is supported */
+
+	if (lane_mode == lane->mode)
+		return 0;
+
+	/* If the lane is powered up, put the lane into the halt state while
+	 * the reconfiguration is being done.
+	 */
+	if (powered_up)
+		lynx_10g_lane_halt(phy);
+
+	err = lynx_10g_lane_disable_pcvt(lane, lane->mode);
+	if (err)
+		goto out;
+
+	lynx_10g_lane_change_proto_conf(lane, lane_mode);
+	lynx_10g_lane_remap_pll(lane, lane_mode);
+	WARN_ON(lynx_10g_lane_enable_pcvt(lane, lane_mode));
+
+	lane->mode = lane_mode;
+
+out:
+	if (powered_up) {
+		/* The RM says to wait for at least 120 ns */
+		usleep_range(1, 2);
+		lynx_10g_lane_reset(phy);
+	}
+
+	return err;
+}
+
+static int lynx_10g_init(struct phy *phy)
+{
+	struct lynx_lane *lane = phy_get_drvdata(phy);
+
+	/* Mark the fact that the lane was init */
+	lane->init = true;
+
+	/* SerDes lanes are powered on at boot time. Any lane that is
+	 * managed by this driver will get powered off when its consumer
+	 * calls phy_init().
+	 */
+	lane->powered_up = true;
+	lynx_10g_power_off(phy);
+
+	return 0;
+}
+
+static int lynx_10g_exit(struct phy *phy)
+{
+	struct lynx_lane *lane = phy_get_drvdata(phy);
+
+	/* The lane returns to the state where it isn't managed by the
+	 * consumer, so we must treat is as if it isn't initialized, and always
+	 * powered on.
+	 */
+	lane->init = false;
+	lane->powered_up = false;
+	lynx_10g_power_on(phy);
+
+	return 0;
+}
+
+static const struct phy_ops lynx_10g_ops = {
+	.init		= lynx_10g_init,
+	.exit		= lynx_10g_exit,
+	.power_on	= lynx_10g_power_on,
+	.power_off	= lynx_10g_power_off,
+	.set_mode	= lynx_10g_set_mode,
+	.validate	= lynx_10g_validate,
+	.owner		= THIS_MODULE,
+};
+
+static int lynx_10g_probe(struct platform_device *pdev)
+{
+	return lynx_probe(pdev, of_device_get_match_data(&pdev->dev),
+			  &lynx_10g_ops);
+}
+
+static const struct of_device_id lynx_10g_of_match_table[] = {
+	{ .compatible = "fsl,ls1028a-serdes", .data = &lynx_info_ls1028a },
+	{ .compatible = "fsl,ls1046a-serdes1", .data = &lynx_info_ls1046a_serdes1 },
+	{ .compatible = "fsl,ls1046a-serdes2", .data = &lynx_info_ls1046a_serdes2 },
+	{ .compatible = "fsl,ls1088a-serdes1", .data = &lynx_info_ls1088a_serdes1 },
+	{ .compatible = "fsl,ls2088a-serdes1", .data = &lynx_info_ls2088a_serdes1 },
+	{ .compatible = "fsl,ls2088a-serdes2", .data = &lynx_info_ls2088a_serdes2 },
+	{}
+};
+MODULE_DEVICE_TABLE(of, lynx_10g_of_match_table);
+
+static struct platform_driver lynx_10g_driver = {
+	.probe	= lynx_10g_probe,
+	.remove	= lynx_remove,
+	.driver	= {
+		.name = "lynx-10g",
+		.of_match_table = lynx_10g_of_match_table,
+	},
+};
+module_platform_driver(lynx_10g_driver);
+
+MODULE_IMPORT_NS("PHY_FSL_LYNX");
+MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>");
+MODULE_AUTHOR("Vladimir Oltean <vladimir.oltean@nxp.com>");
+MODULE_DESCRIPTION("Lynx 10G SerDes PHY driver for Layerscape SoCs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.c b/drivers/phy/freescale/phy-fsl-lynx-core.c
index 1e411bfab404..2cfe9236ffc5 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.c
@@ -11,6 +11,12 @@ const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode)
 	switch (lane_mode) {
 	case LANE_MODE_1000BASEX_SGMII:
 		return "1000Base-X/SGMII";
+	case LANE_MODE_2500BASEX:
+		return "2500Base-X";
+	case LANE_MODE_QSGMII:
+		return "QSGMII";
+	case LANE_MODE_10G_QXGMII:
+		return "10G-QXGMII";
 	case LANE_MODE_10GBASER:
 		return "10GBase-R";
 	case LANE_MODE_USXGMII:
@@ -29,6 +35,12 @@ enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf)
 	case PHY_INTERFACE_MODE_SGMII:
 	case PHY_INTERFACE_MODE_1000BASEX:
 		return LANE_MODE_1000BASEX_SGMII;
+	case PHY_INTERFACE_MODE_2500BASEX:
+		return LANE_MODE_2500BASEX;
+	case PHY_INTERFACE_MODE_QSGMII:
+		return LANE_MODE_QSGMII;
+	case PHY_INTERFACE_MODE_10G_QXGMII:
+		return LANE_MODE_10G_QXGMII;
 	case PHY_INTERFACE_MODE_10GBASER:
 		return LANE_MODE_10GBASER;
 	case PHY_INTERFACE_MODE_USXGMII:
@@ -89,6 +101,29 @@ bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode)
 }
 EXPORT_SYMBOL_NS_GPL(lynx_lane_supports_mode, "PHY_FSL_LYNX");
 
+/* The quad protocols are fixed because the lane has multiple consumers, and
+ * one phy_set_mode_ext() affects the other consumers as well. We have no use
+ * case for dynamic protocol changing here, so disallow it.
+ */
+static enum lynx_lane_mode lynx_fixed_protocols[] = {
+	LANE_MODE_QSGMII,
+	LANE_MODE_10G_QXGMII,
+};
+
+static bool lynx_lane_restrict_fixed_mode_change(struct lynx_lane *lane,
+						 enum lynx_lane_mode new)
+{
+	enum lynx_lane_mode curr = lane->mode;
+
+	for (int i = 0; i < ARRAY_SIZE(lynx_fixed_protocols); i++)
+		if ((curr == lynx_fixed_protocols[i] ||
+		     new == lynx_fixed_protocols[i]) &&
+		     curr != new)
+			return true;
+
+	return false;
+}
+
 /* Translate the mode/submode from phy_validate() and phy_set_mode_ext() to a
  * lane_mode and return 0 if it is supported and we can transition to it from
  * the current lane mode, or return negative error otherwise.
@@ -112,6 +147,9 @@ int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode,
 	if (!lynx_lane_supports_mode(lane, tmp_lane_mode))
 		return -EINVAL;
 
+	if (lynx_lane_restrict_fixed_mode_change(lane, tmp_lane_mode))
+		return -EINVAL;
+
 	if (lane_mode)
 		*lane_mode = tmp_lane_mode;
 
diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.h b/drivers/phy/freescale/phy-fsl-lynx-core.h
index 37fa4b544faa..a60429ba9324 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-core.h
+++ b/drivers/phy/freescale/phy-fsl-lynx-core.h
@@ -9,6 +9,7 @@
 #include <soc/fsl/phy-fsl-lynx.h>
 
 #define LYNX_NUM_PLL				2
+#define LYNX_QUIRK_HAS_HARDCODED_USXGMII	BIT(0)
 
 struct lynx_priv;
 struct lynx_lane;
@@ -36,6 +37,7 @@ struct lynx_lane {
 	bool init;
 	unsigned int id;
 	enum lynx_lane_mode mode;
+	u32 default_pccr[LANE_MODE_MAX];
 };
 
 struct lynx_info {
@@ -48,6 +50,8 @@ struct lynx_info {
 	void (*cdr_lock_check)(struct lynx_lane *lane);
 	int first_lane;
 	int num_lanes;
+	int index;
+	unsigned long quirks;
 };
 
 struct lynx_priv {
diff --git a/include/soc/fsl/phy-fsl-lynx.h b/include/soc/fsl/phy-fsl-lynx.h
index 92e8272d5ae1..ff5a7d1835b5 100644
--- a/include/soc/fsl/phy-fsl-lynx.h
+++ b/include/soc/fsl/phy-fsl-lynx.h
@@ -7,10 +7,37 @@
 enum lynx_lane_mode {
 	LANE_MODE_UNKNOWN,
 	LANE_MODE_1000BASEX_SGMII,
+	LANE_MODE_2500BASEX,
+	LANE_MODE_QSGMII,
+	LANE_MODE_10G_QXGMII,
 	LANE_MODE_10GBASER,
 	LANE_MODE_USXGMII,
 	LANE_MODE_25GBASER,
 	LANE_MODE_MAX,
 };
 
+static inline bool lynx_lane_mode_uses_gmii_mac(enum lynx_lane_mode mode)
+{
+	switch (mode) {
+	case LANE_MODE_1000BASEX_SGMII:
+	case LANE_MODE_2500BASEX:
+	case LANE_MODE_QSGMII:
+	case LANE_MODE_10G_QXGMII:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool lynx_lane_mode_uses_xgmii_mac(enum lynx_lane_mode mode)
+{
+	switch (mode) {
+	case LANE_MODE_10GBASER:
+	case LANE_MODE_USXGMII:
+		return true;
+	default:
+		return false;
+	}
+}
+
 #endif /* __PHY_FSL_LYNX_H_ */
-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH v3 0/9] ARM: dts: aspeed: anacapa: restructure devicetree for development-phase
From: Colin Huang @ 2026-06-10 15:16 UTC (permalink / raw)
  To: Andrew Jeffery
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
	colin.huang2, Carl Lee, Rex Fu, Andy Chung, Peter Shen
In-Reply-To: <2d1095b342fe0f4b1b4b99b22bb3af410d9aa60e.camel@codeconstruct.com.au>

Andrew Jeffery <andrew@codeconstruct.com.au> 於 2026年6月10日週三 下午9:04寫道:
>
> On Tue, 2026-06-02 at 21:24 +0800, Colin Huang via B4 Relay wrote:
> > This series refactors the Anacapa BMC devicetree layout to better support
> > development-phase hardware revisions (EVT1/EVT2/DVT) while keeping a platform
> > entrypoint.
> >
> > Signed-off-by: Colin Huang <u8813345@gmail.com>
> > ---
> > Changes in v3:
> > - Restructure the EVT2 devicetree to inherit from the EVT1 devicetree, making it incremental rather than standalone.
> > - Add the DVT devicetree, inheriting from the EVT2 devicetree.
> > - Enable MCTP and FRU support for the NIC.
> > - Align PDB fan GPIO numbering.
> > - Add an EEPROM device node for the NFC adaptor board.
> > - Add an additional EEPROM device node for the SCM.
> > - Add shunt resistor values for HSC monitors
> > - Link to v2: https://lore.kernel.org/r/20260409-anacapa-devlop-phase-devicetree-v2-0-68f328671653@gmail.com
> >
>
> So just to check, the changes in patches 5-8 inclusive are applicable
> to all of EVT1, EVT2 and DVT (given the way you've structured the
> includes)?

Yes, these patch apply to all development phase.

>
> > Changes in v2:
> > - Fix dtbs_check fail.
> >   Validated by following command:
> >     make dt_binding_check DT_SCHEMA_FILES=arm/aspeed/aspeed.yaml
> >     make CHECK_DTBS=y DT_SCHEMA_FILES=arm/aspeed/aspeed.yaml aspeed/aspeed-bmc-facebook-anacapa.dtb
> >     make CHECK_DTBS=y DT_SCHEMA_FILES=arm/aspeed/aspeed.yaml aspeed/aspeed-bmc-facebook-anacapa-evt1.dtb
> >     make CHECK_DTBS=y DT_SCHEMA_FILES=arm/aspeed/aspeed.yaml aspeed/aspeed-bmc-facebook-anacapa-evt2.dtb
> > - Link to v1: https://lore.kernel.org/r/20260407-anacapa-devlop-phase-devicetree-v1-0-97b96367cac3@gmail.com
> >
> > ---
> > Andy Chung (1):
> >       ARM: dts: aspeed: anacapa: Enable MCTP and FRU for NIC
> >
> > Carl Lee (1):
> >       ARM: dts: aspeed: anacapa: Add eeprom device node for NFC adaptor board
> >
> > Colin Huang (5):
> >       dt-bindings: arm: aspeed: add Anacapa EVT1 EVT2 DVT board
> >       ARM: dts: aspeed: anacapa: add EVT1 devicetree and point wrapper to it
> >       ARM: dts: aspeed: anacapa: add EVT2 devicetree inheriting EVT1
> >       ARM: dts: aspeed: anacapa: add DVT devicetree inheriting EVT2
> >       ARM: dts: aspeed: anacapa: add additional EEPROM node for SCM
>
> If you need to respin this series for some reason, can you please
> capitalise the first word of the short description (the bit after the
> last ':') for the commits above and the one below?
>

Got it.  Capitalise the first word.of the short description.

> >
> > Peter Shen (1):
> >       ARM: dts: aspeed: anacapa: evt2: add shunt resistor values for HSC monitors
> >
> > Rex Fu (1):
> >       ARM: dts: aspeed: anacapa: Align PDB fan GPIO numbering
> >
> >  .../devicetree/bindings/arm/aspeed/aspeed.yaml     |    3 +
> >  .../dts/aspeed/aspeed-bmc-facebook-anacapa-dvt.dts |  178 +++
> >  .../aspeed/aspeed-bmc-facebook-anacapa-evt1.dts    | 1179 ++++++++++++++++++++
> >  .../aspeed/aspeed-bmc-facebook-anacapa-evt2.dts    |  228 ++++
> >  .../dts/aspeed/aspeed-bmc-facebook-anacapa.dts     | 1077 +-----------------
> >  5 files changed, 1589 insertions(+), 1076 deletions(-)
> > ---
> > base-commit: 7ca1caf017d34396397b19fb4de9ecef256f4acc
> > change-id: 20260407-anacapa-devlop-phase-devicetree-4101d3f312c0
> >
> > Best regards,
>
> Andrew


^ permalink raw reply


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