Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v3 2/2] media: nxp: imx8-isi: Prioritize pending buffers over discard buffers
From: Laurent Pinchart @ 2026-05-20 17:18 UTC (permalink / raw)
  To: Guoniu Zhou
  Cc: Mauro Carvalho Chehab, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Stefan Riedmueller,
	Jacopo Mondi, Christian Hemp, linux-media, imx, linux-arm-kernel,
	linux-kernel, Alexi Birlinger, Dong Aisheng, Guoniu Zhou
In-Reply-To: <20260520171026.GA10336@killaraus.ideasonboard.com>

On Wed, May 20, 2026 at 07:10:27PM +0200, Laurent Pinchart wrote:
> Hello Guoniu,
> 
> Thank you for the patch.
> 
> On Fri, Mar 20, 2026 at 02:42:02PM +0800, Guoniu Zhou wrote:
> > From: Guoniu Zhou <guoniu.zhou@nxp.com>
> > 
> > The number of times to use the discard buffer is determined by the
> > out_pending list size:
> > 
> >   discard = list_empty(&video->out_pending) ? 2
> >             : list_is_singular(&video->out_pending) ? 1
> > 	    : 0;
> > 
> > In the current buffer selection logic, when both discard and pending
> > buffers are available, the driver fills hardware slots with discard
> > buffers first which results in an unnecessary frame drop even though
> > a user buffer was queued and ready.
> > 
> > Change the buffer selection logic to use pending buffers first (up to
> > the number available), and only use discard buffers to fill remaining
> > slots when insufficient pending buffers are queued.
> > 
> > This improves behavior by:
> > - Reducing discarded frames at stream start when user buffers are ready
> > - Decreasing latency in delivering captured frames to user-space
> > - Ensuring user buffers are utilized as soon as they are queued
> > - Improving overall buffer utilization efficiency
> 
> There's a bit of repeat here, but that's OK.
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> > Signed-off-by: Guoniu Zhou <guoniu.zhou@nxp.com>
> > ---
> > Changes in v3:
> > - Expanded commit message to explain the problem in current driver and the
> >   benefits gained from this change
> > - No code changes
> > 
> > Changes in v2:
> > - Replace "This ensures" with "ensure"
> > - Put example from commit message to comment in driver suggested by Frank
> >   https://lore.kernel.org/linux-media/20260311-isi_min_buffers-v1-0-c9299d6e8ae6@nxp.com/T/#m2774912ed31553ef1fdcc840bd6eae53a03ecccd
> > ---
> >  drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c | 9 ++++++++-
> >  1 file changed, 8 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
> > index 1be3a728f32f..77ebff03323a 100644
> > --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
> > +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
> > @@ -792,7 +792,14 @@ static void mxc_isi_video_queue_first_buffers(struct mxc_isi_video *video)
> >  		struct mxc_isi_buffer *buf;
> >  		struct list_head *list;
> >  
> > -		list = i < discard ? &video->out_discard : &video->out_pending;
> > +		/*
> > +		 * Queue buffers: prioritize pending buffers, then discard buffers
> > +		 * For example:
> > +		 * - 2 pending buffers: both slots use pending buffers
> > +		 * - 1 pending buffer: first slot uses pending, second uses discard
> > +		 * - 0 pending buffers: both slots use discard buffers
> > +		 */

Having a second look, I think this is a bit too verbose. Unless you
object, I'll write

		 * Queue buffers: prioritize pending buffers, then discard
		 * buffers.

No need to submit a new version.

> > +		list = (i < 2 - discard) ? &video->out_pending : &video->out_discard;
> >  		buf = list_first_entry(list, struct mxc_isi_buffer, list);
> >  
> >  		mxc_isi_channel_set_outbuf(video->pipe, buf->dma_addrs, buf_id);

-- 
Regards,

Laurent Pinchart


^ permalink raw reply

* Re: [PATCH v4 1/3] PCI: Allow ATS to be always on for CXL.cache capable devices
From: Nicolin Chen @ 2026-05-20 17:29 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Bjorn Helgaas, will, robin.murphy, bhelgaas, joro, praan,
	baolu.lu, kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
	linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
	linux-cxl, nirmoyd
In-Reply-To: <20260520142043.GT3602937@nvidia.com>

On Wed, May 20, 2026 at 11:20:43AM -0300, Jason Gunthorpe wrote:
> On Tue, May 19, 2026 at 06:04:18PM -0700, Nicolin Chen wrote:
> 
> > > Yeah, that's fair, so let's rename it to 
> > > 
> > > pci_translated_required()
> > > 
> > > ie the device requires translated requests to function. This is what
> > > CXL.cache implies (IIRC I was told the spec specifically says this)
> > > 
> > > Requiring translated requests implies you have to enable ATS in the
> > > system.
> > 
> > Perhaps we could let IOMMU drivers check:
> >   pci_cxl_is_cache_capable() || pci_dev_specific_is_pre_cxl()
> > directly?
> 
> I'd rather have a single function.

OK. Can we use pci_ats_required()?

CXL spec explicitly used "ATS" when stating the requirement of
CXL.cache). And it'd fit into the existing pci_ats_ functions.

Nicolin


^ permalink raw reply

* Re: [PATCH v3 1/2] media: nxp: imx8-isi: Fix potential out-of-bounds issues
From: Laurent Pinchart @ 2026-05-20 17:41 UTC (permalink / raw)
  To: Guoniu Zhou
  Cc: Mauro Carvalho Chehab, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Stefan Riedmueller,
	Jacopo Mondi, Christian Hemp, Frank Li, Dong Aisheng, linux-media,
	imx, linux-arm-kernel, linux-kernel, Guoniu Zhou, stable
In-Reply-To: <20260323-isi-v3-1-8df53b24e622@oss.nxp.com>

On Mon, Mar 23, 2026 at 04:33:30PM +0800, Guoniu Zhou wrote:
> From: Guoniu Zhou <guoniu.zhou@nxp.com>
> 
> The maximum downscaling factor supported by ISI can be up to 16. Add
> minimum value constraint before applying the setting to hardware.
> Otherwise, the process will not respond even when Ctrl+C is executed.
> 
> Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISI driver")
> Cc: stable@vger.kernel.org
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Signed-off-by: Guoniu Zhou <guoniu.zhou@nxp.com>
> ---
> Changes in v3:
> - Replace CLAMP_DOWNSCALE_16 macro with inline function
> - Adjust downscale threshold from 0x4000 to 0x2000
> - Clarify downscaling limit in comment
> ---
>  drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h | 16 ++++++++++++++++
>  drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c   |  2 +-
>  drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c  | 11 ++++++++---
>  drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c | 13 ++++++++-----
>  4 files changed, 33 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h
> index 3cbd35305af0..822466445b72 100644
> --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h
> +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h
> @@ -11,6 +11,7 @@
>  #define __MXC_ISI_CORE_H__
>  
>  #include <linux/list.h>
> +#include <linux/math.h>
>  #include <linux/mutex.h>
>  #include <linux/spinlock.h>
>  #include <linux/types.h>
> @@ -413,4 +414,19 @@ static inline void mxc_isi_debug_cleanup(struct mxc_isi_dev *isi)
>  }
>  #endif
>  
> +/*
> + * ISI scaling engine works in two parts: it performs pre-decimation of
> + * the image followed by bilinear filtering to achieve the desired
> + * downscaling factor.
> + *
> + * The decimation filter provides a maximum downscaling factor of 8, and
> + * the subsequent bilinear filter provides a maximum downscaling factor
> + * of 2. Combined, the maximum scaling factor can be up to 16.
> + */
> +static inline unsigned int
> +mxc_isi_clamp_downscale_16(unsigned int val, unsigned int max_val)
> +{
> +	return clamp(val, max(1U, DIV_ROUND_UP(max_val, 16)), max_val);
> +}
> +
>  #endif /* __MXC_ISI_CORE_H__ */
> diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c
> index 9225a7ac1c3e..37e59d687ed7 100644
> --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c
> +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c
> @@ -11,7 +11,7 @@
>  #include "imx8-isi-core.h"
>  #include "imx8-isi-regs.h"
>  
> -#define	ISI_DOWNSCALE_THRESHOLD		0x4000
> +#define	ISI_DOWNSCALE_THRESHOLD		0x2000

This should be split to a separate patch as it's a separate fix.

>  static inline u32 mxc_isi_read(struct mxc_isi_pipe *pipe, u32 reg)
>  {
> diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
> index a39ad7a1ab18..a0e2061f4344 100644
> --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
> +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
> @@ -508,10 +508,15 @@ __mxc_isi_m2m_try_fmt_vid(struct mxc_isi_m2m_ctx *ctx,
>  			  struct v4l2_pix_format_mplane *pix,
>  			  const enum mxc_isi_video_type type)
>  {
> +	const struct v4l2_pix_format_mplane *format =
> +		&ctx->queues.out.format;

This can go in the 'if' below.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

I'll take this patch without the ISI_DOWNSCALE_THRESHOLD change in my
tree, and will send a separate patch for ISI_DOWNSCALE_THRESHOLD.

> +
>  	if (type == MXC_ISI_VIDEO_M2M_CAP) {
> -		/* Downscaling only  */
> -		pix->width = min(pix->width, ctx->queues.out.format.width);
> -		pix->height = min(pix->height, ctx->queues.out.format.height);
> +		/* Downscaling only, by up to 16. */
> +		pix->width = mxc_isi_clamp_downscale_16(pix->width,
> +							format->width);
> +		pix->height = mxc_isi_clamp_downscale_16(pix->height,
> +							 format->height);
>  	}
>  
>  	return mxc_isi_format_try(ctx->m2m->pipe, pix, type);
> diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
> index a41c51dd9ce0..b290821d03d2 100644
> --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
> +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
> @@ -641,16 +641,19 @@ static int mxc_isi_pipe_set_selection(struct v4l2_subdev *sd,
>  			/* Composing is supported on the sink only. */
>  			return -EINVAL;
>  
> -		/* The sink crop is bound by the sink format downscaling only). */
> +		/*
> +		 * The ISI supports downscaling only, with a factor up to 16.
> +		 * Clamp the compose rectangle size accordingly.
> +		 */
>  		format = mxc_isi_pipe_get_pad_format(pipe, state,
>  						     MXC_ISI_PIPE_PAD_SINK);
>  
>  		sel->r.left = 0;
>  		sel->r.top = 0;
> -		sel->r.width = clamp(sel->r.width, MXC_ISI_MIN_WIDTH,
> -				     format->width);
> -		sel->r.height = clamp(sel->r.height, MXC_ISI_MIN_HEIGHT,
> -				      format->height);
> +		sel->r.width = mxc_isi_clamp_downscale_16(sel->r.width,
> +							  format->width);
> +		sel->r.height = mxc_isi_clamp_downscale_16(sel->r.height,
> +							   format->height);
>  
>  		rect = mxc_isi_pipe_get_pad_compose(pipe, state,
>  						    MXC_ISI_PIPE_PAD_SINK);
> 

-- 
Regards,

Laurent Pinchart


^ permalink raw reply

* Re: [PATCH] Documentation: KVM: Document guest-visible compatibility expectations
From: Oliver Upton @ 2026-05-20 17:47 UTC (permalink / raw)
  To: David Woodhouse
  Cc: Paolo Bonzini, Marc Zyngier, Will Deacon, Jonathan Corbet,
	Shuah Khan, kvm, Linux Doc Mailing List,
	Kernel Mailing List, Linux, Sean Christopherson, Jim Mattson,
	Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
	Raghavendra Rao Ananta, Eric Auger, Kees Cook, Arnd Bergmann,
	Nathan Chancellor, linux-arm-kernel, kvmarm, linux-kselftest
In-Reply-To: <add71b6f61edc6357e1fddad83273b2cba697d10.camel@infradead.org>

On Wed, May 20, 2026 at 12:33:52AM +0100, David Woodhouse wrote:
> On Tue, 2026-05-19 at 15:57 -0700, Oliver Upton wrote:
> > What ifs and maybes do not meet the bar, in my opinion, for preserving
> > bug emulation in KVM. Of course there could be a little flexibility with
> > that but we need to have some way of discriminating between bug fixes
> > and genuine guest expectations around the behavior of virtual hardware.
> 
> I believe you have this completely backwards.

No, I really don't.

Leaving every bugfix that could _possibly_ have a guest-visible impact
subject to drive-by scrutiny many years after the dust has settled is
not an acceptable working dynamic. Especially since it would appear
that the rest of the ecosystem has long since moved on from this
particular issue.

If this matters to you so deeply then please, be part of the solution
instead. You may find that reviewing patches leads to better outcomes
than getting belligerent with the arm64 folks every time you guys
decide to rebase your kernel. Hell, hypotheticals actually have a lot
more weight in the context of a review. And if your testing is extensive
enough to catch these sort of subtleties, don't you think it's better
done against mainline?

Maybe it's just me but I am left feeling disappointed that we all
haven't found a productive way of working together. I've tried to bridge
the gap here; we obviously need to do something that at least fixes the
UAPI breakage. Although apparently we don't even care to meet that low
of bar.

> A stable and mature platform doesn't get to play in its ivory tower and
> randomly inflict breakage on guests because they "deserve it".

Really? Aren't you asking for us to emulate something completely broken
for you?

Thanks,
Oliver


^ permalink raw reply

* Re: [PATCH v4 1/3] PCI: Allow ATS to be always on for CXL.cache capable devices
From: Bjorn Helgaas @ 2026-05-20 17:47 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: Jason Gunthorpe, will, robin.murphy, bhelgaas, joro, praan,
	baolu.lu, kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
	linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
	linux-cxl, nirmoyd
In-Reply-To: <ag3vb4SWIfuw++vp@Asurada-Nvidia>

On Wed, May 20, 2026 at 10:29:19AM -0700, Nicolin Chen wrote:
> On Wed, May 20, 2026 at 11:20:43AM -0300, Jason Gunthorpe wrote:
> > On Tue, May 19, 2026 at 06:04:18PM -0700, Nicolin Chen wrote:
> > 
> > > > Yeah, that's fair, so let's rename it to 
> > > > 
> > > > pci_translated_required()
> > > > 
> > > > ie the device requires translated requests to function. This is what
> > > > CXL.cache implies (IIRC I was told the spec specifically says this)
> > > > 
> > > > Requiring translated requests implies you have to enable ATS in the
> > > > system.
> > > 
> > > Perhaps we could let IOMMU drivers check:
> > >   pci_cxl_is_cache_capable() || pci_dev_specific_is_pre_cxl()
> > > directly?
> > 
> > I'd rather have a single function.
> 
> OK. Can we use pci_ats_required()?
> 
> CXL spec explicitly used "ATS" when stating the requirement of
> CXL.cache). And it'd fit into the existing pci_ats_ functions.

OK by me.

You already have a comment in the code about the CXL.cache
requirement; thanks for that.

I don't know enough about CXL to know what's behind the ATS
requirement.  It sounds like it's more than a simple performance
optimization.  If you happen to know the reason, it might be worth
a short comment about that too.

Please add a one-line comment in the code about why we check
Cache_Capable instead of Cache_Enable, i.e., even if CXL.cache is not
enabled now, it may be enabled later.

Bjorn


^ permalink raw reply

* Re: [PATCH v4 2/3] PCI: Allow ATS to be always on for pre-CXL devices
From: Bjorn Helgaas @ 2026-05-20 17:50 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: jgg, will, robin.murphy, bhelgaas, joro, praan, baolu.lu,
	kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
	linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
	linux-cxl, nirmoyd
In-Reply-To: <1a8cf5e88051ab5c10417edb94df598ecbc810cf.1777269009.git.nicolinc@nvidia.com>

On Sun, Apr 26, 2026 at 10:54:01PM -0700, Nicolin Chen wrote:
> Some NVIDIA GPU/NIC devices, though they don't implement CXL config space,
> have many CXL-like properties. Call this kind "pre-CXL".
> 
> Similar to CXL.cache capability, these pre-CXL devices also require the ATS
> function even when their RIDs are IOMMU bypassed, i.e. keep ATS "always on"
> v.s. "on demand" when a non-zero PASID line gets enabled in SVA use cases.
> ...

> +/* Some pre-CXL devices require ATS when it is IOMMU-bypassed */

I guess these devices are purely PCIe, with no actual CXL
transactions, so a hint here about what leads to the ATS requirement
would be useful.  It sounds like an actual functional requirement, not
just a performance optimization.

> +bool pci_dev_specific_ats_always_on(struct pci_dev *pdev)
> +{
> +	const struct pci_dev_ats_always_on *i;
> +
> +	for (i = pci_dev_ats_always_on; i->vendor; i++) {
> +		if (i->vendor != pdev->vendor)
> +			continue;
> +		if (i->ats_always_on && i->ats_always_on(pdev))
> +			return true;
> +		if (!i->ats_always_on && i->device == pdev->device)
> +			return true;
> +	}
> +
> +	return false;
> +}
>  #endif /* CONFIG_PCI_ATS */
>  
>  /* Freescale PCIe doesn't support MSI in RC mode */
> -- 
> 2.43.0
> 


^ permalink raw reply

* Re: [PATCH v22 08/13] mfd: core: Add firmware-node support to MFD cells
From: Shivendra Pratap @ 2026-05-20 17:51 UTC (permalink / raw)
  To: Bartosz Golaszewski, Lee Jones
  Cc: linux-pm, linux-kernel, linux-arm-msm, linux-arm-kernel,
	devicetree, Florian Fainelli, Krzysztof Kozlowski,
	Dmitry Baryshkov, Mukesh Ojha, Andre Draszik, Greg Kroah-Hartman,
	Kathiravan Thirumoorthy, Srinivas Kandagatla, Bartosz Golaszewski,
	Sebastian Reichel, Mark Rutland, Lorenzo Pieralisi,
	Rafael J. Wysocki, Daniel Lezcano, Christian Loehle, Ulf Hansson,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Konrad Dybcio, Arnd Bergmann, Souvik Chakravarty, Andy Yan,
	Matthias Brugger, John Stultz, Moritz Fischer, Sudeep Holla
In-Reply-To: <f604833d-b333-4514-91fa-3cf95f99f9e7@oss.qualcomm.com>



On 18-05-2026 22:11, Shivendra Pratap wrote:
> 
> 
> On 18-05-2026 14:27, Bartosz Golaszewski wrote:
>> On Thu, 14 May 2026 16:25:49 +0200, Shivendra Pratap
>> <shivendra.pratap@oss.qualcomm.com> said:
>>> MFD core has no way to register a child device using an explicit 
>>> firmware
>>> node. This prevents drivers from registering child nodes when those 
>>> nodes
>>> do not define a compatible string. One such example is the PSCI
>>> "reboot-mode" node, which omits a compatible string as it describes
>>> boot-states provided by the underlying firmware.
>>>
>>> Extend struct mfd_cell with a callback that allows drivers to provide an
>>> explicit firmware node. The node is added to the MFD child device during
>>> registration when none is assigned by device tree, ACPI, or software
>>> matching.
>>>
>>> Suggested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
>>> Signed-off-by: Shivendra Pratap <shivendra.pratap@oss.qualcomm.com>
>>> ---
>>>   drivers/mfd/mfd-core.c   | 30 ++++++++++++++++++++++++++++++
>>>   include/linux/mfd/core.h | 14 ++++++++++++++
>>>   2 files changed, 44 insertions(+)
>>>
>>> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
>>> index 
>>> 7aa32b90cf1eb7fa0a05bf3dc506e60a262c9850..cc2a2a924d6d3044e29a9f864b536ee325ed797b 100644
>>> --- a/drivers/mfd/mfd-core.c
>>> +++ b/drivers/mfd/mfd-core.c
>>> @@ -10,6 +10,7 @@
>>>   #include <linux/kernel.h>
>>>   #include <linux/platform_device.h>
>>>   #include <linux/acpi.h>
>>> +#include <linux/fwnode.h>
>>>   #include <linux/list.h>
>>>   #include <linux/property.h>
>>>   #include <linux/mfd/core.h>
>>> @@ -148,6 +149,11 @@ static int mfd_match_of_node_to_dev(struct 
>>> platform_device *pdev,
>>>       return 0;
>>>   }
>>>
>>> +static void mfd_child_fwnode_put(void *data)
>>> +{
>>> +    fwnode_handle_put(data);
>>> +}
>>
>> Ah, this seems to answer my previous question, but...
>>
>>> +
>>>   static int mfd_add_device(struct device *parent, int id,
>>>                 const struct mfd_cell *cell,
>>>                 struct resource *mem_base,
>>> @@ -156,6 +162,7 @@ static int mfd_add_device(struct device *parent, 
>>> int id,
>>>       struct resource *res;
>>>       struct platform_device *pdev;
>>>       struct mfd_of_node_entry *of_entry, *tmp;
>>> +    struct fwnode_handle *fwnode;
>>>       bool disabled = false;
>>>       int ret = -ENOMEM;
>>>       int platform_id;
>>> @@ -224,6 +231,29 @@ static int mfd_add_device(struct device *parent, 
>>> int id,
>>>
>>>       mfd_acpi_add_device(cell, pdev);
>>>
>>> +    if (!pdev->dev.fwnode && cell->get_child_fwnode) {
>>> +        fwnode = cell->get_child_fwnode(parent);
>>> +        if (fwnode) {
>>> +            device_set_node(&pdev->dev, fwnode);
>>> +
>>> +            /*
>>> +             * platform_device_release() drops only of_node refs.
>>
>> Which is a separate problem we're discussing elsewhere. It should 
>> probably drop
>> the fwnode reference it holds, not the one of of_node.
>>
>>> +             * Track non-OF fwnodes explicitly so they are put on
>>> +             * all teardown paths.
>>> +             */
>>> +            if (!to_of_node(fwnode)) {
>>> +                ret = devm_add_action(&pdev->dev,
>>> +                              mfd_child_fwnode_put,
>>> +                              fwnode);
>>
>> What if the device never gets bound to the driver? The release will 
>> never be
>> called, this is why it's wrong to schedule devres actions for unbound 
>> devices
>> and one of the reasons for patch 1 in this series.
>>
>> What I suggest for now is: in tear-down path: see if the cell has the
>> get_child_fwnode() callback and - if so - drop the reference. Add a 
>> big, fat
>> comment saying that this must be removed if we decide to switch to 
>> dropping the
>> device's fwnode reference in platform driver core which may happen soon.
> 
> Ack. sure. lets me work it out.

Hi Lee,

While planning to address this for the next spin, it would be helpful if 
you could review and share any additional comments that should be taken 
care in next spin.

thanks,
Shivendra


^ permalink raw reply

* Re: [PATCH v4 11/24] iommu: Add iommu_report_device_broken() to quarantine a broken device
From: Jason Gunthorpe @ 2026-05-20 17:51 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <ag1guf1fHg4fE7Lw@Asurada-Nvidia>

On Wed, May 20, 2026 at 12:20:25AM -0700, Nicolin Chen wrote:
> > > I see you suggest to treat the entire batch as ATS-broken. Just to
> > > confirm: without per-SID retry, that might falsely block a healthy
> > > device in the ATC batch, right? The driver now batches all ATC_INV
> > > commands via arm_smmu_invs_end_batch().
> > 
> > Yes, it is not good, but a giant complex series is not reviewable. So
> > I'd start with trashing all the devices, then come with a narrowing.
> 
> I can take that path for now and leave a FIXME.
> 
> Another option is to not batch multiple devices, until we support
> retry (which shouldn't be hard to add since we've already done the
> coding)?

That's an interesting idea, it undoes some of the meaningful
optimization we have recently done though :\

> > We cannot eliminate parallel ATS invalidation. Two threads could be
> > concurrently processing the invs list. So it has handle it, the driver
> > is going to have to tolerate a number of redundant error events.
> 
> OK. That sounds like we still need a flag or locking so that at
> least pci_disable_ats() would not be called again. I will see
> what I can do.

I think we can call pci_disable_ats() as many times as we want, we
mostly need the driver to merge multiple error notifications for the
same event.

> > It depends on the driver, mlx5 has a FLR RAS flow for instance.
> 
> I assume a driver like that would trigger FLR flow on its own?

Yes
 
> > A driver with a device that can blow up ATS should implement the FLR
> > flow if it wants automatic RAS. It requires driver co-ordination.
> 
> Or FLR via sysfs, which I have been doing...

Yes
 
> > But I wasn't thinking we can rely on existing AER events here, yes
> > probably there will be AERs associated with the device exploding so
> > badly it cannot do ATS, but also maybe not..
> 
> So, should I put the AER injection on hold for a future work? To
> be honest, I am still not very clear how AER injection could help
> here; or is it for a case where ATC times out while device isn't
> aware of any AER fault?

Right, if we don't get an AER fault then we should ensure the ATC is
surfaced, but you have a reasonable point that it isn't so likely the
get an ATC invalidation timeout without a corresponding related AER..

Still, I'd feel better if it is was definititive and we didn't rely on
this. This further points that the driver has to merge multiple error
notifications if it gets some AERs and a new "ATC ERROR" all for the
same key event.

Jason


^ permalink raw reply

* Re: [PATCH v4 2/3] PCI: Allow ATS to be always on for pre-CXL devices
From: Jason Gunthorpe @ 2026-05-20 17:53 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Nicolin Chen, will, robin.murphy, bhelgaas, joro, praan, baolu.lu,
	kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
	linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
	linux-cxl, nirmoyd
In-Reply-To: <20260520175026.GA67027@bhelgaas>

On Wed, May 20, 2026 at 12:50:26PM -0500, Bjorn Helgaas wrote:
> On Sun, Apr 26, 2026 at 10:54:01PM -0700, Nicolin Chen wrote:
> > Some NVIDIA GPU/NIC devices, though they don't implement CXL config space,
> > have many CXL-like properties. Call this kind "pre-CXL".
> > 
> > Similar to CXL.cache capability, these pre-CXL devices also require the ATS
> > function even when their RIDs are IOMMU bypassed, i.e. keep ATS "always on"
> > v.s. "on demand" when a non-zero PASID line gets enabled in SVA use cases.
> > ...
> 
> > +/* Some pre-CXL devices require ATS when it is IOMMU-bypassed */
> 
> I guess these devices are purely PCIe, with no actual CXL
> transactions, so a hint here about what leads to the ATS requirement
> would be useful. 

Not quite, they are not actually "real" PCIe devices, these are
devices that present to the system as PCIe, can issue CXL like .cache
operations and don't use PCIe electrical.

Jason


^ permalink raw reply

* Re: [PATCH v4 1/3] PCI: Allow ATS to be always on for CXL.cache capable devices
From: Jason Gunthorpe @ 2026-05-20 17:56 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Nicolin Chen, will, robin.murphy, bhelgaas, joro, praan, baolu.lu,
	kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
	linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
	linux-cxl, nirmoyd
In-Reply-To: <20260520174758.GA66039@bhelgaas>

On Wed, May 20, 2026 at 12:47:58PM -0500, Bjorn Helgaas wrote:

> I don't know enough about CXL to know what's behind the ATS
> requirement.  It sounds like it's more than a simple performance
> optimization.  If you happen to know the reason, it might be worth
> a short comment about that too.

At the core of this is underlying physical interconnect protocols that
only work with translated addresses.

Ie CXL.cache only has a definition for translated physical in its
protocol spec. The use of true physical only is due to the cache
coherence shootdown protocol..

It is why I suggested 'pci_translated_required()' earlier, there are a
few more than CXl.cache why a device might need translated physical
addresses only.

ATS is the only way for a device to get those addresses, so
ats_required is fine too, but it sort of glosses over what is driving
it.

Jason


^ permalink raw reply

* [PATCH] clk: moxart: fix refcount leak
From: Alexander A. Klimov @ 2026-05-20 17:55 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Michael Turquette, Stephen Boyd,
	Brian Masney, Jonas Jensen, Mike Turquette,
	moderated list:ARM/MOXA ART SOC, open list:COMMON CLK FRAMEWORK,
	open list
  Cc: Alexander A. Klimov

Every value returned from of_clk_get() is supposed to be cleaned up
via clk_put() once not needed anymore.
The values here are used only for error checking,
but weren't cleaned up until now.

Fixes: c7bb4fc16ead ("clk: add MOXA ART SoCs clock driver")
Signed-off-by: Alexander A. Klimov <grandmaster@al2klimov.de>
---
 drivers/clk/clk-moxart.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c
index 3786a0153ad1..7e191b1481bb 100644
--- a/drivers/clk/clk-moxart.c
+++ b/drivers/clk/clk-moxart.c
@@ -39,6 +39,7 @@ static void __init moxart_of_pll_clk_init(struct device_node *node)
 		pr_err("%pOF: of_clk_get failed\n", node);
 		return;
 	}
+	clk_put(ref_clk);
 
 	hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1);
 	if (IS_ERR(hw)) {
@@ -83,6 +84,7 @@ static void __init moxart_of_apb_clk_init(struct device_node *node)
 		pr_err("%pOF: of_clk_get failed\n", node);
 		return;
 	}
+	clk_put(pll_clk);
 
 	hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div);
 	if (IS_ERR(hw)) {
-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH 5/8] dt-bindings: arm: ras: Introduce bindings for ARM AEST
From: Umang Chheda @ 2026-05-20 18:13 UTC (permalink / raw)
  To: Rob Herring
  Cc: Ruidong Tian, Tony Luck, Borislav Petkov, Krzysztof Kozlowski,
	Conor Dooley, Bjorn Andersson, Konrad Dybcio, catalin.marinas,
	will, lpieralisi, rafael, mark.rutland, Sudeep Holla,
	linux-arm-msm, linux-acpi, linux-arm-kernel, linux-edac,
	linux-kernel, devicetree
In-Reply-To: <20260513175823.GA1471517-robh@kernel.org>

Hello Rob,

Thanks for helping reviewing the code!

On 5/13/2026 11:28 PM, Rob Herring wrote:
> On Tue, May 05, 2026 at 05:53:49PM +0530, Umang Chheda wrote:
>> The Arm Error Source Table (AEST) specification describes how firmware
>> exposes RAS error source topology to the operating system. On ACPI
>> systems this information is provided via the AEST ACPI table.
>>
>> Introduce Device Tree bindings that provide an equivalent description
>> of AEST error sources for DT-based platforms.
>>
>> Signed-off-by: Umang Chheda <umang.chheda@oss.qualcomm.com>
>> ---
>>  .../devicetree/bindings/arm/arm,aest.yaml          | 406 +++++++++++++++++++++
>>  include/dt-bindings/arm/aest.h                     |  43 +++
>>  2 files changed, 449 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/arm,aest.yaml b/Documentation/devicetree/bindings/arm/arm,aest.yaml
>> new file mode 100644
>> index 000000000000..7809a0d38270
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/arm,aest.yaml
>> @@ -0,0 +1,406 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/arm/arm,aest.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Arm Error Source Table (AEST)
>> +
>> +maintainers:
>> +  - Umang Chheda <umang.chheda@oss.qualcomm.com>
>> +
>> +description:
>> +  The Arm Error Source Table (AEST) describes RAS error sources and their
>> +  register interfaces. Each error source exposes one or more error records
>> +  through either system registers or a memory-mapped register window, and
>> +  may signal errors via interrupts. The top-level node acts as a container
>> +  for one or more child nodes, each describing a single AEST error source.
>> +  Refer to the Arm AEST specification (DEN0085 / DDI 0587B) for details.
>> +  Flag bit constants for use in DT source files are defined in
>> +  <dt-bindings/arm/aest.h>.
>> +
>> +properties:
>> +  compatible:
>> +    const: arm,aest
>> +
>> +  "#address-cells":
>> +    const: 2
>> +
>> +  "#size-cells":
>> +    const: 2
>> +
>> +  ranges: true
>> +
>> +required:
>> +  - compatible
>> +
>> +additionalProperties: false
>> +
>> +patternProperties:
>> +  "^aest-[a-z0-9-]+(@[0-9a-f]+)?$":
>> +    type: object
>> +    description:
>> +      An AEST error source node describing one error source defined by
>> +      the Arm AEST specification.
>> +
>> +    properties:
>> +      compatible:
>> +        description:
>> +          Identifies the type of AEST error source. Each value corresponds to
>> +          a distinct error source class defined by the Arm AEST specification.
>> +          arm,aest-proxy represents a proxy error source that forwards errors
>> +          from another error source.
>> +        enum:
>> +          - arm,aest-processor
>> +          - arm,aest-memory
>> +          - arm,aest-smmu
>> +          - arm,aest-gic
>> +          - arm,aest-pcie
>> +          - arm,aest-vendor
>> +          - arm,aest-proxy
> 
> This is a fundamental difference how DT and ACPI get structured. ACPI 
> defines new table for some feature and puts everything in that table. 
> For DT, these all belong in the node for the corresponding h/w. For 
> example, if the GIC supports AEST, then that belongs in the GIC node.

Thanks for the feedback. To clarify your suggestion — should the AEST
RAS properties be added directly as properties of the hardware node
(e.g. arm,ras-num-records inside the cpu@0 node itself), or as a child
node under the hardware node (e.g. a ras-error-source {} child under cpu@0)?


> 
>> +
>> +      reg:
>> +        description:
>> +          Register ranges for the error source. Absence of reg implies
>> +          system-register access (interface type 0). A single range implies
>> +          memory-mapped access (interface type 1). Two ranges imply
>> +          single-record memory-mapped access (interface type 2).
>> +        minItems: 1
>> +        maxItems: 4
>> +
>> +      reg-names:
>> +        description:
>> +          Names for the register ranges. The base error-record window is
>> +          unnamed (or first entry). Optional named ranges provide access to
>> +          the fault-injection, error-group, and interrupt-config register
>> +          windows defined by the AEST specification.
>> +        minItems: 1
>> +        maxItems: 4
>> +        items:
>> +          enum:
>> +            - fault-inject
>> +            - err-group
>> +            - irq-config
>> +
>> +      interrupts:
>> +        description: Interrupts associated with the error source.
>> +        minItems: 1
>> +        maxItems: 2
>> +
>> +      interrupt-names:
>> +        description: Names of the interrupts associated with the error source.
>> +        minItems: 1
>> +        maxItems: 2
>> +        items:
>> +          enum:
>> +            - fhi
>> +            - eri
>> +
>> +      arm,fhi-flags:
>> +        description:
>> +          Bitmask of flags for the fault-handling interrupt (FHI), as defined
>> +          in the AEST node interrupt structure flags field. Constants are
>> +          defined in <dt-bindings/arm/aest.h> - AEST_IRQ_MODE_LEVEL (0),
>> +          AEST_IRQ_MODE_EDGE (1).
> 
> DT already has a way to define interrupt flags. Why invent something 
> new?

Ack, this flag is not needed for DT based systems, will remove this.

> 
> Rob

Thanks,
Umang




^ permalink raw reply

* Re: [PATCH v4 11/24] iommu: Add iommu_report_device_broken() to quarantine a broken device
From: Nicolin Chen @ 2026-05-20 18:13 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <20260520175123.GZ3602937@nvidia.com>

On Wed, May 20, 2026 at 02:51:23PM -0300, Jason Gunthorpe wrote:
> On Wed, May 20, 2026 at 12:20:25AM -0700, Nicolin Chen wrote:
> > > > I see you suggest to treat the entire batch as ATS-broken. Just to
> > > > confirm: without per-SID retry, that might falsely block a healthy
> > > > device in the ATC batch, right? The driver now batches all ATC_INV
> > > > commands via arm_smmu_invs_end_batch().
> > > 
> > > Yes, it is not good, but a giant complex series is not reviewable. So
> > > I'd start with trashing all the devices, then come with a narrowing.
> > 
> > I can take that path for now and leave a FIXME.
> > 
> > Another option is to not batch multiple devices, until we support
> > retry (which shouldn't be hard to add since we've already done the
> > coding)?
> 
> That's an interesting idea, it undoes some of the meaningful
> optimization we have recently done though :\

I remember you didn't like it. That's why we had the retry(), which
I feel we should keep it..

> > > We cannot eliminate parallel ATS invalidation. Two threads could be
> > > concurrently processing the invs list. So it has handle it, the driver
> > > is going to have to tolerate a number of redundant error events.
> > 
> > OK. That sounds like we still need a flag or locking so that at
> > least pci_disable_ats() would not be called again. I will see
> > what I can do.
> 
> I think we can call pci_disable_ats() as many times as we want

That triggers WARN_ON(!dev->ats_enabled) in pci_disable_ats :-(

> we
> mostly need the driver to merge multiple error notifications for the
> same event.

Yes.

> > > But I wasn't thinking we can rely on existing AER events here, yes
> > > probably there will be AERs associated with the device exploding so
> > > badly it cannot do ATS, but also maybe not..
> > 
> > So, should I put the AER injection on hold for a future work? To
> > be honest, I am still not very clear how AER injection could help
> > here; or is it for a case where ATC times out while device isn't
> > aware of any AER fault?
> 
> Right, if we don't get an AER fault then we should ensure the ATC is
> surfaced, but you have a reasonable point that it isn't so likely the
> get an ATC invalidation timeout without a corresponding related AER..
> 
> Still, I'd feel better if it is was definititive and we didn't rely on
> this. This further points that the driver has to merge multiple error
> notifications if it gets some AERs and a new "ATC ERROR" all for the
> same key event.

I feel some race here... Part of the complexity of this v4 is to deal
with concurrent device reset during the async report() between IOMMU
core and driver. Now, we add AER that could compete on the device side
as well...

I will see what I can do here, yet likely would defer it to a followup
series, given the direction is to shrink the size of the series.

Thanks
Nicolin


^ permalink raw reply

* [PATCH 6.12 374/666] perf evsel: Add alternate_hw_config and use in evsel__match
From: Greg Kroah-Hartman @ 2026-05-20 16:19 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Namhyung Kim, Ian Rogers, Kan Liang,
	James Clark, Yang Jihong, Dominique Martinet, Colin Ian King,
	Howard Chu, Yunseong Kim, Ze Gao, Yicong Yang, Weilin Wang,
	Will Deacon, Mike Leach, Jing Zhang, Yang Li, Leo Yan, ak,
	Athira Rajeev, linux-arm-kernel, Sun Haiyong, John Garry,
	Sasha Levin
In-Reply-To: <20260520162111.222830634@linuxfoundation.org>

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Ian Rogers <irogers@google.com>

[ Upstream commit 22a4db3c36034e2b034c5b88414680857fc59cf4 ]

There are cases where we want to match events like instructions and
cycles with legacy hardware values, in particular in stat-shadow's
hard coded metrics. An evsel's name isn't a good point of reference as
it gets altered, strstr would be too imprecise and re-parsing the
event from its name is silly. Instead, hold the legacy hardware event
name, determined during parsing, in the evsel for this matching case.

Inline evsel__match2 that is only used in builtin-diff.

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Cc: Yang Jihong <yangjihong@bytedance.com>
Cc: Dominique Martinet <asmadeus@codewreck.org>
Cc: Colin Ian King <colin.i.king@gmail.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Yunseong Kim <yskelg@gmail.com>
Cc: Ze Gao <zegao2021@gmail.com>
Cc: Yicong Yang <yangyicong@hisilicon.com>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Will Deacon <will@kernel.org>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
Cc: Yang Li <yang.lee@linux.alibaba.com>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: ak@linux.intel.com
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Sun Haiyong <sunhaiyong@loongson.cn>
Cc: John Garry <john.g.garry@oracle.com>
Link: https://lore.kernel.org/r/20240926144851.245903-2-james.clark@linaro.org
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Stable-dep-of: c9ef786c0970 ("perf cgroup: Update metric leader in evlist__expand_cgroup")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 tools/perf/builtin-diff.c      |  6 ++--
 tools/perf/util/evsel.c        | 21 ++++++++++++
 tools/perf/util/evsel.h        | 19 ++---------
 tools/perf/util/parse-events.c | 59 +++++++++++++++++++++-------------
 tools/perf/util/parse-events.h |  8 ++++-
 tools/perf/util/parse-events.y |  2 +-
 tools/perf/util/pmu.c          |  6 +++-
 tools/perf/util/pmu.h          |  2 +-
 8 files changed, 77 insertions(+), 46 deletions(-)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 23326dd203339..82fb7773e03e6 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -469,13 +469,13 @@ static int diff__process_sample_event(const struct perf_tool *tool,
 
 static struct perf_diff pdiff;
 
-static struct evsel *evsel_match(struct evsel *evsel,
-				      struct evlist *evlist)
+static struct evsel *evsel_match(struct evsel *evsel, struct evlist *evlist)
 {
 	struct evsel *e;
 
 	evlist__for_each_entry(evlist, e) {
-		if (evsel__match2(evsel, e))
+		if ((evsel->core.attr.type == e->core.attr.type) &&
+		    (evsel->core.attr.config == e->core.attr.config))
 			return e;
 	}
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index dda107b12b8c6..6e8d70ec05bad 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -299,6 +299,7 @@ void evsel__init(struct evsel *evsel,
 	evsel->pmu_name      = NULL;
 	evsel->group_pmu_name = NULL;
 	evsel->skippable     = false;
+	evsel->alternate_hw_config = PERF_COUNT_HW_MAX;
 }
 
 struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx)
@@ -445,6 +446,8 @@ struct evsel *evsel__clone(struct evsel *orig)
 	if (evsel__copy_config_terms(evsel, orig) < 0)
 		goto out_err;
 
+	evsel->alternate_hw_config = orig->alternate_hw_config;
+
 	return evsel;
 
 out_err:
@@ -1856,6 +1859,24 @@ static int evsel__read_tool(struct evsel *evsel, int cpu_map_idx, int thread)
 	return 0;
 }
 
+bool __evsel__match(const struct evsel *evsel, u32 type, u64 config)
+{
+
+	u32 e_type = evsel->core.attr.type;
+	u64 e_config = evsel->core.attr.config;
+
+	if (e_type != type) {
+		return type == PERF_TYPE_HARDWARE && evsel->pmu && evsel->pmu->is_core &&
+			evsel->alternate_hw_config == config;
+	}
+
+	if ((type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE) &&
+	    perf_pmus__supports_extended_type())
+		e_config &= PERF_HW_EVENT_MASK;
+
+	return e_config == config;
+}
+
 int evsel__read_counter(struct evsel *evsel, int cpu_map_idx, int thread)
 {
 	if (evsel__is_tool(evsel))
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 26574a33a7250..dc0d300776f16 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -102,6 +102,7 @@ struct evsel {
 		int			bpf_fd;
 		struct bpf_object	*bpf_obj;
 		struct list_head	config_terms;
+		u64			alternate_hw_config;
 	};
 
 	/*
@@ -395,26 +396,10 @@ u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sam
 struct tep_format_field *evsel__field(struct evsel *evsel, const char *name);
 struct tep_format_field *evsel__common_field(struct evsel *evsel, const char *name);
 
-static inline bool __evsel__match(const struct evsel *evsel, u32 type, u64 config)
-{
-	if (evsel->core.attr.type != type)
-		return false;
-
-	if ((type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE)  &&
-	    perf_pmus__supports_extended_type())
-		return (evsel->core.attr.config & PERF_HW_EVENT_MASK) == config;
-
-	return evsel->core.attr.config == config;
-}
+bool __evsel__match(const struct evsel *evsel, u32 type, u64 config);
 
 #define evsel__match(evsel, t, c) __evsel__match(evsel, PERF_TYPE_##t, PERF_COUNT_##c)
 
-static inline bool evsel__match2(struct evsel *e1, struct evsel *e2)
-{
-	return (e1->core.attr.type == e2->core.attr.type) &&
-	       (e1->core.attr.config == e2->core.attr.config);
-}
-
 int evsel__read_counter(struct evsel *evsel, int cpu_map_idx, int thread);
 
 int __evsel__read_on_cpu(struct evsel *evsel, int cpu_map_idx, int thread, bool scale);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 9a8be1e46d674..fcc4dab618bee 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -228,7 +228,7 @@ __add_event(struct list_head *list, int *idx,
 	    bool init_attr,
 	    const char *name, const char *metric_id, struct perf_pmu *pmu,
 	    struct list_head *config_terms, bool auto_merge_stats,
-	    struct perf_cpu_map *cpu_list)
+	    struct perf_cpu_map *cpu_list, u64 alternate_hw_config)
 {
 	struct evsel *evsel;
 	struct perf_cpu_map *cpus = perf_cpu_map__is_empty(cpu_list) && pmu ? pmu->cpus : cpu_list;
@@ -264,6 +264,7 @@ __add_event(struct list_head *list, int *idx,
 	evsel->auto_merge_stats = auto_merge_stats;
 	evsel->pmu = pmu;
 	evsel->pmu_name = pmu ? strdup(pmu->name) : NULL;
+	evsel->alternate_hw_config = alternate_hw_config;
 
 	if (name)
 		evsel->name = strdup(name);
@@ -286,16 +287,19 @@ struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr,
 {
 	return __add_event(/*list=*/NULL, &idx, attr, /*init_attr=*/false, name,
 			   metric_id, pmu, /*config_terms=*/NULL,
-			   /*auto_merge_stats=*/false, /*cpu_list=*/NULL);
+			   /*auto_merge_stats=*/false, /*cpu_list=*/NULL,
+			   /*alternate_hw_config=*/PERF_COUNT_HW_MAX);
 }
 
 static int add_event(struct list_head *list, int *idx,
 		     struct perf_event_attr *attr, const char *name,
-		     const char *metric_id, struct list_head *config_terms)
+		     const char *metric_id, struct list_head *config_terms,
+		     u64 alternate_hw_config)
 {
 	return __add_event(list, idx, attr, /*init_attr*/true, name, metric_id,
 			   /*pmu=*/NULL, config_terms,
-			   /*auto_merge_stats=*/false, /*cpu_list=*/NULL) ? 0 : -ENOMEM;
+			   /*auto_merge_stats=*/false, /*cpu_list=*/NULL,
+			   alternate_hw_config) ? 0 : -ENOMEM;
 }
 
 static int add_event_tool(struct list_head *list, int *idx,
@@ -315,7 +319,8 @@ static int add_event_tool(struct list_head *list, int *idx,
 	evsel = __add_event(list, idx, &attr, /*init_attr=*/true, /*name=*/NULL,
 			    /*metric_id=*/NULL, /*pmu=*/NULL,
 			    /*config_terms=*/NULL, /*auto_merge_stats=*/false,
-			    cpu_list);
+			    cpu_list,
+			    /*alternate_hw_config=*/PERF_COUNT_HW_MAX);
 	perf_cpu_map__put(cpu_list);
 	if (!evsel)
 		return -ENOMEM;
@@ -450,7 +455,7 @@ bool parse_events__filter_pmu(const struct parse_events_state *parse_state,
 static int parse_events_add_pmu(struct parse_events_state *parse_state,
 				struct list_head *list, struct perf_pmu *pmu,
 				const struct parse_events_terms *const_parsed_terms,
-				bool auto_merge_stats);
+				bool auto_merge_stats, u64 alternate_hw_config);
 
 int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
 			   struct parse_events_state *parse_state,
@@ -476,7 +481,8 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
 			 */
 			ret = parse_events_add_pmu(parse_state, list, pmu,
 						   parsed_terms,
-						   perf_pmu__auto_merge_stats(pmu));
+						   perf_pmu__auto_merge_stats(pmu),
+						   /*alternate_hw_config=*/PERF_COUNT_HW_MAX);
 			if (ret)
 				return ret;
 			continue;
@@ -507,7 +513,8 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
 
 		if (__add_event(list, idx, &attr, /*init_attr*/true, config_name ?: name,
 				metric_id, pmu, &config_terms, /*auto_merge_stats=*/false,
-				/*cpu_list=*/NULL) == NULL)
+				/*cpu_list=*/NULL,
+				/*alternate_hw_config=*/PERF_COUNT_HW_MAX) == NULL)
 			return -ENOMEM;
 
 		free_config_terms(&config_terms);
@@ -772,7 +779,7 @@ int parse_events_add_breakpoint(struct parse_events_state *parse_state,
 	name = get_config_name(head_config);
 
 	return add_event(list, &parse_state->idx, &attr, name, /*mertic_id=*/NULL,
-			 &config_terms);
+			&config_terms, /*alternate_hw_config=*/PERF_COUNT_HW_MAX);
 }
 
 static int check_type_val(struct parse_events_term *term,
@@ -1072,6 +1079,7 @@ static int config_term_pmu(struct perf_event_attr *attr,
 		if (perf_pmu__have_event(pmu, term->config)) {
 			term->type_term = PARSE_EVENTS__TERM_TYPE_USER;
 			term->no_value = true;
+			term->alternate_hw_config = true;
 		} else {
 			attr->type = PERF_TYPE_HARDWARE;
 			attr->config = term->val.num;
@@ -1384,8 +1392,9 @@ static int __parse_events_add_numeric(struct parse_events_state *parse_state,
 	name = get_config_name(head_config);
 	metric_id = get_config_metric_id(head_config);
 	ret = __add_event(list, &parse_state->idx, &attr, /*init_attr*/true, name,
-			metric_id, pmu, &config_terms, /*auto_merge_stats=*/false,
-			/*cpu_list=*/NULL) ? 0 : -ENOMEM;
+			  metric_id, pmu, &config_terms, /*auto_merge_stats=*/false,
+			  /*cpu_list=*/NULL, /*alternate_hw_config=*/PERF_COUNT_HW_MAX
+		) == NULL ? -ENOMEM : 0;
 	free_config_terms(&config_terms);
 	return ret;
 }
@@ -1443,7 +1452,7 @@ static bool config_term_percore(struct list_head *config_terms)
 static int parse_events_add_pmu(struct parse_events_state *parse_state,
 				struct list_head *list, struct perf_pmu *pmu,
 				const struct parse_events_terms *const_parsed_terms,
-				bool auto_merge_stats)
+				bool auto_merge_stats, u64 alternate_hw_config)
 {
 	struct perf_event_attr attr;
 	struct perf_pmu_info info;
@@ -1480,7 +1489,7 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state,
 				    /*init_attr=*/true, /*name=*/NULL,
 				    /*metric_id=*/NULL, pmu,
 				    /*config_terms=*/NULL, auto_merge_stats,
-				    /*cpu_list=*/NULL);
+				    /*cpu_list=*/NULL, alternate_hw_config);
 		return evsel ? 0 : -ENOMEM;
 	}
 
@@ -1501,7 +1510,8 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state,
 
 	/* Look for event names in the terms and rewrite into format based terms. */
 	if (perf_pmu__check_alias(pmu, &parsed_terms,
-				  &info, &alias_rewrote_terms, err)) {
+				  &info, &alias_rewrote_terms,
+				  &alternate_hw_config, err)) {
 		parse_events_terms__exit(&parsed_terms);
 		return -EINVAL;
 	}
@@ -1546,7 +1556,8 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state,
 	evsel = __add_event(list, &parse_state->idx, &attr, /*init_attr=*/true,
 			    get_config_name(&parsed_terms),
 			    get_config_metric_id(&parsed_terms), pmu,
-			    &config_terms, auto_merge_stats, /*cpu_list=*/NULL);
+			    &config_terms, auto_merge_stats, /*cpu_list=*/NULL,
+			    alternate_hw_config);
 	if (!evsel) {
 		parse_events_terms__exit(&parsed_terms);
 		return -ENOMEM;
@@ -1567,7 +1578,7 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state,
 }
 
 int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
-			       const char *event_name,
+			       const char *event_name, u64 hw_config,
 			       const struct parse_events_terms *const_parsed_terms,
 			       struct list_head **listp, void *loc_)
 {
@@ -1620,7 +1631,7 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
 
 		auto_merge_stats = perf_pmu__auto_merge_stats(pmu);
 		if (!parse_events_add_pmu(parse_state, list, pmu,
-					  &parsed_terms, auto_merge_stats)) {
+					  &parsed_terms, auto_merge_stats, hw_config)) {
 			struct strbuf sb;
 
 			strbuf_init(&sb, /*hint=*/ 0);
@@ -1633,7 +1644,7 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
 
 	if (parse_state->fake_pmu) {
 		if (!parse_events_add_pmu(parse_state, list, perf_pmus__fake_pmu(), &parsed_terms,
-					  /*auto_merge_stats=*/true)) {
+					  /*auto_merge_stats=*/true, hw_config)) {
 			struct strbuf sb;
 
 			strbuf_init(&sb, /*hint=*/ 0);
@@ -1674,13 +1685,15 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
 	/* Attempt to add to list assuming event_or_pmu is a PMU name. */
 	pmu = perf_pmus__find(event_or_pmu);
 	if (pmu && !parse_events_add_pmu(parse_state, *listp, pmu, const_parsed_terms,
-					/*auto_merge_stats=*/false))
+					 /*auto_merge_stats=*/false,
+					 /*alternate_hw_config=*/PERF_COUNT_HW_MAX))
 		return 0;
 
 	if (parse_state->fake_pmu) {
 		if (!parse_events_add_pmu(parse_state, *listp, perf_pmus__fake_pmu(),
 					  const_parsed_terms,
-					  /*auto_merge_stats=*/false))
+					  /*auto_merge_stats=*/false,
+					  /*alternate_hw_config=*/PERF_COUNT_HW_MAX))
 			return 0;
 	}
 
@@ -1693,7 +1706,8 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
 
 			if (!parse_events_add_pmu(parse_state, *listp, pmu,
 						  const_parsed_terms,
-						  auto_merge_stats)) {
+						  auto_merge_stats,
+						  /*alternate_hw_config=*/PERF_COUNT_HW_MAX)) {
 				ok++;
 				parse_state->wild_card_pmus = true;
 			}
@@ -1704,7 +1718,8 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
 
 	/* Failure to add, assume event_or_pmu is an event name. */
 	zfree(listp);
-	if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, const_parsed_terms, listp, loc))
+	if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, PERF_COUNT_HW_MAX,
+					const_parsed_terms, listp, loc))
 		return 0;
 
 	if (asprintf(&help, "Unable to find PMU or event on a PMU of '%s'", event_or_pmu) < 0)
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 10cc9c433116d..2b52f8d6aa29a 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -127,6 +127,12 @@ struct parse_events_term {
 	 * value is assumed to be 1. An event name also has no value.
 	 */
 	bool no_value;
+	/**
+	 * @alternate_hw_config: config is the event name but num is an
+	 * alternate PERF_TYPE_HARDWARE config value which is often nice for the
+	 * sake of quick matching.
+	 */
+	bool alternate_hw_config;
 };
 
 struct parse_events_error {
@@ -238,7 +244,7 @@ struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr,
 				      struct perf_pmu *pmu);
 
 int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
-			       const char *event_name,
+			       const char *event_name, u64 hw_config,
 			       const struct parse_events_terms *const_parsed_terms,
 			       struct list_head **listp, void *loc);
 
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index b3c51f06cbdc4..dcf47fabdfdd7 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -292,7 +292,7 @@ PE_NAME sep_dc
 	struct list_head *list;
 	int err;
 
-	err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);
+	err = parse_events_multi_pmu_add(_parse_state, $1, PERF_COUNT_HW_MAX, NULL, &list, &@1);
 	if (err < 0) {
 		struct parse_events_state *parse_state = _parse_state;
 		struct parse_events_error *error = parse_state->error;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 8b4e346808b4c..8885998c19530 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1606,7 +1606,7 @@ static int check_info_data(struct perf_pmu *pmu,
  */
 int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms,
 			  struct perf_pmu_info *info, bool *rewrote_terms,
-			  struct parse_events_error *err)
+			  u64 *alternate_hw_config, struct parse_events_error *err)
 {
 	struct parse_events_term *term, *h;
 	struct perf_pmu_alias *alias;
@@ -1638,6 +1638,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_
 						NULL);
 			return ret;
 		}
+
 		*rewrote_terms = true;
 		ret = check_info_data(pmu, alias, info, err, term->err_term);
 		if (ret)
@@ -1646,6 +1647,9 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_
 		if (alias->per_pkg)
 			info->per_pkg = true;
 
+		if (term->alternate_hw_config)
+			*alternate_hw_config = term->val.num;
+
 		list_del_init(&term->list);
 		parse_events_term__delete(term);
 	}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index bcd278b9b546f..0222124b86b92 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -220,7 +220,7 @@ __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name);
 int perf_pmu__format_type(struct perf_pmu *pmu, const char *name);
 int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms,
 			  struct perf_pmu_info *info, bool *rewrote_terms,
-			  struct parse_events_error *err);
+			  u64 *alternate_hw_config, struct parse_events_error *err);
 int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb);
 
 void perf_pmu_format__set_value(void *format, int config, unsigned long *bits);
-- 
2.53.0





^ permalink raw reply related

* Re: [PATCH v3 0/6] KVM: arm64: Don't perform vgic-v2 lazy init on timer injection
From: Oliver Upton @ 2026-05-20 18:26 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: kvmarm, linux-arm-kernel, Deepanshu Kartikey, Steffen Eiden,
	Joey Gouly, Suzuki K Poulose, Zenghui Yu
In-Reply-To: <20260520100200.543845-1-maz@kernel.org>

On Wed, May 20, 2026 at 11:01:54AM +0100, Marc Zyngier wrote:
> This is the third version of this series aiming at fixing issues with
> vgic-v2 being initialised from non-preemptible context.
> 
> * From v2 [2]:
> 
>   - Remove the PMU's irq level cache which was hidding in plain sight
> 
>   - Simplify the userspace notification of interrupt level update
> 
>   - Additional comment clarification in patch #1
> 
>   - Collected RB, with thanks
> 
> * From v1 [1]:
> 
>   - Repaint kvm_timer_irq_can_fire() to kvm_timer_enabled()
> 
>   - Drop duplicate kvm_timer_update_status() call
> 
>   - Force lazy init on the irqfd slow-path for SPIs
> 
> [1] https://lore.kernel.org/r/20260417124612.2770268-1-maz@kernel.org
> [2] https://lore.kernel.org/r/20260422100210.3008156-1-maz@kernel.org
> 
> Marc Zyngier (6):
>   KVM: arm64: timer: Repaint kvm_timer_{should,irq_can}_fire() to
>     kvm_timer_{pending,enabled}()
>   KVM: arm64: Simplify userspace notification of interrupt state
>   KVM: arm64: timer: Kill the per-timer irq level cache
>   KVM: arm64: pmu: Kill the PMU interrupt level cache
>   KVM: arm64: vgic-v2: Force vgic init on injection outside the run loop
>   KVM: arm64: vgic-v2: Don't init the vgic on in-kernel interrupt
>     injection

s/how/now/ on the first line of the changelog in the last patch... Too
lazy to draft another mail.

Reviewed-by: Oliver Upton <oupton@kernel.org>

Thanks,
Oliver


^ permalink raw reply

* Re: [PATCH v2] i2c: imx-lpi2c: fix resource leaks switching to devm_dma_request_chan()
From: Frank Li @ 2026-05-20 18:29 UTC (permalink / raw)
  To: Carlos Song (OSS)
  Cc: aisheng.dong, andi.shyti, s.hauer, kernel, festevam, carlos.song,
	linux-i2c, imx, linux-arm-kernel, linux-kernel, stable
In-Reply-To: <20260520093323.2882070-1-carlos.song@oss.nxp.com>

On Wed, May 20, 2026 at 05:33:23PM +0800, Carlos Song (OSS) wrote:
> From: Carlos Song <carlos.song@nxp.com>
>
> The LPI2C driver requests DMA channels using dma_request_chan(), but
> never releases them in lpi2c_imx_remove(), resulting in DMA channel
> leaks every time the driver is unloaded.
>
> Additionally, when lpi2c_dma_init() successfully requests the TX DMA
> channel but fails to request the RX DMA channel, the probe falls back
> to PIO mode and completes successfully. Since probe succeeds, the devres
> framework will not trigger any cleanup, leaving the TX DMA channel and
> the memory allocated for the dma structure held for the lifetime of the
> device even though DMA is never used.
>
> Switch to devm_dma_request_chan() to let the device core manage DMA
> channel lifetime automatically. Wrap all allocations within a devres
> group so that devres_release_group() can release all partially acquired
> resources when DMA init fails and probe continues in PIO mode.
>
> Fixes: a09c8b3f9047 ("i2c: imx-lpi2c: add eDMA mode support for LPI2C")
> Cc: stable@vger.kernel.org
> Signed-off-by: Carlos Song <carlos.song@nxp.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Change for v2:
>   - Wrap all allocations in lpi2c_dma_init() within a devres group so
>     that devres_release_group() releases all partially acquired resources
>     (dma structure memory, TX DMA channel) when DMA init fails and probe
>     continues in PIO mode. Without this, a successful TX channel request
>     followed by a failed RX channel request would leave the TX channel
>     and dma structure held for the lifetime of the device.
> ---
>  drivers/i2c/busses/i2c-imx-lpi2c.c | 53 ++++++++++++++++++------------
>  1 file changed, 32 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
> index 6e298424de5e..dedcc24e63ec 100644
> --- a/drivers/i2c/busses/i2c-imx-lpi2c.c
> +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
> @@ -1383,55 +1383,66 @@ static int lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx,
>  	return 0;
>  }
>
> -static void dma_exit(struct device *dev, struct lpi2c_imx_dma *dma)
> -{
> -	if (dma->chan_rx)
> -		dma_release_channel(dma->chan_rx);
> -
> -	if (dma->chan_tx)
> -		dma_release_channel(dma->chan_tx);
> -
> -	devm_kfree(dev, dma);
> -}
> -
>  static int lpi2c_dma_init(struct device *dev, dma_addr_t phy_addr)
>  {
>  	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
>  	struct lpi2c_imx_dma *dma;
> +	void *group;
>  	int ret;
>
> -	dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
> -	if (!dma)
> +	/*
> +	 * Open a devres group so that all resources allocated within
> +	 * this function can be released together if DMA init fails but
> +	 * probe continues in PIO mode.
> +	 */
> +	group = devres_open_group(dev, NULL, GFP_KERNEL);
> +	if (!group)
>  		return -ENOMEM;
>
> +	dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
> +	if (!dma) {
> +		ret = -ENOMEM;
> +		goto release_group;
> +	}
> +
>  	dma->phy_addr = phy_addr;
>
>  	/* Prepare for TX DMA: */
> -	dma->chan_tx = dma_request_chan(dev, "tx");
> +	dma->chan_tx = devm_dma_request_chan(dev, "tx");
>  	if (IS_ERR(dma->chan_tx)) {
>  		ret = PTR_ERR(dma->chan_tx);
>  		if (ret != -ENODEV && ret != -EPROBE_DEFER)
>  			dev_err(dev, "can't request DMA tx channel (%d)\n", ret);
> -		dma->chan_tx = NULL;
> -		goto dma_exit;
> +		goto release_group;
>  	}
>
>  	/* Prepare for RX DMA: */
> -	dma->chan_rx = dma_request_chan(dev, "rx");
> +	dma->chan_rx = devm_dma_request_chan(dev, "rx");
>  	if (IS_ERR(dma->chan_rx)) {
>  		ret = PTR_ERR(dma->chan_rx);
>  		if (ret != -ENODEV && ret != -EPROBE_DEFER)
>  			dev_err(dev, "can't request DMA rx channel (%d)\n", ret);
> -		dma->chan_rx = NULL;
> -		goto dma_exit;
> +		goto release_group;
>  	}
>
> +	/*
> +	 * DMA init succeeded. Remove the group marker but keep all resources
> +	 * bound to the device, they will be freed at device removal.
> +	 */
> +	devres_remove_group(dev, group);
> +
>  	lpi2c_imx->can_use_dma = true;
>  	lpi2c_imx->dma = dma;
>  	return 0;
>
> -dma_exit:
> -	dma_exit(dev, dma);
> +release_group:
> +	/*
> +	 * DMA init failed. Release ALL resources allocated inside this
> +	 * group (dma memory, TX channel if already acquired, etc.) so
> +	 * that a successful PIO-mode probe does not hold unused resources
> +	 * for the entire device lifetime.
> +	 */
> +	devres_release_group(dev, group);
>  	return ret;
>  }
>
> --
> 2.43.0
>


^ permalink raw reply

* Re: [PATCH] Documentation: KVM: Document guest-visible compatibility expectations
From: David Woodhouse @ 2026-05-20 18:29 UTC (permalink / raw)
  To: Oliver Upton
  Cc: Paolo Bonzini, Marc Zyngier, Will Deacon, Jonathan Corbet,
	Shuah Khan, kvm, Linux Doc Mailing List,
	Kernel Mailing List, Linux, Sean Christopherson, Jim Mattson,
	Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
	Raghavendra Rao Ananta, Eric Auger, Kees Cook, Arnd Bergmann,
	Nathan Chancellor, linux-arm-kernel, kvmarm, linux-kselftest
In-Reply-To: <ag3zr7-11FO3k-Wv@kernel.org>

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

On Wed, 2026-05-20 at 10:47 -0700, Oliver Upton wrote:
> On Wed, May 20, 2026 at 12:33:52AM +0100, David Woodhouse wrote:
> > On Tue, 2026-05-19 at 15:57 -0700, Oliver Upton wrote:
> > > What ifs and maybes do not meet the bar, in my opinion, for preserving
> > > bug emulation in KVM. Of course there could be a little flexibility with
> > > that but we need to have some way of discriminating between bug fixes
> > > and genuine guest expectations around the behavior of virtual hardware.
> > 
> > I believe you have this completely backwards.
> 
> No, I really don't.
> 
> Leaving every bugfix that could _possibly_ have a guest-visible impact
> subject to drive-by scrutiny many years after the dust has settled is
> not an acceptable working dynamic. Especially since it would appear
> that the rest of the ecosystem has long since moved on from this
> particular issue.

That's reductio ad absurdum.

I can continue to work around this one internally, sure.

But I'm also concerned about the general case because not only did you
refuse it, but you *also* said that this change in guest-visible
behaviour "should've happened without a change to the revision number".

Which seems to indicate that not only are you being randomly
obstructive about a one-line fix, you *also* don't actually understand
the general concept of what is expected of KVM, which this
Documentation patch is intending to clarify.

It was *right* to bump the IIDR from 1 to 2 when this guest visible
behaviour was changed. The only problem was not letting userspace
select the old revision. I'm really concerned that we now appear to
have a regression of understanding of even the part we previously *did*
get right.

> If this matters to you so deeply then please, be part of the solution
> instead. You may find that reviewing patches leads to better outcomes
> than getting belligerent with the arm64 folks every time you guys
> decide to rebase your kernel. Hell, hypotheticals actually have a lot
> more weight in the context of a review. And if your testing is extensive
> enough to catch these sort of subtleties, don't you think it's better
> done against mainline?

Yes. Definitely. That's why my series with the fixes is more *test*
than actual fix, giving a nice simple framework for any such changes in
future. It checks that GICR_CTLR_IR|GICR_CTLR_CES are visible only with
IIDR.rev=3 for example.

And we're making progress on the amount of downstream crap, but it
doesn't help when we seem to have an impedance mismatch on the very
question of what it means to support customers on KVM at scale. This
thread is not exactly encouraging my engineers to poke their heads
above the parapet.

> Maybe it's just me but I am left feeling disappointed that we all
> haven't found a productive way of working together. I've tried to bridge
> the gap here; we obviously need to do something that at least fixes the
> UAPI breakage. Although apparently we don't even care to meet that low
> of bar.
> 
> > A stable and mature platform doesn't get to play in its ivory tower and
> > randomly inflict breakage on guests because they "deserve it".
> 
> Really? Aren't you asking for us to emulate something completely broken
> for you?

No. I'm asking for a path to be able to *fix* it.

As things stand, if I just drop these patches and launch guests on a
new kernel, those guests will see writable IGROUPR registers and may
try to use them. And then if I have to roll *back* a kernel deployment,
those guests may lose interrupts.

The *only* time a guest-visible feature (or bugfix, nobody cares about
the difference outside the ivory tower) can be enabled is when the
kernel deployment is finished and stable and *won't* be rolled back.
And *then* new launches (and reboots) can get it.

And one day, when the last guest which was launched *without* it is
finally rebooted and sees the new model, *then* maybe we no longer need
that one line if() statement to support IIDR version 1.

2018 was basically *yesterday*. And I'm kind of scared that I even have
to explain it.

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]

^ permalink raw reply

* [PATCH v6 00/22] Add HDMI 2.0 support to DW HDMI QP TX
From: Cristian Ciocaltea @ 2026-05-20 18:38 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sandy Huang,
	Heiko Stübner, Andy Yan, Luca Ceresoli, Daniel Stone
  Cc: kernel, dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip,
	Dmitry Baryshkov, Diederik de Haas, Maud Spierings

Enable HDMI 2.0 display modes (e.g. 4K@60Hz) on the Synopsys DW HDMI QP
TX controller, as found in Rockchip RK3576 & RK3588 SoCs, by adding SCDC
management for high TMDS clock ratio and scrambling.

Since SCDC state is lost on sink disconnects, the bridge driver needs to
trigger a CRTC reset during connector detection.  To support this, the
series introduces the connector and bridge scrambling infrastructure
(patches 1-7), wires it up through the bridge connector layer with an
atomic-aware detect_ctx hook (patches 8-10), then implements the SCDC
scrambling feature in the DW HDMI QP bridge driver (patches 11-14).

Patches 15-17 are minor cleanups in the Rockchip platform driver.
Patches 18-22 improve HPD handling by deferring IRQ registration until
the connector is fully initialized, adding .enable_hpd()/.disable_hpd()
PHY ops, and restricting HPD events to the affected connector.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
Changes in v6:
- Collected R-b & A-b tags from Dmitry and Heiko
- Restructured the series from 10 into 22 patches, splitting the SCDC
  scrambling helpers, connector infrastructure, bridge operations,
  bridge_connector plumbing, dw-hdmi-qp implementation, and Rockchip
  platform changes into distinct commits
- Added drm_scdc_dbg() macro to simplify debug messages (new patch)
- Added drm_scdc_start/stop/sync_status() helpers for full scrambling
  lifecycle management (reworked from v5 patch 5)
- Added drm_atomic_helper_connector_hdmi_hotplug_ctx() to propagate
  modeset acquire context for SCDC sync on hotplug (new patch)
- Added connector scrambler callbacks and SCDC work/flag infrastructure
  as a separate patch (split from v5 patch 5)
- Added DRM_BRIDGE_OP_HDMI_SCRAMBLER bridge operation with
  hdmi_scrambler_enable/disable callbacks (new patch)
- Implemented bridge_connector scrambler interface wiring (new patch)
- Added .enable_hpd()/.disable_hpd() PHY ops for dw-hdmi-qp bridge and
  Rockchip platform drivers, replacing the obsolete .setup_hpd() op
- Added dw_hdmi_qp_hpd_notify() helper for targeted connector-only HPD
  notification (split from v5 patch 10)
- Dropped drm_fb_helper_hotplug_event() unused variable (new cleanup)
- Dropped unused drm_simple_kms_helper.h include (new cleanup)
- Masked RK3576 HPD IRQ in io_init() for consistency with RK3588
- Rebased onto latest drm-misc-next
- Link to v5: https://patch.msgid.link/20260426-dw-hdmi-qp-scramb-v5-0-d778e70c317b@collabora.com

Changes in v5:
- Added new patches: 1/10, 3/10, 6/10, 7/10, 8/10
- Removed redundant no-op error check in drm_bridge_helper_reset_crtc()
  (patch 1)
- Removed the EDEADLK retry loop from the bridge .detect_ctx() callback,
  as that's already handled in the drm_bridge_detect_ctx() helper or by
  the caller when ctx is provided (patch 2)
- Refactored drm_bridge_detect() to delegate to drm_bridge_detect_ctx()
  and added a WARN_ON for unexpected negative return values (patch 2)
- Split the bridge-connector .detect_ctx() switch into a preparatory
  patch to use cached connector status in .get_modes() (patch 3)
- Improved error handling in SCDC scrambling setup: roll back high TMDS
  clock ratio on scrambling failure, reset scramb_enabled flag on
  set_scramb failure, and add SCDC version read/write error checks
  (patch 5)
- Annotated scramb_enabled with READ_ONCE/WRITE_ONCE for cross-context
  access between modeset paths and the scrambling work item (patch 5)
- Renamed SCDC_MIN_SOURCE_VERSION to SCDC_MAX_SOURCE_VERSION (patch 5)
- Rate limited i2c error messages (patch 6)
- Added missing newlines in dev_err_probe() messages (patch 7)
- Replaced indirect device pointer accesses with local dev variable in
  bind() (patch 8)
- Split the HPD connector restriction (formerly patch 4/4): register HPD
  IRQ after connector setup first (patch 9), then restrict HPD event to
  the affected connector (patch 10); also collected R-b from Heiko
- Rebased onto latest drm-misc-next
- Link to v4: https://lore.kernel.org/r/20260303-dw-hdmi-qp-scramb-v4-0-317d3b8bd219@collabora.com

Changes in v4:
- Fixed conflicts while rebasing onto latest drm-misc-next
- Link to v3: https://lore.kernel.org/r/20260119-dw-hdmi-qp-scramb-v3-0-bd8611730fc1@collabora.com

Changes in v3:
- Used drm_bridge_helper_reset_crtc() helper to reset the display
  pipeline and got rid of some boilerplate code (Maxime)
- Rebased onto latest drm-misc-next
- Link to v2: https://lore.kernel.org/r/20260113-dw-hdmi-qp-scramb-v2-0-ae7b2c58d24d@collabora.com

Changes in v2:
- Collected Tested-by tags from Diederik and Maud
- Rebased onto latest drm-misc-next
- Ensured the recently introduced 'no-hpd' support for dealing with
  unconnected/repurposed/broken HPD pin is limited to HDMI 1.4 rates
- Link to v1: https://lore.kernel.org/r/20251203-dw-hdmi-qp-scramb-v1-0-836fe7401a69@collabora.com

---
Cristian Ciocaltea (22):
      drm/fb-helper: Remove unused local variable in hotplug_event()
      drm/connector: Add HDMI 2.0 scrambler infrastructure
      drm/display: scdc_helper: Add macro to simplify debugging
      drm/display: scdc_helper: Add HDMI 2.0 scrambling management helpers
      drm/display: hdmi_state_helper: Add ctx-aware hotplug helper for SCDC sync
      drm/bridge: Remove redundant error check in drm_bridge_helper_reset_crtc()
      drm/bridge: Add HDMI 2.0 scrambler bridge operation and callbacks
      drm/display: bridge_connector: Use cached connector status in .get_modes()
      drm/display: bridge_connector: Switch to .detect_ctx() connector helper
      drm/display: bridge_connector: Wire up HDMI 2.0 scrambler callbacks
      drm/bridge: dw-hdmi-qp: Rate limit i2c read error messages
      drm/bridge: dw-hdmi-qp: Provide .{enable|disable}_hpd() PHY ops
      drm/bridge: dw-hdmi-qp: Add HDMI 2.0 SCDC scrambling support`
      drm/bridge: dw-hdmi-qp: Provide dw_hdmi_qp_hpd_notify() helper
      drm/rockchip: dw_hdmi_qp: Add missing newlines in dev_err_probe() messages
      drm/rockchip: dw_hdmi_qp: Use local dev variable consistently in bind()
      drm/rockchip: dw_hdmi_qp: Drop unnecessary #include
      drm/rockchip: dw_hdmi_qp: Defer HPD IRQ enable until after connector setup
      drm/rockchip: dw_hdmi_qp: Mask HPD IRQ in rk3576_io_init()
      drm/rockchip: dw_hdmi_qp: Implement .{enable|disable}_hpd() PHY ops
      drm/rockchip: dw_hdmi_qp: Switch to dw_hdmi_qp_hpd_notify()
      drm/bridge: dw-hdmi-qp: Remove obsolete .setup_hpd() phy op

 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c    | 132 +++++++++---
 drivers/gpu/drm/display/drm_bridge_connector.c  | 118 +++++++----
 drivers/gpu/drm/display/drm_hdmi_state_helper.c |  36 +++-
 drivers/gpu/drm/display/drm_scdc_helper.c       | 259 ++++++++++++++++++++++--
 drivers/gpu/drm/drm_bridge_helper.c             |   2 -
 drivers/gpu/drm/drm_connector.c                 |  14 ++
 drivers/gpu/drm/drm_fb_helper.c                 |  11 +-
 drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c  | 130 ++++++------
 include/drm/bridge/dw_hdmi_qp.h                 |   4 +-
 include/drm/display/drm_hdmi_state_helper.h     |   4 +
 include/drm/display/drm_scdc_helper.h           |   6 +-
 include/drm/drm_bridge.h                        |  26 +++
 include/drm/drm_connector.h                     |  52 +++++
 13 files changed, 623 insertions(+), 171 deletions(-)
---
base-commit: a48bbcc7ac739e93562d6148c6fa504c2e9f22f8
change-id: 20251203-dw-hdmi-qp-scramb-cdbd8b57ccf9



^ permalink raw reply

* [PATCH v6 02/22] drm/connector: Add HDMI 2.0 scrambler infrastructure
From: Cristian Ciocaltea @ 2026-05-20 18:38 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sandy Huang,
	Heiko Stübner, Andy Yan, Luca Ceresoli, Daniel Stone
  Cc: kernel, dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip
In-Reply-To: <20260520-dw-hdmi-qp-scramb-v6-0-24b74603b782@collabora.com>

Add the connector-level infrastructure to support HDMI 2.0 scrambling:

- .scrambler_src_{enable|disable}() callbacks in
  drm_connector_hdmi_funcs for source-side scrambling control
- A delayed work item (scdc_work) with an associated callback (scdc_cb)
  for periodic monitoring of sink-side scrambling status
- A scrambler_enabled flag to track whether scrambling is currently
  active

These are intended to be used by SCDC scrambling helpers to coordinate
scrambling setup and teardown between the source driver and the DRM
core.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/drm_connector.c | 14 +++++++++++
 include/drm/drm_connector.h     | 52 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 3fa4d2082cd7..91e58362fbc0 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -220,6 +220,19 @@ void drm_connector_free_work_fn(struct work_struct *work)
 	}
 }
 
+static void drm_connector_hdmi_scdc_work(struct work_struct *work)
+{
+	struct drm_connector *connector;
+	struct drm_connector_hdmi *hdmi;
+
+	hdmi = container_of(to_delayed_work(work), struct drm_connector_hdmi,
+			    scdc_work);
+	connector = container_of(hdmi, struct drm_connector, hdmi);
+
+	if (hdmi->scdc_cb)
+		hdmi->scdc_cb(connector);
+}
+
 static int drm_connector_init_only(struct drm_device *dev,
 				   struct drm_connector *connector,
 				   const struct drm_connector_funcs *funcs,
@@ -285,6 +298,7 @@ static int drm_connector_init_only(struct drm_device *dev,
 	mutex_init(&connector->edid_override_mutex);
 	mutex_init(&connector->hdmi.infoframes.lock);
 	mutex_init(&connector->hdmi_audio.lock);
+	INIT_DELAYED_WORK(&connector->hdmi.scdc_work, drm_connector_hdmi_scdc_work);
 	connector->edid_blob_ptr = NULL;
 	connector->epoch_counter = 0;
 	connector->tile_blob_ptr = NULL;
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 5ad62c207d00..49eaa30b1329 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -28,6 +28,7 @@
 #include <linux/ctype.h>
 #include <linux/hdmi.h>
 #include <linux/notifier.h>
+#include <linux/workqueue.h>
 #include <drm/drm_mode_object.h>
 #include <drm/drm_util.h>
 #include <drm/drm_property.h>
@@ -1358,6 +1359,36 @@ struct drm_connector_hdmi_funcs {
 	 */
 	const struct drm_edid *(*read_edid)(struct drm_connector *connector);
 
+	/**
+	 * @scrambler_src_enable:
+	 *
+	 * This callback is invoked through @drm_scdc_start_scrambling during
+	 * a commit to setup SCDC scrambling and high TMDS clock ratio on
+	 * source side.
+	 *
+	 * The @scrambler_src_enable callback is mandatory if HDMI 2.0 is
+	 * to be supported.
+	 *
+	 * Returns:
+	 * 0 on success, a negative error code otherwise
+	 */
+	int (*scrambler_src_enable)(struct drm_connector *connector);
+
+	/**
+	 * @scrambler_src_disable:
+	 *
+	 * This callback is invoked through @drm_scdc_stop_scrambling during
+	 * a commit to disable SCDC scrambling and high TMDS clock ratio on
+	 * source side.
+	 *
+	 * The @scrambler_src_disable callback is mandatory if HDMI 2.0 is
+	 * to be supported.
+	 *
+	 * Returns:
+	 * 0 on success, a negative error code otherwise
+	 */
+	int (*scrambler_src_disable)(struct drm_connector *connector);
+
 	/**
 	 * @avi:
 	 *
@@ -1944,6 +1975,27 @@ struct drm_connector_hdmi {
 	 */
 	unsigned long supported_formats;
 
+	/**
+	 * @scrambler_enabled: Tracks whether HDMI 2.0 scrambler is currently enabled.
+	 */
+	bool scrambler_enabled;
+
+	/**
+	 * @scdc_work: Work item currently used to monitor sink-side scrambling
+	 * status and retry setup if the sink resets it.
+	 */
+	struct delayed_work scdc_work;
+
+	/** @scdc_cb: Callback to be invoked as part of @scdc_work.
+	 *
+	 * Currently used to monitor sink-side scrambling status and retry
+	 * setup if the sink resets it.
+	 *
+	 * This is assigned by the framework when making use of
+	 * drm_scdc_start_scrambling() helper.
+	 */
+	void (*scdc_cb)(struct drm_connector *connector);
+
 	/**
 	 * @funcs: HDMI connector Control Functions
 	 */

-- 
2.53.0



^ permalink raw reply related

* [PATCH v6 01/22] drm/fb-helper: Remove unused local variable in hotplug_event()
From: Cristian Ciocaltea @ 2026-05-20 18:38 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sandy Huang,
	Heiko Stübner, Andy Yan, Luca Ceresoli, Daniel Stone
  Cc: kernel, dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip
In-Reply-To: <20260520-dw-hdmi-qp-scramb-v6-0-24b74603b782@collabora.com>

Remove the 'err' local variable in drm_fb_helper_hotplug_event() which
only stores a return value that is never used beyond the immediate
return statement.  This simplifies the code without behavior changes.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/drm_fb_helper.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 38d25dce7f33..d8fb90160b90 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1744,21 +1744,17 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
  */
 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 {
-	int err = 0;
-
 	if (!drm_fbdev_emulation || !fb_helper)
 		return 0;
 
 	mutex_lock(&fb_helper->lock);
-	if (fb_helper->deferred_setup) {
-		err = __drm_fb_helper_initial_config_and_unlock(fb_helper);
-		return err;
-	}
+	if (fb_helper->deferred_setup)
+		return __drm_fb_helper_initial_config_and_unlock(fb_helper);
 
 	if (!fb_helper->fb || !drm_master_internal_acquire(fb_helper->dev)) {
 		fb_helper->delayed_hotplug = true;
 		mutex_unlock(&fb_helper->lock);
-		return err;
+		return 0;
 	}
 
 	drm_master_internal_release(fb_helper->dev);
@@ -1802,4 +1798,3 @@ bool drm_fb_helper_gem_is_fb(const struct drm_fb_helper *fb_helper,
 	return gem == obj;
 }
 EXPORT_SYMBOL_GPL(drm_fb_helper_gem_is_fb);
-

-- 
2.53.0



^ permalink raw reply related

* Re: [PATCH 1/8] mm: Add ptep_try_install() for lockless empty-slot installs
From: Tejun Heo @ 2026-05-20 18:38 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Alexei Starovoitov, David Vernet, Andrea Righi, Changwoo Min,
	Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Martin KaFai Lau, Kumar Kartikeya Dwivedi, Catalin Marinas,
	Will Deacon, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, Andrew Morton, Mike Rapoport, Emil Tsalapatis,
	sched-ext, bpf, X86 ML, linux-arm-kernel, linux-mm, LKML
In-Reply-To: <fb889bfc-af0e-491e-a69f-38c2abf88d22@kernel.org>

On Wed, May 20, 2026 at 10:41:15AM +0200, David Hildenbrand (Arm) wrote:
> And that should be carefully documented.

Will do.

> > The fault handler has to install _some_ page and let kernel continue.
> > Scratch page or arena page doesn't matter. Potentially different CPUs
> > will see different page. It's not a concern at all.
> > bpf prog is buggy, but the kernel will continue to work without a glitch.
> > bpf runtime will disable and unload misbehaving prog.
> 
> Having one page table walker overwrite a scratch page on race is just rather ...
> questionable locking design, that just screams for problems long-term, really.
> 
> At least in apply_range_clear_cb() one could similarly switch to
> ptep_try_install() to at least have both these paths handle races in a
> reasonable way. (having to handle when ptep_try_install() is not really implemented)

Hmm... wouldn't that be more confusing on apply_range_clear_cb() side?
Whether it maintains the current behavior (if collide with scratch, try
again with scratch as the original value) or flip the behavior (fail if
scratch), that extra logic is spurious, and those tend to confuse people as
they force asking why it has to be that specific way. If the goal is
documenting the subtlety, wouldn't a detailed comment serve the purpose
better?

> Anyhow, the documentation of ptep_try_install() must clearly spell out that this
> must be used very carefully, and only in special kernel page tables, never user
> page tables. There are likely other scenarios we should document (caller must
> prevent concurrent page table teardown somehow, and must be prepared to handle
> races if other code is not using atomics).
> 
> To highlight that, we should likely consider adding a "kernel" in the name, like
> "ptep_try_install_kernel()".
> 
> I am also not sure if "install" is the right terminology and whether it should
> instead be "ptep_try_set()". (set_pte_at is the non-atomic interface right now)

So, ptep_try_set_kernel()?

> Further note that last time I talked to Linus about arch helpers, he preferred
> 
> #define ptep_try_install ptep_try_install
> 
> over __HAVE_ARCH_PTEP_TRY_INSTALL

Will do.

Thanks.

-- 
tejun


^ permalink raw reply

* [PATCH v6 06/22] drm/bridge: Remove redundant error check in drm_bridge_helper_reset_crtc()
From: Cristian Ciocaltea @ 2026-05-20 18:38 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sandy Huang,
	Heiko Stübner, Andy Yan, Luca Ceresoli, Daniel Stone
  Cc: kernel, dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip,
	Dmitry Baryshkov
In-Reply-To: <20260520-dw-hdmi-qp-scramb-v6-0-24b74603b782@collabora.com>

Remove the no-op error check after drm_atomic_helper_reset_crtc() since
the goto target is the immediately following label and the return value
is already propagated correctly without it.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/drm_bridge_helper.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge_helper.c b/drivers/gpu/drm/drm_bridge_helper.c
index 420f29cf3e54..0a3c8fee66b3 100644
--- a/drivers/gpu/drm/drm_bridge_helper.c
+++ b/drivers/gpu/drm/drm_bridge_helper.c
@@ -50,8 +50,6 @@ int drm_bridge_helper_reset_crtc(struct drm_bridge *bridge,
 
 	crtc = connector->state->crtc;
 	ret = drm_atomic_helper_reset_crtc(crtc, ctx);
-	if (ret)
-		goto out;
 
 out:
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);

-- 
2.53.0



^ permalink raw reply related

* [PATCH v6 03/22] drm/display: scdc_helper: Add macro to simplify debugging
From: Cristian Ciocaltea @ 2026-05-20 18:38 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sandy Huang,
	Heiko Stübner, Andy Yan, Luca Ceresoli, Daniel Stone
  Cc: kernel, dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip
In-Reply-To: <20260520-dw-hdmi-qp-scramb-v6-0-24b74603b782@collabora.com>

Introduce the drm_scdc_dbg() wrapper over drm_dbg_kms() to help getting
rid of the boilerplate around prefixing the debug messages with the
connector information.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/display/drm_scdc_helper.c | 24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_scdc_helper.c b/drivers/gpu/drm/display/drm_scdc_helper.c
index df878aad4a36..cb6632346aad 100644
--- a/drivers/gpu/drm/display/drm_scdc_helper.c
+++ b/drivers/gpu/drm/display/drm_scdc_helper.c
@@ -55,6 +55,10 @@
 
 #define SCDC_I2C_SLAVE_ADDRESS 0x54
 
+#define drm_scdc_dbg(connector, fmt, ...)					\
+	drm_dbg_kms((connector)->dev, "[CONNECTOR:%d:%s] " fmt,			\
+		    (connector)->base.id, (connector)->name, ##__VA_ARGS__)
+
 /**
  * drm_scdc_read - read a block of data from SCDC
  * @adapter: I2C controller
@@ -158,9 +162,7 @@ bool drm_scdc_get_scrambling_status(struct drm_connector *connector)
 
 	ret = drm_scdc_readb(connector->ddc, SCDC_SCRAMBLER_STATUS, &status);
 	if (ret < 0) {
-		drm_dbg_kms(connector->dev,
-			    "[CONNECTOR:%d:%s] Failed to read scrambling status: %d\n",
-			    connector->base.id, connector->name, ret);
+		drm_scdc_dbg(connector, "Failed to read scrambling status: %d\n", ret);
 		return false;
 	}
 
@@ -188,9 +190,7 @@ bool drm_scdc_set_scrambling(struct drm_connector *connector,
 
 	ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config);
 	if (ret < 0) {
-		drm_dbg_kms(connector->dev,
-			    "[CONNECTOR:%d:%s] Failed to read TMDS config: %d\n",
-			    connector->base.id, connector->name, ret);
+		drm_scdc_dbg(connector, "Failed to read TMDS config: %d\n", ret);
 		return false;
 	}
 
@@ -201,9 +201,7 @@ bool drm_scdc_set_scrambling(struct drm_connector *connector,
 
 	ret = drm_scdc_writeb(connector->ddc, SCDC_TMDS_CONFIG, config);
 	if (ret < 0) {
-		drm_dbg_kms(connector->dev,
-			    "[CONNECTOR:%d:%s] Failed to enable scrambling: %d\n",
-			    connector->base.id, connector->name, ret);
+		drm_scdc_dbg(connector, "Failed to enable scrambling: %d\n", ret);
 		return false;
 	}
 
@@ -248,9 +246,7 @@ bool drm_scdc_set_high_tmds_clock_ratio(struct drm_connector *connector,
 
 	ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config);
 	if (ret < 0) {
-		drm_dbg_kms(connector->dev,
-			    "[CONNECTOR:%d:%s] Failed to read TMDS config: %d\n",
-			    connector->base.id, connector->name, ret);
+		drm_scdc_dbg(connector, "Failed to read TMDS config: %d\n", ret);
 		return false;
 	}
 
@@ -261,9 +257,7 @@ bool drm_scdc_set_high_tmds_clock_ratio(struct drm_connector *connector,
 
 	ret = drm_scdc_writeb(connector->ddc, SCDC_TMDS_CONFIG, config);
 	if (ret < 0) {
-		drm_dbg_kms(connector->dev,
-			    "[CONNECTOR:%d:%s] Failed to set TMDS clock ratio: %d\n",
-			    connector->base.id, connector->name, ret);
+		drm_scdc_dbg(connector, "Failed to set TMDS clock ratio: %d\n", ret);
 		return false;
 	}
 

-- 
2.53.0



^ permalink raw reply related

* [PATCH v6 08/22] drm/display: bridge_connector: Use cached connector status in .get_modes()
From: Cristian Ciocaltea @ 2026-05-20 18:38 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sandy Huang,
	Heiko Stübner, Andy Yan, Luca Ceresoli, Daniel Stone
  Cc: kernel, dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip,
	Dmitry Baryshkov
In-Reply-To: <20260520-dw-hdmi-qp-scramb-v6-0-24b74603b782@collabora.com>

Replace the active drm_bridge_connector_detect() call in get_modes()
with a read of the already-cached connector->status.

The .get_modes() callback is only invoked from
drm_helper_probe_single_connector_modes(), which has already retrieved
the connector status.  Calling detect again is redundant and triggers a
duplicate hotplug event.  This is also a prerequisite for switching to
the .detect_ctx() hook, which requires a drm_modeset_acquire_ctx not
available in the .get_modes() path.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/display/drm_bridge_connector.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c
index 649969fca141..b69785eb49e2 100644
--- a/drivers/gpu/drm/display/drm_bridge_connector.c
+++ b/drivers/gpu/drm/display/drm_bridge_connector.c
@@ -294,12 +294,10 @@ static const struct drm_connector_funcs drm_bridge_connector_funcs = {
 static int drm_bridge_connector_get_modes_edid(struct drm_connector *connector,
 					       struct drm_bridge *bridge)
 {
-	enum drm_connector_status status;
 	const struct drm_edid *drm_edid;
 	int n;
 
-	status = drm_bridge_connector_detect(connector, false);
-	if (status != connector_status_connected)
+	if (connector->status != connector_status_connected)
 		goto no_edid;
 
 	drm_edid = drm_bridge_edid_read(bridge, connector);

-- 
2.53.0



^ permalink raw reply related

* [PATCH v6 04/22] drm/display: scdc_helper: Add HDMI 2.0 scrambling management helpers
From: Cristian Ciocaltea @ 2026-05-20 18:38 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sandy Huang,
	Heiko Stübner, Andy Yan, Luca Ceresoli, Daniel Stone
  Cc: kernel, dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip
In-Reply-To: <20260520-dw-hdmi-qp-scramb-v6-0-24b74603b782@collabora.com>

Add drm_scdc_start_scrambling(), drm_scdc_stop_scrambling() and
drm_scdc_sync_status() helpers to manage the full lifecycle of HDMI 2.0
SCDC scrambling on both source and sink sides.

drm_scdc_start_scrambling() configures SCDC scrambling and high TMDS
clock ratio and starts a periodic work item that monitors the sink's
SCDC scrambling status, retrying setup when the sink loses state.

drm_scdc_stop_scrambling() tears down scrambling on both sides and
cancels the monitoring work.

drm_scdc_sync_status() triggers a CRTC reset on reconnection to restore
SCDC state lost during sink disconnects within an active display
pipeline.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/display/drm_scdc_helper.c | 235 +++++++++++++++++++++++++++++-
 include/drm/display/drm_scdc_helper.h     |   6 +-
 2 files changed, 236 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_scdc_helper.c b/drivers/gpu/drm/display/drm_scdc_helper.c
index cb6632346aad..5bacb886d373 100644
--- a/drivers/gpu/drm/display/drm_scdc_helper.c
+++ b/drivers/gpu/drm/display/drm_scdc_helper.c
@@ -21,16 +21,22 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/i2c.h>
+#include <linux/minmax.h>
 #include <linux/slab.h>
-#include <linux/delay.h>
 
-#include <drm/display/drm_scdc_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge_helper.h>
 #include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
 #include <drm/drm_device.h>
 #include <drm/drm_print.h>
 
+#include <drm/display/drm_scdc_helper.h>
+
 /**
  * DOC: scdc helpers
  *
@@ -50,10 +56,14 @@
  * has to track the connector status changes using interrupts and
  * restore the SCDC status. The typical solution for this is to trigger an
  * empty modeset in drm_connector_helper_funcs.detect_ctx(), like what vc4 does
- * in vc4_hdmi_reset_link().
+ * in vc4_hdmi_reset_link(). Alternatively, use the HDMI connector framework
+ * which ensures drm_scdc_sync_status() is called in the context of
+ * drm_atomic_helper_connector_hdmi_hotplug_ctx().
  */
 
-#define SCDC_I2C_SLAVE_ADDRESS 0x54
+#define SCDC_I2C_SLAVE_ADDRESS		0x54
+#define SCDC_MAX_SOURCE_VERSION		0x1
+#define SCDC_STATUS_POLL_DELAY_MS	3000
 
 #define drm_scdc_dbg(connector, fmt, ...)					\
 	drm_dbg_kms((connector)->dev, "[CONNECTOR:%d:%s] " fmt,			\
@@ -270,3 +280,220 @@ bool drm_scdc_set_high_tmds_clock_ratio(struct drm_connector *connector,
 	return true;
 }
 EXPORT_SYMBOL(drm_scdc_set_high_tmds_clock_ratio);
+
+static int drm_scdc_setup_scrambler(struct drm_connector *connector)
+{
+	bool done;
+
+	done = drm_scdc_set_high_tmds_clock_ratio(connector, true);
+	if (!done)
+		return -EIO;
+
+	done = drm_scdc_set_scrambling(connector, true);
+	if (!done)
+		return -EIO;
+
+	schedule_delayed_work(&connector->hdmi.scdc_work,
+			      msecs_to_jiffies(SCDC_STATUS_POLL_DELAY_MS));
+	return 0;
+}
+
+static void drm_scdc_monitor_scrambler(struct drm_connector *connector)
+{
+	if (READ_ONCE(connector->hdmi.scrambler_enabled) &&
+	    !drm_scdc_get_scrambling_status(connector))
+		drm_scdc_setup_scrambler(connector);
+}
+
+static int drm_scdc_reset_crtc(struct drm_connector *connector,
+			       struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_crtc *crtc;
+	u8 config;
+	int ret;
+
+	if (!ctx || !connector->state)
+		return 0;
+
+	crtc = connector->state->crtc;
+	if (!crtc || !crtc->state || !crtc->state->active)
+		return 0;
+
+	ret = drm_scdc_readb(connector->ddc, SCDC_TMDS_CONFIG, &config);
+	if (ret) {
+		drm_scdc_dbg(connector, "Failed to read TMDS config: %d\n", ret);
+		return ret;
+	}
+
+	if ((config & SCDC_SCRAMBLING_ENABLE) &&
+	    (config & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40))
+		return 0;
+
+	/*
+	 * Reset the CRTC to suspend TMDS transmission, conforming to HDMI 2.0
+	 * spec which requires scrambled data not to be sent before the sink is
+	 * configured, and TMDS clock to be suspended while changing the clock
+	 * ratio.  The disable/re-enable cycle triggered by the reset should
+	 * call drm_scdc_start_scrambling() during re-enable, properly
+	 * configuring the sink before data transmission resumes.
+	 */
+
+	drm_scdc_dbg(connector, "Resetting CRTC to restore SCDC status\n");
+
+	ret = drm_atomic_helper_reset_crtc(crtc, ctx);
+	if (ret && ret != -EDEADLOCK)
+		drm_scdc_dbg(connector, "Failed to reset CRTC: %d\n", ret);
+
+	return ret;
+}
+
+/**
+ * drm_scdc_start_scrambling - activate scrambling and monitor SCDC status
+ * @connector: connector
+ *
+ * Enables scrambling and high TMDS clock ratio on both source and sink sides.
+ * Additionally, use a delayed work item to monitor the scrambling status on
+ * the sink side and retry the operation, as some displays refuse to set the
+ * scrambling bit right away.
+ *
+ * Returns:
+ * Zero if scrambling is set successfully, an error code otherwise.
+ */
+int drm_scdc_start_scrambling(struct drm_connector *connector)
+{
+	struct drm_display_info *info = &connector->display_info;
+	struct drm_connector_hdmi *hdmi = &connector->hdmi;
+	int ret;
+	u8 ver;
+
+	if (!hdmi->funcs ||
+	    !hdmi->funcs->scrambler_src_enable ||
+	    !hdmi->funcs->scrambler_src_disable) {
+		drm_scdc_dbg(connector, "Function not implemented, bailing.\n");
+		return -EINVAL;
+	}
+
+	if (!info->is_hdmi ||
+	    !info->hdmi.scdc.supported ||
+	    !info->hdmi.scdc.scrambling.supported) {
+		drm_scdc_dbg(connector, "Sink doesn't support scrambling.\n");
+		return -EINVAL;
+	}
+
+	drm_scdc_dbg(connector, "Enabling scrambling\n");
+
+	ret = drm_scdc_readb(connector->ddc, SCDC_SINK_VERSION, &ver);
+	if (ret) {
+		drm_scdc_dbg(connector, "Failed to read SCDC_SINK_VERSION: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_scdc_writeb(connector->ddc, SCDC_SOURCE_VERSION,
+			      min_t(u8, ver, SCDC_MAX_SOURCE_VERSION));
+	if (ret) {
+		drm_scdc_dbg(connector, "Failed to write SCDC_SOURCE_VERSION: %d\n", ret);
+		return ret;
+	}
+
+	hdmi->scdc_cb = drm_scdc_monitor_scrambler;
+	WRITE_ONCE(hdmi->scrambler_enabled, true);
+
+	ret = drm_scdc_setup_scrambler(connector);
+	if (!ret)
+		ret = hdmi->funcs->scrambler_src_enable(connector);
+
+	if (ret) {
+		WRITE_ONCE(hdmi->scrambler_enabled, false);
+		cancel_delayed_work_sync(&hdmi->scdc_work);
+		hdmi->scdc_cb = NULL;
+
+		drm_scdc_set_scrambling(connector, false);
+		drm_scdc_set_high_tmds_clock_ratio(connector, false);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_scdc_start_scrambling);
+
+/**
+ * drm_scdc_stop_scrambling - deactivate scrambling and SCDC status monitor
+ * @connector: connector
+ *
+ * Disables scrambling and high TMDS clock ratio on both source and sink sides.
+ * Also cancels the SCDC status monitoring work item, if it is still pending.
+ *
+ * Returns:
+ * Zero if scrambling is reset successfully, an error code otherwise.
+ */
+int drm_scdc_stop_scrambling(struct drm_connector *connector)
+{
+	struct drm_display_info *info = &connector->display_info;
+	struct drm_connector_hdmi *hdmi = &connector->hdmi;
+
+	if (!hdmi->funcs ||
+	    !hdmi->funcs->scrambler_src_disable) {
+		drm_scdc_dbg(connector, "Function not implemented, bailing.\n");
+		return -EINVAL;
+	}
+
+	if (!READ_ONCE(hdmi->scrambler_enabled))
+		return 0;
+
+	drm_scdc_dbg(connector, "Disabling scrambling\n");
+
+	WRITE_ONCE(hdmi->scrambler_enabled, false);
+	cancel_delayed_work_sync(&hdmi->scdc_work);
+	hdmi->scdc_cb = NULL;
+
+	if (connector->status == connector_status_connected &&
+	    info->is_hdmi && info->hdmi.scdc.supported &&
+	    info->hdmi.scdc.scrambling.supported) {
+		drm_scdc_set_scrambling(connector, false);
+		drm_scdc_set_high_tmds_clock_ratio(connector, false);
+	}
+
+	return hdmi->funcs->scrambler_src_disable(connector);
+}
+EXPORT_SYMBOL(drm_scdc_stop_scrambling);
+
+/**
+ * drm_scdc_sync_status - resync the sink-side SCDC upon reconnect
+ * @connector: connector
+ * @plugged: connector plugged status event
+ * @ctx: lock acquisition context
+ *
+ * When receiving hotplug disconnect/reconnect event, while the display is
+ * still active (CRTC enabled), the SCDC status on the sink side is reset
+ * and must be explicitly restored.
+ *
+ * The typical solution for this is to trigger an empty modeset in
+ * drm_connector_helper_funcs.detect_ctx(), which is what this helper does
+ * by triggering a CRTC reset on reconnection.
+ *
+ * When making use of the HDMI connector framework, this is automatically
+ * triggered via drm_atomic_helper_connector_hdmi_hotplug_ctx().
+ *
+ * Returns:
+ * Zero on success, an error code otherwise, including -EDEADLOCK.
+ */
+int drm_scdc_sync_status(struct drm_connector *connector, bool plugged,
+			 struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_connector_hdmi *hdmi = &connector->hdmi;
+
+	if (!hdmi->funcs)
+		return 0;
+
+	if (plugged && READ_ONCE(hdmi->scrambler_enabled)) {
+		if (!hdmi->funcs->scrambler_src_enable ||
+		    !hdmi->funcs->scrambler_src_disable)
+			return 0;
+
+		return drm_scdc_reset_crtc(connector, ctx);
+	}
+
+	// TODO: Also handle HDMI 2.1 FRL link training
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_scdc_sync_status);
diff --git a/include/drm/display/drm_scdc_helper.h b/include/drm/display/drm_scdc_helper.h
index 34600476a1b9..5d9a37bbb362 100644
--- a/include/drm/display/drm_scdc_helper.h
+++ b/include/drm/display/drm_scdc_helper.h
@@ -29,6 +29,7 @@
 #include <drm/display/drm_scdc.h>
 
 struct drm_connector;
+struct drm_modeset_acquire_ctx;
 struct i2c_adapter;
 
 ssize_t drm_scdc_read(struct i2c_adapter *adapter, u8 offset, void *buffer,
@@ -76,5 +77,8 @@ bool drm_scdc_get_scrambling_status(struct drm_connector *connector);
 
 bool drm_scdc_set_scrambling(struct drm_connector *connector, bool enable);
 bool drm_scdc_set_high_tmds_clock_ratio(struct drm_connector *connector, bool set);
-
+int drm_scdc_start_scrambling(struct drm_connector *connector);
+int drm_scdc_stop_scrambling(struct drm_connector *connector);
+int drm_scdc_sync_status(struct drm_connector *connector, bool plugged,
+			 struct drm_modeset_acquire_ctx *ctx);
 #endif

-- 
2.53.0



^ permalink raw reply related


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