Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v9 3/9] drm/bridge: fsl-ldb: Add support for i.MX94
From: Frank Li @ 2026-06-15 15:00 UTC (permalink / raw)
  To: Laurentiu Palcu
  Cc: Ying Liu, Luca Ceresoli, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, linux-clk, imx, devicetree, linux-arm-kernel,
	linux-kernel, dri-devel
In-Reply-To: <20260612-dcif-upstreaming-v9-3-8d0ff89aa3c5@oss.nxp.com>

On Fri, Jun 12, 2026 at 02:58:34PM +0300, Laurentiu Palcu wrote:
>
> i.MX94 series LDB controller shares the same LDB and LVDS control
> registers as i.MX8MP and i.MX93 but supports a higher maximum clock
> frequency.
>
> Add a 'max_clk_khz' member to the fsl_ldb_devdata structure in order to
> be able to set different max frequencies for other platforms.
>
> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
> ---

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

>  drivers/gpu/drm/bridge/fsl-ldb.c | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
> index bd03c36ee696c..b4959f654f2ac 100644
> --- a/drivers/gpu/drm/bridge/fsl-ldb.c
> +++ b/drivers/gpu/drm/bridge/fsl-ldb.c
> @@ -57,6 +57,7 @@ enum fsl_ldb_devtype {
>         IMX6SX_LDB,
>         IMX8MP_LDB,
>         IMX93_LDB,
> +       IMX94_LDB,
>  };
>
>  struct fsl_ldb_devdata {
> @@ -64,21 +65,31 @@ struct fsl_ldb_devdata {
>         u32 lvds_ctrl;
>         bool lvds_en_bit;
>         bool single_ctrl_reg;
> +       u32 max_clk_khz;
>  };
>
>  static const struct fsl_ldb_devdata fsl_ldb_devdata[] = {
>         [IMX6SX_LDB] = {
>                 .ldb_ctrl = 0x18,
>                 .single_ctrl_reg = true,
> +               .max_clk_khz = 80000,
>         },
>         [IMX8MP_LDB] = {
>                 .ldb_ctrl = 0x5c,
>                 .lvds_ctrl = 0x128,
> +               .max_clk_khz = 80000,
>         },
>         [IMX93_LDB] = {
>                 .ldb_ctrl = 0x20,
>                 .lvds_ctrl = 0x24,
>                 .lvds_en_bit = true,
> +               .max_clk_khz = 80000,
> +       },
> +       [IMX94_LDB] = {
> +               .ldb_ctrl = 0x04,
> +               .lvds_ctrl = 0x08,
> +               .lvds_en_bit = true,
> +               .max_clk_khz = 148500,
>         },
>  };
>
> @@ -274,7 +285,7 @@ fsl_ldb_mode_valid(struct drm_bridge *bridge,
>  {
>         struct fsl_ldb *fsl_ldb = to_fsl_ldb(bridge);
>
> -       if (mode->clock > (fsl_ldb_is_dual(fsl_ldb) ? 160000 : 80000))
> +       if (mode->clock > (fsl_ldb_is_dual(fsl_ldb) ? 2 : 1) * fsl_ldb->devdata->max_clk_khz)
>                 return MODE_CLOCK_HIGH;
>
>         return MODE_OK;
> @@ -386,6 +397,8 @@ static const struct of_device_id fsl_ldb_match[] = {
>           .data = &fsl_ldb_devdata[IMX8MP_LDB], },
>         { .compatible = "fsl,imx93-ldb",
>           .data = &fsl_ldb_devdata[IMX93_LDB], },
> +       { .compatible = "fsl,imx94-ldb",
> +         .data = &fsl_ldb_devdata[IMX94_LDB], },
>         { /* sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, fsl_ldb_match);
>
> --
> 2.51.0
>


^ permalink raw reply

* Re: [PATCH v9 5/9] drm/imx: Add support for i.MX94 DCIF
From: Frank Li @ 2026-06-15 14:58 UTC (permalink / raw)
  To: Laurentiu Palcu
  Cc: Ying Liu, Luca Ceresoli, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-clk,
	imx, devicetree, linux-arm-kernel, linux-kernel, dri-devel
In-Reply-To: <20260612-dcif-upstreaming-v9-5-8d0ff89aa3c5@oss.nxp.com>

On Fri, Jun 12, 2026 at 02:58:36PM +0300, Laurentiu Palcu wrote:
> The i.MX94 Display Control Interface features:
>  * Up to maximum 3 layers of alpha blending:
>     - 1 background layer(Layer 0);
>     - 1 foreground layer(Layer 1);
>     - A programmable constant color behind the background layer;
>  * Each layer supports:
>     - programmable plane size;
>     - programmable background color;
>     - embedded alpha and global alpha;
>  * Data output with CRC checksum for 4 programmable regions;
>
> Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com> # bridge refcounting
> Signed-off-by: Sandor Yu <sandor.yu@nxp.com>
> Co-developed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
> ---

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


^ permalink raw reply

* Re: [PATCH v2] arm64: tlbflush: Don't broadcast if mm was only active on local cpu
From: Will Deacon @ 2026-06-15 14:44 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Linu Cherian, Catalin Marinas, Ryan Roberts, Kevin Brodsky,
	Anshuman Khandual, Yang Shi, Huang Ying, linux-arm-kernel,
	linux-kernel
In-Reply-To: <ai_yj7GA_q1hD9cr@J2N7QTR9R3.cambridge.arm.com>

On Mon, Jun 15, 2026 at 01:39:43PM +0100, Mark Rutland wrote:
> On Sun, Jun 14, 2026 at 12:04:44PM +0100, Will Deacon wrote:
> > On Sat, May 23, 2026 at 07:17:10PM +0530, Linu Cherian wrote:
> 
> > >  static inline void flush_tlb_mm(struct mm_struct *mm)
> > >  {
> > >  	unsigned long asid;
> > > +	bool local;
> > >  
> > > -	dsb(ishst);
> > > +	local = flush_tlb_user_pre(mm, TLBF_NONE);
> > >  	asid = __TLBI_VADDR(0, ASID(mm));
> > > -	__tlbi(aside1is, asid);
> > > -	__tlbi_user(aside1is, asid);
> > > -	__tlbi_sync_s1ish(mm);
> > > +	if (local) {
> > > +		__tlbi(aside1, asid);
> > > +		__tlbi_user(aside1, asid);
> > > +		dsb(nsh);
> > > +	} else {
> > > +		__tlbi(aside1is, asid);
> > > +		__tlbi_user(aside1is, asid);
> > > +		__tlbi_sync_s1ish(mm);
> > > +	}
> > > +	flush_tlb_user_post(local);
> > 
> > I think you've changed this since Ryan's original patch, but why are you
> > only calling __tlbi_sync_s1ish() for the !local case? Doesn't that break
> > the erratum workaround when running as a VM if the vCPU is migrated?
> 
> The errata mitigated by __tlbi_sync_s1ish() only affect broadcast
> maintenance (the 'ish' in the name was intended to convey that). No
> workaround is necessary for local TLB maintenance; aside from anything
> else, when some PE executes the DSB to complete the maintenance, that
> DSB alone is sufficient to complete memory accesses made by that PE.
> 
> If it would make things clearer, we could add a __tlbi_sync_s1nsh()
> helper for the local case, which would boil down to a DSB NSH.

No, I don't think that's what I'm concerned about.

> Regardless of the erratum, to correctly handle a vCPU being migrated
> from pCPU-x to pCPU-y, we rely on:
> 
> * The host to set HCR_EL2.FB to ensure that TLB maintenance is
>   broadcast to the ISH domain.
> 
> * The host to set HCR_EL2.BSU to ensure the DSB is upgrade to ISH such
>   that any guest-issued DSB NSH will it can complete any TLB maintenance
>   that was upgraded to ISH.
> 
> * The host to issue a DSB ISH on pCPU-x before the vCPU can run on
>   pCPU-y, to complete any outstanding maintenance that was issued on
>   pCPU-x. IIUC a DSB ISH on pCPU-y is not architecturally sufficient; it
>   must be executed on the same CPU which issued the TLB maintenance.
> 
> ... but as above, all of that should be independent of any of the errata
> that require the workaround.

Yes, I understand all of the above but the case I'm struggling with is
where a vCPU runs on a system that needs the TLB invalidation to be
performed twice. For non-broadcast invalidation (from the guest
perspective), this patch will mean that it only performs the
invalidation once. So if the vCPU migrates to another physical CPU, can
that effectively undo the HCR_EL2.FB upgrade unless KVM issues TLB
invalidation as well as a DSB on migration?

Maybe I'm missing something, as it looks like upstream already elides
the call to __tlbi_sync_s1ish() for the NOBROADCAST case.

Will


^ permalink raw reply

* Re: [PATCH net-next v7 05/12] net: phylink: support late PCS provider attach
From: Maxime Chevallier @ 2026-06-15 14:44 UTC (permalink / raw)
  To: Christian Marangi
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan, Lorenzo Bianconi,
	Heiner Kallweit, Russell King, Saravana Kannan, Philipp Zabel,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	netdev, devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-mediatek, llvm
In-Reply-To: <6a300da0.d5af3cef.1ca29d.19c4@mx.google.com>



On 6/15/26 16:35, Christian Marangi wrote:
> On Mon, Jun 15, 2026 at 04:29:04PM +0200, Maxime Chevallier wrote:
>>
>>
>> On 6/15/26 16:10, Christian Marangi wrote:
>>> On Mon, Jun 15, 2026 at 04:07:03PM +0200, Maxime Chevallier wrote:
>>>> Hi Christian,
>>>>
>>>> On 6/15/26 14:29, Christian Marangi wrote:
>>>>> Add support for late PCS provider attachment to a phylink instance.
>>>>> This works by creating a global notifier for the PCS provider and
>>>>> making each phylink instance that makes use of fwnode subscribe to
>>>>> this notifier.
>>>>>
>>>>> The PCS notifier will emit the event FWNODE_PCS_PROVIDER_ADD every time
>>>>> a new PCS provider is added.
>>>>>
>>>>> phylink will then react to this event and will call the new function
>>>>> fwnode_phylink_pcs_get_from_fwnode() that will check if the PCS fwnode
>>>>> provided by the event is present in the pcs-handle property of the
>>>>> phylink instance.
>>>>>
>>>>> If a related PCS is found, then such PCS is added to the phylink
>>>>> instance PCS list.
>>>>>
>>>>> Then we link the PCS to the phylink instance and we refresh the supported
>>>>> interfaces of the phylink instance.
>>>>>
>>>>> Finally we check if we are in a major_config_failed scenario and trigger
>>>>> an interface reconfiguration in the next phylink resolve.
>>>>>
>>>>> In the example scenario where the link was previously torn down due to
>>>>> removal of PCS, the link will be established again as the PCS came back
>>>>> and is now available to phylink.
>>>>>
>>>>> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
>>>>> ---
>>>>
>>>> [...]
>>>>
>>>>> @@ -2151,6 +2204,10 @@ void phylink_destroy(struct phylink *pl)
>>>>>  	if (pl->link_gpio)
>>>>>  		gpiod_put(pl->link_gpio);
>>>>>  
>>>>> +	/* Unregister notifier for late PCS attach */
>>>>> +	if (pl->fwnode_pcs_nb.notifier_call)
>>>>> +		unregister_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
>>>>
>>>> I wanted to try this out, but I get :
>>>>
>>>> drivers/net/phy/phylink.c:2218:17: error: implicit declaration of function ‘unregister_fwnode_pcs_notifier’; did you mean ‘register_fwnode_pcs_notifier’? [-Werror=implicit-function-declaration]
>>>>  2218 |                 unregister_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
>>>>       |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>       |                 register_fwnode_pcs_notifier
>>>>
>>>> I guess you either need to stub this, or there's a missing Kconfig
>>>> dependency somewhere
>>>>
>>>
>>> Hi yes if you want toi test just enable CONFIG_FWNODE_PCS. I forgot to add
>>> the static declaration for unregister_fwnode_pcs_notifier. 
>>
>> I'll give it a go with this yeah, I have a few devices here I'd like to
>> try this on.
>>
>> Can you CC me for the next rounds ?
>>
> 
> Sure, if you can would be good to check also the other commit if everything
> is logically correct.

Absolutely, I'm planning on doing this :) This is quite the series though,
I'll try to give it some deeper look in the upcoming days, I expect net-next
to close soon anyways, so that's as good as it gets for reviewing this :)

Also, it's probably a good idea to have Sean in CC as well, I know a few people
interested in the Xilinx PCS his series brought, hopefully he can follow-up on
this series with the other new PCS drivers.

> 
> BTW by checking test from patchwork I can see also another fix is needed if
> you want to test this revision.
> 
> phylink_create()
> 
> -if (config->num_possible_pcs && pl->mac_ops->mac_select_pcs) {
> +if (config->num_possible_pcs && mac_ops->mac_select_pcs) {

Ack, I'll test it with this change, thanks :)

Maxime

> 
> Aside from these change I expect the current legacy code to be not
> affected by these change.

I'll probably have things to say about this "legacy" naming :)

Thanks for driving this work forwards anyway, that's 

> 



^ permalink raw reply

* Re: [PATCH v2] arm64: tlbflush: Don't broadcast if mm was only active on local cpu
From: Will Deacon @ 2026-06-15 14:43 UTC (permalink / raw)
  To: Ryan Roberts
  Cc: Linu Cherian, Catalin Marinas, Kevin Brodsky, Anshuman Khandual,
	Yang Shi, Mark Rutland, Huang Ying, linux-arm-kernel,
	linux-kernel, shameerali.kolothum.thodi
In-Reply-To: <bfc8803d-b375-477e-bba7-806edaf86578@arm.com>

On Mon, Jun 15, 2026 at 12:21:19PM +0100, Ryan Roberts wrote:
> On 14/06/2026 12:04, Will Deacon wrote:
> > On Sat, May 23, 2026 at 07:17:10PM +0530, Linu Cherian wrote:
> >> From: Ryan Roberts <ryan.roberts@arm.com>
> >>
> >> Testing with 7.1-rc4 :
> >> +-----------------------+---------------------------------------------------+-------------+
> >> | Benchmark             | Result Class                                      |  Improvement|  
> >> +=======================+===================================================+=============+
> >> | perf/syscall          | fork (ops/sec)                                    |   (I) 3.25% |
> >> +-----------------------+---------------------------------------------------+-------------+
> >> | pts/memtier-benchmark | Protocol: Redis Clients: 100 Ratio: 1:5 (Ops/sec) |   (I) 2.70% |
> >> | 			| Protocol: Redis Clients: 100 Ratio: 5:1 (Ops/sec) |   (I) 2.13% |
> >> +-----------------------+---------------------------------------------------+-------------+
> > 
> > I think we need a much more comprehensive set of benchmarks before we can
> > begin to consider a change like this.
> 
> I believe that Linu ran a wider set of benchmarks and didn't find any
> regressions. These are just the ones that show improvement (Linu, please correct
> me and/or provide details).

I think it's important to show the ones that suffer as well... and also
look at different configurations (e.g. preemptible settings) and different
environments (e.g. native vs in a VM).

> Additionally Huang Ying did some testing against the RFC and reported 4.5%
> improvement with Redis:
> 
> https://lore.kernel.org/linux-arm-kernel/87segumv6w.fsf@DESKTOP-5N7EMDA 

To be clear: I'm not disputing that some benchmarks appear to show a small
boost from this series. I'm just worried that's not the whole story.

> >>  arch/arm64/include/asm/mmu.h         |  12 +++
> >>  arch/arm64/include/asm/mmu_context.h |   2 +
> >>  arch/arm64/include/asm/tlbflush.h    | 127 +++++++++++++++++++++------
> >>  arch/arm64/mm/context.c              |  30 ++++++-
> >>  4 files changed, 141 insertions(+), 30 deletions(-)
> > 
> > Doesn't this break BTM/SVM with the SMMU? I think that's a non-starter
> > even if you can provide some more compelling numbers.
> 
> AIUI, we don't support BTM upstream - the SMMU uses private ASIDs and implements
> MMU notifiers to forward the TLBIs via its command queue interface.
> 
> I was also under the impression that supporting BTM upsteam was not desired;
> Please correct me if that's not accurate or if you're aware of plans to add
> support. I've been (coincidentlly) looking at some other stuff that could
> benefit from BTM but had concluded it wouldn't be an acceptable approach upstream.
> 
> If we did ever want to add SMMU BTM support though, I think it would be simple
> enough to add an interface to allow the SMMU to disable the optimization (i.e.
> force active_cpu to ACTIVE_CPU_MULTIPLE)?

We used to have some initial BTM support in the SMMUv3 driver but the
main problem was finding an upstream driver/soc that can use it properly
and so it was ultimately removed in d38c28dbefee ("iommu/arm-smmu-v3: Put
the SVA mmu notifier in the smmu_domain") because it was getting in the
way of wider driver rework and we couldn't test it.

However, there *is* work to re-enable it on top of that rework (and other
changes):

  https://lore.kernel.org/linux-iommu/20250319173202.78988-6-shameerali.kolothum.thodi@huawei.com/

although I don't know if Shameer intends to repost that...

> >> +static inline bool flush_tlb_user_pre(struct mm_struct *mm, tlbf_t flags)
> >> +{
> >> +	unsigned int self, active;
> >> +	bool local;
> >> +
> >> +	migrate_disable();
> >> +
> >> +	if (flags & TLBF_NOBROADCAST) {
> >> +		dsb(nshst);
> >> +		return true;
> >> +	}
> > 
> > Why does the NOBROADCAST case need migration disabled? It didn't before...
> 
> The existing semantic for TLBF_BOBROADCAST is that it emits a local TLBI on
> whatever CPU we happen to be executing on. It's used for lazily fixing up
> spurious faults (i.e. hitting RO TLB entries when the PTE has been relaxed to
> RW). So it's still functionally correct if the thread migrates CPU between
> taking the fault and issuing the local TLBI - in the worst case it just leads to
> another spurious fault.
> 
> For this new case, we need to ensure we don't get migrated between reading
> active_cpu and issuing the local TLBI, otherwise we would only issue a local
> TLBI when a broadcast was required.

Sounds like those two users probably need separating out, then?

> >> +	self = smp_processor_id();
> >> +
> >> +	/*
> >> +	 * The load of mm->context.active_cpu must not be reordered before the
> >> +	 * store to the pgtable that necessitated this flush. This ensures that
> >> +	 * if the value read is our cpu id, then no other cpu can have seen the
> >> +	 * old pgtable value and therefore does not need this old value to be
> >> +	 * flushed from its tlb. But we don't want to upgrade the dsb(ishst),
> >> +	 * needed to make the pgtable updates visible to the walker, to a
> >> +	 * dsb(ish) by default. So speculatively load without a barrier and if
> >> +	 * it indicates our cpu id, then upgrade the barrier and re-load.
> >> +	 */
> >> +	active = READ_ONCE(mm->context.active_cpu);
> >> +	if (active == self) {
> >> +		dsb(ish);
> >> +		active = READ_ONCE(mm->context.active_cpu);
> >> +	} else {
> >> +		dsb(ishst);
> >> +	}
> > 
> > Why can't you just do:
> > 
> > 	dsb(ishst);
> > 	active = READ_ONCE(mm->context.active_cpu);
> > 
> > ?
> 
> Prior to this optimization, we always issued a dsb(ishst) here. Catalin
> suggested the same simplification against the RFC. I believe Linu tried it but
> saw regressions; Hopefully Linu can provide the details.

I don't follow...

The old code always did dsb(ishst). The proposed code here does either
dsb(ish) or dsb(ishst). How can that possibly be faster?

> >> +	local = active == self;
> >> +	if (!local)
> >> +		migrate_enable();
> >> +
> >> +	return local;
> >> +}
> >> +
> >> +static inline void flush_tlb_user_post(bool local)
> >> +{
> >> +	if (local)
> >> +		migrate_enable();
> >> +}
> > 
> > I was under the impression that disabling/enabling migration was an
> > expensive thing to do, so I'd really want to see some more numbers to
> > justify this (including from inside a VM) and allow us to consider the
> > trade-offs properly. It's also not at all clear to me that it's safe
> > from such a low-level TLB invalidation helper.
> 
> I had assumed it wasn't very expensive, but perhaps I'm wrong. I know
> preempt_enable() can be expensive because it has to test to see if it needs to
> reschedule. But I assumed for disabling/enabling migration, it would just be a
> counter and the scheduler would check that it's zero before considing moving the
> task to another run queue. (But I have practically zero understanding of the
> scheduler so I'll assume I'm wrong...).

I'm not an expert here either, but reading the code shows that it has
a preempt guard along with additional book-keeping.

> Instead of disabling migration, perhaps we could re-check active_cpu after
> issuing the local tlbi - if it's now reporting "multiple" we must have been
> migrated and we need to upgrade to a braodcast TLBI?

That's an interesting idea, although I suppose it means the
post-invalidation DSB needs to be ISH for the local case to check the
active_cpu safely?

> >>   *	TLB Invalidation
> >>   *	================
> >> @@ -408,12 +482,20 @@ static inline void flush_tlb_all(void)
> >>  static inline void flush_tlb_mm(struct mm_struct *mm)
> >>  {
> >>  	unsigned long asid;
> >> +	bool local;
> >>  
> >> -	dsb(ishst);
> >> +	local = flush_tlb_user_pre(mm, TLBF_NONE);
> >>  	asid = __TLBI_VADDR(0, ASID(mm));
> >> -	__tlbi(aside1is, asid);
> >> -	__tlbi_user(aside1is, asid);
> >> -	__tlbi_sync_s1ish(mm);
> >> +	if (local) {
> >> +		__tlbi(aside1, asid);
> >> +		__tlbi_user(aside1, asid);
> >> +		dsb(nsh);
> >> +	} else {
> >> +		__tlbi(aside1is, asid);
> >> +		__tlbi_user(aside1is, asid);
> >> +		__tlbi_sync_s1ish(mm);
> >> +	}
> >> +	flush_tlb_user_post(local);
> > 
> > I think you've changed this since Ryan's original patch, but why are you
> > only calling __tlbi_sync_s1ish() for the !local case? Doesn't that break
> > the erratum workaround when running as a VM if the vCPU is migrated?
> 
> Hmm. So from the guest kernel's perspective, it has concluded that it only needs
> to target the local (v)CPU. Since the errata only affect boardcast TLBIs, it
> concludes there is no need to issue the workarounds. But since it's a VM, the HW
> will upgrade the local TLBIs to broadcast TLBIs, but will not magically
> re-instate the workarounds. I guess the simplest solution would be to disable
> the optimization when either workaround is enabled.

That's what I was thinking, but Mark seems to think it's ok. I'll reply
to him on the other part of the thread.

> Perhaps this is all getting a bit too complex for not enough benefit...

I don't think the complexity is unmanageable, but I'm not yet convinced
that this offers any real benefit overall.

Will


^ permalink raw reply

* Re: [PATCH] KVM: arm64: Sync SPSR_EL1 when injecting an exception into a pVM
From: Will Deacon @ 2026-06-15 14:41 UTC (permalink / raw)
  To: Fuad Tabba
  Cc: Marc Zyngier, Oliver Upton, linux-arm-kernel, kvmarm,
	linux-kernel, Joey Gouly, Steffen Eiden, Suzuki K Poulose,
	Zenghui Yu, Catalin Marinas, Sascha Bischoff, Andrew Jones
In-Reply-To: <CA+EHjTyMOoCLQ7d6+TgkrnOJF-PV9K-BKtb4CNuAg8p4gtg6wg@mail.gmail.com>

On Mon, Jun 15, 2026 at 11:52:10AM +0100, Fuad Tabba wrote:
> On Mon, 15 Jun 2026 at 11:05, Will Deacon <will@kernel.org> wrote:
> >
> > On Fri, Jun 12, 2026 at 12:34:14PM +0100, Fuad Tabba wrote:
> > > When pKVM injects a synchronous exception into a protected guest, it
> > > re-enters without restoring the guest's EL1 sysregs and writes the EL1
> > > exception registers to hardware by hand: ESR_EL1 and ELR_EL1, but not
> > > SPSR_EL1. enter_exception64() sets SPSR_EL1 (the interrupted PSTATE)
> > > only in memory, so the guest's handler reads a stale SPSR_EL1 and
> > > restores the wrong PSTATE on eret.
> > >
> > > Write SPSR_EL1 alongside the other exception registers.
> > >
> > > Fixes: 6c30bfb18d0b ("KVM: arm64: Add handlers for protected VM System Registers")
> > > Reported-by: sashiko <sashiko@sashiko.dev>
> > > Signed-off-by: Fuad Tabba <tabba@google.com>
> > > ---
> > >  arch/arm64/kvm/hyp/nvhe/sys_regs.c | 1 +
> > >  1 file changed, 1 insertion(+)
> > >
> > > diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
> > > index 8c3fbb413a06..1a7d5cd16d72 100644
> > > --- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c
> > > +++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
> > > @@ -268,6 +268,7 @@ static void inject_sync64(struct kvm_vcpu *vcpu, u64 esr)
> > >
> > >       write_sysreg_el1(esr, SYS_ESR);
> > >       write_sysreg_el1(read_sysreg_el2(SYS_ELR), SYS_ELR);
> > > +     write_sysreg_el1(read_sysreg_el2(SYS_SPSR), SYS_SPSR);
> > >       write_sysreg_el2(*vcpu_pc(vcpu), SYS_ELR);
> > >       write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
> > >  }
> >
> > Is SPSR_EL1 not set in enter_exception64() using vcpu_cpsr(vcpu), which
> > *is* set here? I'm just a bit wary of the report, as I'd have expected
> > fireworks if we weren't initialising the guest's SPSR on the exception
> > injection path.
> 
> Yes, enter_exception64() sets SPSR_EL1, but only in memory:
> __vcpu_write_spsr() takes the nVHE path and calls
> __vcpu_assign_sys_reg(vcpu, SPSR_EL1, val), which writes
> vcpu->arch.ctxt.sys_regs[SPSR_EL1] without touching the hardware
> register.
> 
> In the normal nVHE entry path that memory value reaches hardware via
> __sysreg_restore_state_nvhe() before __guest_enter(). But
> inject_sync64() runs inside the fixup_guest_exit() loop, which
> re-enters the guest directly without a sysreg restore pass. ESR_EL1
> and ELR_EL1 are already written to hardware by hand for this reason
> but SPSR_EL1 was missed.

Ah, I see. Does that mean that all the in-memory updates performed by
enter_exception64() (e.g. the construction of the cpsr) are ignored too?

Will


^ permalink raw reply

* Re: [PATCH net-next v7 05/12] net: phylink: support late PCS provider attach
From: Christian Marangi @ 2026-06-15 14:35 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan, Lorenzo Bianconi,
	Heiner Kallweit, Russell King, Saravana Kannan, Philipp Zabel,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	netdev, devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-mediatek, llvm
In-Reply-To: <7702ac09-75fd-49de-8ad2-fceaa122b627@bootlin.com>

On Mon, Jun 15, 2026 at 04:29:04PM +0200, Maxime Chevallier wrote:
> 
> 
> On 6/15/26 16:10, Christian Marangi wrote:
> > On Mon, Jun 15, 2026 at 04:07:03PM +0200, Maxime Chevallier wrote:
> >> Hi Christian,
> >>
> >> On 6/15/26 14:29, Christian Marangi wrote:
> >>> Add support for late PCS provider attachment to a phylink instance.
> >>> This works by creating a global notifier for the PCS provider and
> >>> making each phylink instance that makes use of fwnode subscribe to
> >>> this notifier.
> >>>
> >>> The PCS notifier will emit the event FWNODE_PCS_PROVIDER_ADD every time
> >>> a new PCS provider is added.
> >>>
> >>> phylink will then react to this event and will call the new function
> >>> fwnode_phylink_pcs_get_from_fwnode() that will check if the PCS fwnode
> >>> provided by the event is present in the pcs-handle property of the
> >>> phylink instance.
> >>>
> >>> If a related PCS is found, then such PCS is added to the phylink
> >>> instance PCS list.
> >>>
> >>> Then we link the PCS to the phylink instance and we refresh the supported
> >>> interfaces of the phylink instance.
> >>>
> >>> Finally we check if we are in a major_config_failed scenario and trigger
> >>> an interface reconfiguration in the next phylink resolve.
> >>>
> >>> In the example scenario where the link was previously torn down due to
> >>> removal of PCS, the link will be established again as the PCS came back
> >>> and is now available to phylink.
> >>>
> >>> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> >>> ---
> >>
> >> [...]
> >>
> >>> @@ -2151,6 +2204,10 @@ void phylink_destroy(struct phylink *pl)
> >>>  	if (pl->link_gpio)
> >>>  		gpiod_put(pl->link_gpio);
> >>>  
> >>> +	/* Unregister notifier for late PCS attach */
> >>> +	if (pl->fwnode_pcs_nb.notifier_call)
> >>> +		unregister_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
> >>
> >> I wanted to try this out, but I get :
> >>
> >> drivers/net/phy/phylink.c:2218:17: error: implicit declaration of function ‘unregister_fwnode_pcs_notifier’; did you mean ‘register_fwnode_pcs_notifier’? [-Werror=implicit-function-declaration]
> >>  2218 |                 unregister_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
> >>       |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >>       |                 register_fwnode_pcs_notifier
> >>
> >> I guess you either need to stub this, or there's a missing Kconfig
> >> dependency somewhere
> >>
> > 
> > Hi yes if you want toi test just enable CONFIG_FWNODE_PCS. I forgot to add
> > the static declaration for unregister_fwnode_pcs_notifier. 
> 
> I'll give it a go with this yeah, I have a few devices here I'd like to
> try this on.
> 
> Can you CC me for the next rounds ?
> 

Sure, if you can would be good to check also the other commit if everything
is logically correct.

BTW by checking test from patchwork I can see also another fix is needed if
you want to test this revision.

phylink_create()

-if (config->num_possible_pcs && pl->mac_ops->mac_select_pcs) {
+if (config->num_possible_pcs && mac_ops->mac_select_pcs) {

Aside from these change I expect the current legacy code to be not
affected by these change.

-- 
	Ansuel


^ permalink raw reply

* [PATCH net-next v7 05/12] net: phylink: support late PCS provider attach
From: Christian Marangi @ 2026-06-15 12:29 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan, Christian Marangi,
	Lorenzo Bianconi, Heiner Kallweit, Russell King, Saravana Kannan,
	Philipp Zabel, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, netdev, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-mediatek, llvm
In-Reply-To: <20260615122950.22281-1-ansuelsmth@gmail.com>

Add support for late PCS provider attachment to a phylink instance.
This works by creating a global notifier for the PCS provider and
making each phylink instance that makes use of fwnode subscribe to
this notifier.

The PCS notifier will emit the event FWNODE_PCS_PROVIDER_ADD every time
a new PCS provider is added.

phylink will then react to this event and will call the new function
fwnode_phylink_pcs_get_from_fwnode() that will check if the PCS fwnode
provided by the event is present in the pcs-handle property of the
phylink instance.

If a related PCS is found, then such PCS is added to the phylink
instance PCS list.

Then we link the PCS to the phylink instance and we refresh the supported
interfaces of the phylink instance.

Finally we check if we are in a major_config_failed scenario and trigger
an interface reconfiguration in the next phylink resolve.

In the example scenario where the link was previously torn down due to
removal of PCS, the link will be established again as the PCS came back
and is now available to phylink.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
 drivers/net/pcs/pcs.c     | 49 ++++++++++++++++++++++++++++++++
 drivers/net/phy/phylink.c | 57 +++++++++++++++++++++++++++++++++++++
 include/linux/pcs/pcs.h   | 60 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 166 insertions(+)

diff --git a/drivers/net/pcs/pcs.c b/drivers/net/pcs/pcs.c
index 67f9716f48fd..713b2ec22c97 100644
--- a/drivers/net/pcs/pcs.c
+++ b/drivers/net/pcs/pcs.c
@@ -22,6 +22,19 @@ struct fwnode_pcs_provider {
 
 static LIST_HEAD(fwnode_pcs_providers);
 static DEFINE_MUTEX(fwnode_pcs_mutex);
+static BLOCKING_NOTIFIER_HEAD(fwnode_pcs_notify_list);
+
+int register_fwnode_pcs_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&fwnode_pcs_notify_list, nb);
+}
+EXPORT_SYMBOL_GPL(register_fwnode_pcs_notifier);
+
+int unregister_fwnode_pcs_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&fwnode_pcs_notify_list, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_fwnode_pcs_notifier);
 
 struct phylink_pcs *fwnode_pcs_simple_get(struct fwnode_reference_args *pcsspec,
 					  void *data)
@@ -55,6 +68,10 @@ int fwnode_pcs_add_provider(struct fwnode_handle *fwnode,
 
 	fwnode_dev_initialized(fwnode, true);
 
+	blocking_notifier_call_chain(&fwnode_pcs_notify_list,
+				     FWNODE_PCS_PROVIDER_ADD,
+				     fwnode);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(fwnode_pcs_add_provider);
@@ -150,6 +167,38 @@ struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode, unsigned int in
 }
 EXPORT_SYMBOL_GPL(fwnode_pcs_get);
 
+struct phylink_pcs *
+fwnode_phylink_pcs_get_from_fwnode(struct fwnode_handle *fwnode,
+				   struct fwnode_handle *pcs_fwnode)
+{
+	struct fwnode_reference_args pcsspec;
+	int index = 0;
+	int ret;
+
+	/* Loop until we find a matching PCS node or
+	 * fwnode_parse_pcsspec() returns error
+	 * if we don't have any other PCS reference to check.
+	 */
+	while (true) {
+		ret = fwnode_parse_pcsspec(fwnode, index, NULL, &pcsspec);
+		if (ret)
+			return ERR_PTR(ret);
+
+		/* Exit loop if we found the matching PCS node */
+		if (pcsspec.fwnode == pcs_fwnode) {
+			fwnode_handle_put(pcsspec.fwnode);
+			break;
+		}
+
+		/* Check the next PCS reference */
+		fwnode_handle_put(pcsspec.fwnode);
+		index++;
+	}
+
+	return fwnode_pcs_get(fwnode, index);
+}
+EXPORT_SYMBOL_GPL(fwnode_phylink_pcs_get_from_fwnode);
+
 unsigned int fwnode_phylink_pcs_count(struct fwnode_handle *fwnode)
 {
 	struct fwnode_reference_args out_args;
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index ca4dad4b140a..0734c98498a9 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -12,6 +12,7 @@
 #include <linux/netdevice.h>
 #include <linux/of.h>
 #include <linux/of_mdio.h>
+#include <linux/pcs/pcs.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
 #include <linux/phylink.h>
@@ -62,6 +63,7 @@ struct phylink {
 
 	/* List of available PCS */
 	struct list_head pcs_list;
+	struct notifier_block fwnode_pcs_nb;
 
 	/* What interface are supported by the current link.
 	 * Can change on removal or addition of new PCS.
@@ -1997,6 +1999,51 @@ static int phylink_fill_available_pcs(struct phylink *pl,
 	return ret;
 }
 
+static int pcs_provider_notify(struct notifier_block *self,
+			       unsigned long val, void *data)
+{
+	struct phylink *pl = container_of(self, struct phylink, fwnode_pcs_nb);
+	struct fwnode_handle *pcs_fwnode = data;
+	struct phylink_pcs *pcs;
+
+	/* Check if the just added PCS provider is
+	 * in the phylink instance pcs-handle property.
+	 */
+	pcs = fwnode_phylink_pcs_get_from_fwnode(dev_fwnode(pl->config->dev),
+						 pcs_fwnode);
+	if (IS_ERR(pcs))
+		return NOTIFY_DONE;
+
+	/* Add the PCS */
+	rtnl_lock();
+
+	mutex_lock(&pl->state_mutex);
+
+	/* Link PCS with phylink */
+	list_add(&pcs->list, &pl->pcs_list);
+	pcs->phylink = pl;
+
+	/* Refresh supported interfaces */
+	phy_interface_copy(pl->supported_interfaces,
+			   pl->config->supported_interfaces);
+	list_for_each_entry(pcs, &pl->pcs_list, list)
+		phy_interface_or(pl->supported_interfaces,
+				 pl->supported_interfaces,
+				 pcs->supported_interfaces);
+
+	/* Force an interface reconfig if major config fail */
+	if (pl->major_config_failed)
+		pl->force_major_config = true;
+
+	mutex_unlock(&pl->state_mutex);
+
+	rtnl_unlock();
+
+	phylink_run_resolve(pl);
+
+	return NOTIFY_OK;
+}
+
 /**
  * phylink_create() - create a phylink instance
  * @config: a pointer to the target &struct phylink_config
@@ -2068,6 +2115,12 @@ struct phylink *phylink_create(struct phylink_config *config,
 				 pl->supported_interfaces,
 				 pcs->supported_interfaces);
 
+	/* Register notifier for late PCS attach */
+	if (!phy_interface_empty(config->pcs_interfaces)) {
+		pl->fwnode_pcs_nb.notifier_call = pcs_provider_notify;
+		register_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
+	}
+
 	pl->config = config;
 	if (config->type == PHYLINK_NETDEV) {
 		pl->netdev = to_net_dev(config->dev);
@@ -2151,6 +2204,10 @@ void phylink_destroy(struct phylink *pl)
 	if (pl->link_gpio)
 		gpiod_put(pl->link_gpio);
 
+	/* Unregister notifier for late PCS attach */
+	if (pl->fwnode_pcs_nb.notifier_call)
+		unregister_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
+
 	/* Drop link between PCS and phylink */
 	list_for_each_entry(pcs, &pl->pcs_list, list)
 		pcs->phylink = NULL;
diff --git a/include/linux/pcs/pcs.h b/include/linux/pcs/pcs.h
index df1e6f32cfad..9de3f273428e 100644
--- a/include/linux/pcs/pcs.h
+++ b/include/linux/pcs/pcs.h
@@ -4,7 +4,36 @@
 
 #include <linux/phylink.h>
 
+enum fwnode_pcs_notify_event {
+	FWNODE_PCS_PROVIDER_ADD,
+};
+
 #if IS_ENABLED(CONFIG_FWNODE_PCS)
+/**
+ * register_fwnode_pcs_notifier - Register a notifier block for fwnode
+ *				  PCS events
+ * @nb: pointer to the notifier block
+ *
+ * Registers a notifier block to the fwnode_pcs_notify_list blocking
+ * notifier chain. This allows phylink instance to subscribe for
+ * PCS provider events.
+ *
+ * Returns: 0 or a negative error.
+ */
+int register_fwnode_pcs_notifier(struct notifier_block *nb);
+
+/**
+ * unregister_fwnode_pcs_notifier - Unregister a notifier block for fwnode
+ *				    PCS events
+ * @nb: pointer to the notifier block
+ *
+ * Unregisters a notifier block to the fwnode_pcs_notify_list blocking
+ * notifier chain.
+ *
+ * Returns: 0 or a negative error.
+ */
+int unregister_fwnode_pcs_notifier(struct notifier_block *nb);
+
 /**
  * fwnode_pcs_get - Retrieves a PCS from a firmware node
  * @fwnode: firmware node
@@ -20,6 +49,25 @@
 struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode,
 				   unsigned int index);
 
+/**
+ * fwnode_phylink_pcs_get_from_fwnode - Retrieves the PCS provided
+ *					by the firmware node from a
+ *					firmware node
+ * @fwnode: firmware node
+ * @pcs_fwnode: PCS firmware node
+ *
+ * Parse 'pcs-handle' in 'fwnode' and get the PCS that match
+ * 'pcs_fwnode' firmware node.
+ *
+ * Returns: a pointer to the phylink_pcs or a negative
+ * error pointer. Can return -EPROBE_DEFER if the PCS is not
+ * present in global providers list (either due to driver
+ * still needs to be probed or it failed to probe/removed)
+ */
+struct phylink_pcs *
+fwnode_phylink_pcs_get_from_fwnode(struct fwnode_handle *fwnode,
+				   struct fwnode_handle *pcs_fwnode);
+
 /**
  * fwnode_phylink_pcs_count - count PCS entries described in firmware node
  * @fwnode: firmware node
@@ -53,12 +101,24 @@ int fwnode_phylink_pcs_parse(struct fwnode_handle *fwnode,
 			     struct phylink_pcs **available_pcs,
 			     unsigned int num_pcs);
 #else
+static inline int register_fwnode_pcs_notifier(struct notifier_block *nb)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode,
 						 int index)
 {
 	return ERR_PTR(-ENOENT);
 }
 
+static inline struct phylink_pcs *
+fwnode_phylink_pcs_get_from_fwnode(struct fwnode_handle *fwnode,
+				   struct fwnode_handle *pcs_fwnode)
+{
+	return ERR_PTR(-ENOENT);
+}
+
 static inline unsigned int fwnode_phylink_pcs_count(struct fwnode_handle *fwnode)
 {
 	return 0;
-- 
2.53.0



^ permalink raw reply related

* Re: [PATCH v2 02/11] ASoC: fsl_audmix: Use guard() for spin locks
From: Frank Li @ 2026-06-15 14:30 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-3-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:15PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for spin locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/fsl_audmix.c | 11 ++++-------
>  1 file changed, 4 insertions(+), 7 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c
> index 40a3b7432174..066239c64037 100644
> --- a/sound/soc/fsl/fsl_audmix.c
> +++ b/sound/soc/fsl/fsl_audmix.c
> @@ -280,7 +280,6 @@ static int fsl_audmix_dai_trigger(struct snd_pcm_substream *substream, int cmd,
>  				  struct snd_soc_dai *dai)
>  {
>  	struct fsl_audmix *priv = snd_soc_dai_get_drvdata(dai);
> -	unsigned long lock_flags;
>
>  	/* Capture stream shall not be handled */
>  	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
> @@ -290,16 +289,14 @@ static int fsl_audmix_dai_trigger(struct snd_pcm_substream *substream, int cmd,
>  	case SNDRV_PCM_TRIGGER_START:
>  	case SNDRV_PCM_TRIGGER_RESUME:
>  	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> -		spin_lock_irqsave(&priv->lock, lock_flags);
> -		priv->tdms |= BIT(dai->driver->id);
> -		spin_unlock_irqrestore(&priv->lock, lock_flags);
> +		scoped_guard(spinlock_irqsave, &priv->lock)
> +			priv->tdms |= BIT(dai->driver->id);
>  		break;
>  	case SNDRV_PCM_TRIGGER_STOP:
>  	case SNDRV_PCM_TRIGGER_SUSPEND:
>  	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> -		spin_lock_irqsave(&priv->lock, lock_flags);
> -		priv->tdms &= ~BIT(dai->driver->id);
> -		spin_unlock_irqrestore(&priv->lock, lock_flags);
> +		scoped_guard(spinlock_irqsave, &priv->lock)
> +			priv->tdms &= ~BIT(dai->driver->id);
>  		break;
>  	default:
>  		return -EINVAL;
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH net-next v7 05/12] net: phylink: support late PCS provider attach
From: Maxime Chevallier @ 2026-06-15 14:29 UTC (permalink / raw)
  To: Christian Marangi
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan, Lorenzo Bianconi,
	Heiner Kallweit, Russell King, Saravana Kannan, Philipp Zabel,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	netdev, devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-mediatek, llvm
In-Reply-To: <6a3007ce.73de60af.3a056d.d903@mx.google.com>



On 6/15/26 16:10, Christian Marangi wrote:
> On Mon, Jun 15, 2026 at 04:07:03PM +0200, Maxime Chevallier wrote:
>> Hi Christian,
>>
>> On 6/15/26 14:29, Christian Marangi wrote:
>>> Add support for late PCS provider attachment to a phylink instance.
>>> This works by creating a global notifier for the PCS provider and
>>> making each phylink instance that makes use of fwnode subscribe to
>>> this notifier.
>>>
>>> The PCS notifier will emit the event FWNODE_PCS_PROVIDER_ADD every time
>>> a new PCS provider is added.
>>>
>>> phylink will then react to this event and will call the new function
>>> fwnode_phylink_pcs_get_from_fwnode() that will check if the PCS fwnode
>>> provided by the event is present in the pcs-handle property of the
>>> phylink instance.
>>>
>>> If a related PCS is found, then such PCS is added to the phylink
>>> instance PCS list.
>>>
>>> Then we link the PCS to the phylink instance and we refresh the supported
>>> interfaces of the phylink instance.
>>>
>>> Finally we check if we are in a major_config_failed scenario and trigger
>>> an interface reconfiguration in the next phylink resolve.
>>>
>>> In the example scenario where the link was previously torn down due to
>>> removal of PCS, the link will be established again as the PCS came back
>>> and is now available to phylink.
>>>
>>> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
>>> ---
>>
>> [...]
>>
>>> @@ -2151,6 +2204,10 @@ void phylink_destroy(struct phylink *pl)
>>>  	if (pl->link_gpio)
>>>  		gpiod_put(pl->link_gpio);
>>>  
>>> +	/* Unregister notifier for late PCS attach */
>>> +	if (pl->fwnode_pcs_nb.notifier_call)
>>> +		unregister_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
>>
>> I wanted to try this out, but I get :
>>
>> drivers/net/phy/phylink.c:2218:17: error: implicit declaration of function ‘unregister_fwnode_pcs_notifier’; did you mean ‘register_fwnode_pcs_notifier’? [-Werror=implicit-function-declaration]
>>  2218 |                 unregister_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
>>       |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>       |                 register_fwnode_pcs_notifier
>>
>> I guess you either need to stub this, or there's a missing Kconfig
>> dependency somewhere
>>
> 
> Hi yes if you want toi test just enable CONFIG_FWNODE_PCS. I forgot to add
> the static declaration for unregister_fwnode_pcs_notifier. 

I'll give it a go with this yeah, I have a few devices here I'd like to
try this on.

Can you CC me for the next rounds ?

Maxime

> 



^ permalink raw reply

* Re: [PATCH v2 11/11] ASoC: fsl: mpc5200_psc_ac97: Use guard() for mutex locks
From: Frank Li @ 2026-06-15 14:26 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-12-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:24PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for mutex locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>
> Changes in v2:
>  - psc_ac97_cold_reset(): Fix scoped_guard() usage by replacing
>    scoped_guard(mutex_lock, ...) with scoped_guard(mutex, ...).
>
>  sound/soc/fsl/mpc5200_psc_ac97.c | 34 +++++++++++---------------------
>  1 file changed, 12 insertions(+), 22 deletions(-)
>
> diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
> index 8554fb690772..d4d9f5b6bc07 100644
> --- a/sound/soc/fsl/mpc5200_psc_ac97.c
> +++ b/sound/soc/fsl/mpc5200_psc_ac97.c
> @@ -31,14 +31,13 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
>  	int status;
>  	unsigned int val;
>
> -	mutex_lock(&psc_dma->mutex);
> +	guard(mutex)(&psc_dma->mutex);
>
>  	/* Wait for command send status zero = ready */
>  	status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
>  				MPC52xx_PSC_SR_CMDSEND), 100, 0);
>  	if (status == 0) {
>  		pr_err("timeout on ac97 bus (rdy)\n");
> -		mutex_unlock(&psc_dma->mutex);
>  		return -ENODEV;
>  	}
>
> @@ -54,19 +53,16 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
>  	if (status == 0) {
>  		pr_err("timeout on ac97 read (val) %x\n",
>  				in_be16(&psc_dma->psc_regs->sr_csr.status));
> -		mutex_unlock(&psc_dma->mutex);
>  		return -ENODEV;
>  	}
>  	/* Get the data */
>  	val = in_be32(&psc_dma->psc_regs->ac97_data);
>  	if (((val >> 24) & 0x7f) != reg) {
>  		pr_err("reg echo error on ac97 read\n");
> -		mutex_unlock(&psc_dma->mutex);
>  		return -ENODEV;
>  	}
>  	val = (val >> 8) & 0xffff;
>
> -	mutex_unlock(&psc_dma->mutex);
>  	return (unsigned short) val;
>  }
>
> @@ -75,52 +71,46 @@ static void psc_ac97_write(struct snd_ac97 *ac97,
>  {
>  	int status;
>
> -	mutex_lock(&psc_dma->mutex);
> +	guard(mutex)(&psc_dma->mutex);
>
>  	/* Wait for command status zero = ready */
>  	status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
>  				MPC52xx_PSC_SR_CMDSEND), 100, 0);
>  	if (status == 0) {
>  		pr_err("timeout on ac97 bus (write)\n");
> -		goto out;
> +		return;
>  	}
>  	/* Write data */
>  	out_be32(&psc_dma->psc_regs->ac97_cmd,
>  			((reg & 0x7f) << 24) | (val << 8));
> -
> - out:
> -	mutex_unlock(&psc_dma->mutex);
>  }
>
>  static void psc_ac97_warm_reset(struct snd_ac97 *ac97)
>  {
>  	struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
>
> -	mutex_lock(&psc_dma->mutex);
> +	guard(mutex)(&psc_dma->mutex);
>
>  	out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR);
>  	udelay(3);
>  	out_be32(&regs->sicr, psc_dma->sicr);
> -
> -	mutex_unlock(&psc_dma->mutex);
>  }
>
>  static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
>  {
>  	struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
>
> -	mutex_lock(&psc_dma->mutex);
> -	dev_dbg(psc_dma->dev, "cold reset\n");
> +	scoped_guard(mutex, &psc_dma->mutex) {
> +		dev_dbg(psc_dma->dev, "cold reset\n");
>
> -	mpc5200_psc_ac97_gpio_reset(psc_dma->id);
> +		mpc5200_psc_ac97_gpio_reset(psc_dma->id);
>
> -	/* Notify the PSC that a reset has occurred */
> -	out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_ACRB);
> +		/* Notify the PSC that a reset has occurred */
> +		out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_ACRB);
>
> -	/* Re-enable RX and TX */
> -	out_8(&regs->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
> -
> -	mutex_unlock(&psc_dma->mutex);
> +		/* Re-enable RX and TX */
> +		out_8(&regs->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
> +	}
>
>  	usleep_range(1000, 2000);
>  	psc_ac97_warm_reset(ac97);
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH v2 06/11] ASoC: fsl_ssi: Use guard() for mutex locks
From: Frank Li @ 2026-06-15 14:25 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-7-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:19PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for mutex locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/fsl_ssi.c | 13 ++++---------
>  1 file changed, 4 insertions(+), 9 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
> index b2e1da1781ae..dc022976c982 100644
> --- a/sound/soc/fsl/fsl_ssi.c
> +++ b/sound/soc/fsl/fsl_ssi.c
> @@ -1218,13 +1218,13 @@ static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
>  	if (reg > 0x7f)
>  		return;
>
> -	mutex_lock(&fsl_ac97_data->ac97_reg_lock);
> +	guard(mutex)(&fsl_ac97_data->ac97_reg_lock);
>
>  	ret = clk_prepare_enable(fsl_ac97_data->clk);
>  	if (ret) {
>  		pr_err("ac97 write clk_prepare_enable failed: %d\n",
>  			ret);
> -		goto ret_unlock;
> +		return;
>  	}
>
>  	lreg = reg <<  12;
> @@ -1238,9 +1238,6 @@ static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
>  	udelay(100);
>
>  	clk_disable_unprepare(fsl_ac97_data->clk);
> -
> -ret_unlock:
> -	mutex_unlock(&fsl_ac97_data->ac97_reg_lock);
>  }
>
>  static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
> @@ -1252,12 +1249,12 @@ static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
>  	unsigned int lreg;
>  	int ret;
>
> -	mutex_lock(&fsl_ac97_data->ac97_reg_lock);
> +	guard(mutex)(&fsl_ac97_data->ac97_reg_lock);
>
>  	ret = clk_prepare_enable(fsl_ac97_data->clk);
>  	if (ret) {
>  		pr_err("ac97 read clk_prepare_enable failed: %d\n", ret);
> -		goto ret_unlock;
> +		return val;
>  	}
>
>  	lreg = (reg & 0x7f) <<  12;
> @@ -1272,8 +1269,6 @@ static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
>
>  	clk_disable_unprepare(fsl_ac97_data->clk);
>
> -ret_unlock:
> -	mutex_unlock(&fsl_ac97_data->ac97_reg_lock);
>  	return val;
>  }
>
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH v2 03/11] ASoC: fsl_easrc: Use guard() for spin locks
From: Frank Li @ 2026-06-15 14:24 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-4-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:16PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for spin locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/fsl_easrc.c | 36 ++++++++++--------------------------
>  1 file changed, 10 insertions(+), 26 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
> index 114a6c0b6b73..edfd943197a0 100644
> --- a/sound/soc/fsl/fsl_easrc.c
> +++ b/sound/soc/fsl/fsl_easrc.c
> @@ -1025,7 +1025,6 @@ static int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id)
>  	struct fsl_easrc_ctx_priv *ctx_priv;
>  	struct fsl_asrc_pair *ctx;
>  	struct device *dev;
> -	unsigned long lock_flags;
>  	int ret;
>
>  	if (!easrc)
> @@ -1053,9 +1052,8 @@ static int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id)
>  	if (ret)
>  		return ret;
>
> -	spin_lock_irqsave(&easrc->lock, lock_flags);
> -	ret = fsl_easrc_config_slot(easrc, ctx->index);
> -	spin_unlock_irqrestore(&easrc->lock, lock_flags);
> +	scoped_guard(spinlock_irqsave, &easrc->lock)
> +		ret = fsl_easrc_config_slot(easrc, ctx->index);
>  	if (ret)
>  		return ret;
>
> @@ -1301,13 +1299,12 @@ static int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx)
>  	enum asrc_pair_index index = ASRC_INVALID_PAIR;
>  	struct fsl_asrc *easrc = ctx->asrc;
>  	struct device *dev;
> -	unsigned long lock_flags;
>  	int ret = 0;
>  	int i;
>
>  	dev = &easrc->pdev->dev;
>
> -	spin_lock_irqsave(&easrc->lock, lock_flags);
> +	guard(spinlock_irqsave)(&easrc->lock);
>
>  	for (i = ASRC_PAIR_A; i < EASRC_CTX_MAX_NUM; i++) {
>  		if (easrc->pair[i])
> @@ -1331,8 +1328,6 @@ static int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx)
>  		easrc->channel_avail -= channels;
>  	}
>
> -	spin_unlock_irqrestore(&easrc->lock, lock_flags);
> -
>  	return ret;
>  }
>
> @@ -1343,7 +1338,6 @@ static int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx)
>   */
>  static void fsl_easrc_release_context(struct fsl_asrc_pair *ctx)
>  {
> -	unsigned long lock_flags;
>  	struct fsl_asrc *easrc;
>
>  	if (!ctx)
> @@ -1351,14 +1345,12 @@ static void fsl_easrc_release_context(struct fsl_asrc_pair *ctx)
>
>  	easrc = ctx->asrc;
>
> -	spin_lock_irqsave(&easrc->lock, lock_flags);
> +	guard(spinlock_irqsave)(&easrc->lock);
>
>  	fsl_easrc_release_slot(easrc, ctx->index);
>
>  	easrc->channel_avail += ctx->channels;
>  	easrc->pair[ctx->index] = NULL;
> -
> -	spin_unlock_irqrestore(&easrc->lock, lock_flags);
>  }
>
>  /*
> @@ -2292,15 +2284,13 @@ static int fsl_easrc_runtime_suspend(struct device *dev)
>  {
>  	struct fsl_asrc *easrc = dev_get_drvdata(dev);
>  	struct fsl_easrc_priv *easrc_priv = easrc->private;
> -	unsigned long lock_flags;
>
>  	regcache_cache_only(easrc->regmap, true);
>
>  	clk_disable_unprepare(easrc->mem_clk);
>
> -	spin_lock_irqsave(&easrc->lock, lock_flags);
> -	easrc_priv->firmware_loaded = 0;
> -	spin_unlock_irqrestore(&easrc->lock, lock_flags);
> +	scoped_guard(spinlock_irqsave, &easrc->lock)
> +		easrc_priv->firmware_loaded = 0;
>
>  	return 0;
>  }
> @@ -2311,7 +2301,6 @@ static int fsl_easrc_runtime_resume(struct device *dev)
>  	struct fsl_easrc_priv *easrc_priv = easrc->private;
>  	struct fsl_easrc_ctx_priv *ctx_priv;
>  	struct fsl_asrc_pair *ctx;
> -	unsigned long lock_flags;
>  	int ret;
>  	int i;
>
> @@ -2323,13 +2312,11 @@ static int fsl_easrc_runtime_resume(struct device *dev)
>  	regcache_mark_dirty(easrc->regmap);
>  	regcache_sync(easrc->regmap);
>
> -	spin_lock_irqsave(&easrc->lock, lock_flags);
> -	if (easrc_priv->firmware_loaded) {
> -		spin_unlock_irqrestore(&easrc->lock, lock_flags);
> -		goto skip_load;
> +	scoped_guard(spinlock_irqsave, &easrc->lock) {
> +		if (easrc_priv->firmware_loaded)
> +			return 0;
> +		easrc_priv->firmware_loaded = 1;
>  	}
> -	easrc_priv->firmware_loaded = 1;
> -	spin_unlock_irqrestore(&easrc->lock, lock_flags);
>
>  	ret = fsl_easrc_get_firmware(easrc);
>  	if (ret) {
> @@ -2377,9 +2364,6 @@ static int fsl_easrc_runtime_resume(struct device *dev)
>  			goto disable_mem_clk;
>  	}
>
> -skip_load:
> -	return 0;
> -
>  disable_mem_clk:
>  	clk_disable_unprepare(easrc->mem_clk);
>  	return ret;
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH v2 07/11] ASoC: fsl_xcvr: Use guard() for spin locks
From: Frank Li @ 2026-06-15 14:19 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-8-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:20PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for spin locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/fsl_xcvr.c | 29 ++++++++++++-----------------
>  1 file changed, 12 insertions(+), 17 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
> index 6677d3bf36ec..41d100500534 100644
> --- a/sound/soc/fsl/fsl_xcvr.c
> +++ b/sound/soc/fsl/fsl_xcvr.c
> @@ -797,10 +797,9 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  {
>  	struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);
>  	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
> -	unsigned long lock_flags;
>  	int ret = 0;
>
> -	spin_lock_irqsave(&xcvr->lock, lock_flags);
> +	guard(spinlock_irqsave)(&xcvr->lock);
>
>  	switch (cmd) {
>  	case SNDRV_PCM_TRIGGER_START:
> @@ -812,7 +811,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  					 FSL_XCVR_EXT_CTRL_DPTH_RESET(tx));
>  		if (ret < 0) {
>  			dev_err(dai->dev, "Failed to set DPATH RESET: %d\n", ret);
> -			goto release_lock;
> +			return ret;
>  		}
>
>  		if (tx) {
> @@ -824,7 +823,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  						   FSL_XCVR_ISR_CMDC_TX_EN);
>  				if (ret < 0) {
>  					dev_err(dai->dev, "err updating isr %d\n", ret);
> -					goto release_lock;
> +					return ret;
>  				}
>  				fallthrough;
>  			case FSL_XCVR_MODE_SPDIF:
> @@ -833,7 +832,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  						      FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
>  				if (ret < 0) {
>  					dev_err(dai->dev, "Failed to start DATA_TX: %d\n", ret);
> -					goto release_lock;
> +					return ret;
>  				}
>  				break;
>  			}
> @@ -844,14 +843,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  					 FSL_XCVR_EXT_CTRL_DMA_DIS(tx), 0);
>  		if (ret < 0) {
>  			dev_err(dai->dev, "Failed to enable DMA: %d\n", ret);
> -			goto release_lock;
> +			return ret;
>  		}
>
>  		ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
>  					 FSL_XCVR_IRQ_EARC_ALL, FSL_XCVR_IRQ_EARC_ALL);
>  		if (ret < 0) {
>  			dev_err(dai->dev, "Error while setting IER0: %d\n", ret);
> -			goto release_lock;
> +			return ret;
>  		}
>
>  		/* clear DPATH RESET */
> @@ -860,7 +859,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  					 0);
>  		if (ret < 0) {
>  			dev_err(dai->dev, "Failed to clear DPATH RESET: %d\n", ret);
> -			goto release_lock;
> +			return ret;
>  		}
>
>  		break;
> @@ -873,14 +872,14 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  					 FSL_XCVR_EXT_CTRL_DMA_DIS(tx));
>  		if (ret < 0) {
>  			dev_err(dai->dev, "Failed to disable DMA: %d\n", ret);
> -			goto release_lock;
> +			return ret;
>  		}
>
>  		ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,
>  					 FSL_XCVR_IRQ_EARC_ALL, 0);
>  		if (ret < 0) {
>  			dev_err(dai->dev, "Failed to clear IER0: %d\n", ret);
> -			goto release_lock;
> +			return ret;
>  		}
>
>  		if (tx) {
> @@ -891,7 +890,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  							FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
>  				if (ret < 0) {
>  					dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret);
> -					goto release_lock;
> +					return ret;
>  				}
>  				if (xcvr->soc_data->spdif_only)
>  					break;
> @@ -905,7 +904,7 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  				if (ret < 0) {
>  					dev_err(dai->dev,
>  						"Err updating ISR %d\n", ret);
> -					goto release_lock;
> +					return ret;
>  				}
>  				break;
>  			}
> @@ -916,8 +915,6 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
>  		break;
>  	}
>
> -release_lock:
> -	spin_unlock_irqrestore(&xcvr->lock, lock_flags);
>  	return ret;
>  }
>
> @@ -1448,11 +1445,10 @@ static void reset_rx_work(struct work_struct *work)
>  {
>  	struct fsl_xcvr *xcvr = container_of(work, struct fsl_xcvr, work_rst);
>  	struct device *dev = &xcvr->pdev->dev;
> -	unsigned long lock_flags;
>  	u32 ext_ctrl;
>
>  	dev_dbg(dev, "reset rx path\n");
> -	spin_lock_irqsave(&xcvr->lock, lock_flags);
> +	guard(spinlock_irqsave)(&xcvr->lock);
>  	regmap_read(xcvr->regmap, FSL_XCVR_EXT_CTRL, &ext_ctrl);
>
>  	if (!(ext_ctrl & FSL_XCVR_EXT_CTRL_DMA_RD_DIS)) {
> @@ -1469,7 +1465,6 @@ static void reset_rx_work(struct work_struct *work)
>  				   FSL_XCVR_EXT_CTRL_RX_DPTH_RESET,
>  				   0);
>  	}
> -	spin_unlock_irqrestore(&xcvr->lock, lock_flags);
>  }
>
>  static irqreturn_t irq0_isr(int irq, void *devid)
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH v2 01/11] ASoC: fsl_asrc: Use guard() for spin locks
From: Frank Li @ 2026-06-15 14:18 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-2-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:14PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for spin locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/fsl_asrc.c | 10 ++--------
>  1 file changed, 2 insertions(+), 8 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
> index 5fda9b647c70..0b28bcfa47fe 100644
> --- a/sound/soc/fsl/fsl_asrc.c
> +++ b/sound/soc/fsl/fsl_asrc.c
> @@ -222,10 +222,9 @@ static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
>  	enum asrc_pair_index index = ASRC_INVALID_PAIR;
>  	struct fsl_asrc *asrc = pair->asrc;
>  	struct device *dev = &asrc->pdev->dev;
> -	unsigned long lock_flags;
>  	int i, ret = 0;
>
> -	spin_lock_irqsave(&asrc->lock, lock_flags);
> +	guard(spinlock_irqsave)(&asrc->lock);
>
>  	for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) {
>  		if (asrc->pair[i] != NULL)
> @@ -250,8 +249,6 @@ static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
>  		pair->index = index;
>  	}
>
> -	spin_unlock_irqrestore(&asrc->lock, lock_flags);
> -
>  	return ret;
>  }
>
> @@ -265,19 +262,16 @@ static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
>  {
>  	struct fsl_asrc *asrc = pair->asrc;
>  	enum asrc_pair_index index = pair->index;
> -	unsigned long lock_flags;
>
>  	/* Make sure the pair is disabled */
>  	regmap_update_bits(asrc->regmap, REG_ASRCTR,
>  			   ASRCTR_ASRCEi_MASK(index), 0);
>
> -	spin_lock_irqsave(&asrc->lock, lock_flags);
> +	guard(spinlock_irqsave)(&asrc->lock);
>
>  	asrc->channel_avail += pair->channels;
>  	asrc->pair[index] = NULL;
>  	pair->error = 0;
> -
> -	spin_unlock_irqrestore(&asrc->lock, lock_flags);
>  }
>
>  /**
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH net-next v7 01/12] net: phylink: keep and use MAC supported_interfaces in phylink struct
From: Christian Marangi @ 2026-06-15 14:18 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan, Lorenzo Bianconi,
	Heiner Kallweit, Russell King, Saravana Kannan, Philipp Zabel,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	netdev, devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-mediatek, llvm
In-Reply-To: <371a1df7-084c-4431-bd00-0045298e3212@bootlin.com>

On Mon, Jun 15, 2026 at 03:33:34PM +0200, Maxime Chevallier wrote:
> Hello Christian,
> 
> On 6/15/26 14:29, Christian Marangi wrote:
> > Add in phylink struct a copy of supported_interfaces from phylink_config
> > and make use of that instead of relying on phylink_config value.
> > 
> > This in preparation for support of PCS handling internally to phylink
> > where a PCS can be removed or added after the phylink is created and we
> > need both a reference of the supported_interfaces value from
> > phylink_config and an internal value that can be updated with the new
> > PCS info.
> > 
> > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> > ---
> >  drivers/net/phy/phylink.c | 22 +++++++++++++++-------
> >  1 file changed, 15 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> > index 087ac63f9193..4d59c0dd78db 100644
> > --- a/drivers/net/phy/phylink.c
> > +++ b/drivers/net/phy/phylink.c
> > @@ -60,6 +60,11 @@ struct phylink {
> >  	/* The link configuration settings */
> >  	struct phylink_link_state link_config;
> >  
> > +	/* What interface are supported by the current link.
> > +	 * Can change on removal or addition of new PCS.
> > +	 */
> > +	DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
> 
> Can you clarify a bit what you mean here ? Is that the combination of the
> interfaces the MAC supports AND the currently in-use PCS ?
> 

Combination of interface the MAC supports and the currently attached PCS
(not the current one in use)

The fact that it can change is due to the fact that PCS can be attached
later and supported_interfaces can be updated accordingly.

-- 
	Ansuel


^ permalink raw reply

* Re: [PATCH v2 08/11] ASoC: imx-audio-rpmsg: Use guard() for spin locks
From: Frank Li @ 2026-06-15 14:17 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-9-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:21PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for spin locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/imx-audio-rpmsg.c | 25 ++++++++++++-------------
>  1 file changed, 12 insertions(+), 13 deletions(-)
>
> diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c
> index 38aafb8954c7..b55dfbdb4502 100644
> --- a/sound/soc/fsl/imx-audio-rpmsg.c
> +++ b/sound/soc/fsl/imx-audio-rpmsg.c
> @@ -22,7 +22,6 @@ static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
>  	struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data;
>  	struct rpmsg_info *info;
>  	struct rpmsg_msg *msg;
> -	unsigned long flags;
>
>  	if (!rpmsg->rpmsg_pdev)
>  		return 0;
> @@ -37,21 +36,21 @@ static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
>  		/* TYPE C is notification from M core */
>  		switch (r_msg->header.cmd) {
>  		case TX_PERIOD_DONE:
> -			spin_lock_irqsave(&info->lock[TX], flags);
> -			msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
> -			msg->r_msg.param.buffer_tail =
> -						r_msg->param.buffer_tail;
> -			msg->r_msg.param.buffer_tail %= info->num_period[TX];
> -			spin_unlock_irqrestore(&info->lock[TX], flags);
> +			scoped_guard(spinlock_irqsave, &info->lock[TX]) {
> +				msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
> +				msg->r_msg.param.buffer_tail =
> +							r_msg->param.buffer_tail;
> +				msg->r_msg.param.buffer_tail %= info->num_period[TX];
> +			}
>  			info->callback[TX](info->callback_param[TX]);
>  			break;
>  		case RX_PERIOD_DONE:
> -			spin_lock_irqsave(&info->lock[RX], flags);
> -			msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
> -			msg->r_msg.param.buffer_tail =
> -						r_msg->param.buffer_tail;
> -			msg->r_msg.param.buffer_tail %= info->num_period[1];
> -			spin_unlock_irqrestore(&info->lock[RX], flags);
> +			scoped_guard(spinlock_irqsave, &info->lock[RX]) {
> +				msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
> +				msg->r_msg.param.buffer_tail =
> +							r_msg->param.buffer_tail;
> +				msg->r_msg.param.buffer_tail %= info->num_period[1];
> +			}
>  			info->callback[RX](info->callback_param[RX]);
>  			break;
>  		default:
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH v2 05/11] ASoC: fsl_spdif: Use guard() for spin locks
From: Frank Li @ 2026-06-15 14:17 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-6-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:18PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for spin locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/fsl_spdif.c | 8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
> index 1b9be85b34c2..ad1206ed9882 100644
> --- a/sound/soc/fsl/fsl_spdif.c
> +++ b/sound/soc/fsl/fsl_spdif.c
> @@ -853,17 +853,15 @@ static int fsl_spdif_subcode_get(struct snd_kcontrol *kcontrol,
>  	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
>  	struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
>  	struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
> -	unsigned long flags;
>  	int ret = -EAGAIN;
>
> -	spin_lock_irqsave(&ctrl->ctl_lock, flags);
> +	guard(spinlock_irqsave)(&ctrl->ctl_lock);
>  	if (ctrl->ready_buf) {
>  		int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE;
>  		memcpy(&ucontrol->value.iec958.subcode[0],
>  				&ctrl->subcode[idx], SPDIF_UBITS_SIZE);
>  		ret = 0;
>  	}
> -	spin_unlock_irqrestore(&ctrl->ctl_lock, flags);
>
>  	return ret;
>  }
> @@ -885,17 +883,15 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol,
>  	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
>  	struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
>  	struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
> -	unsigned long flags;
>  	int ret = -EAGAIN;
>
> -	spin_lock_irqsave(&ctrl->ctl_lock, flags);
> +	guard(spinlock_irqsave)(&ctrl->ctl_lock);
>  	if (ctrl->ready_buf) {
>  		int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE;
>  		memcpy(&ucontrol->value.bytes.data[0],
>  				&ctrl->qsub[idx], SPDIF_QSUB_SIZE);
>  		ret = 0;
>  	}
> -	spin_unlock_irqrestore(&ctrl->ctl_lock, flags);
>
>  	return ret;
>  }
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH net-next v7 02/12] net: phylink: introduce internal phylink PCS handling
From: Christian Marangi @ 2026-06-15 14:17 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan, Lorenzo Bianconi,
	Heiner Kallweit, Russell King, Saravana Kannan, Philipp Zabel,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	netdev, devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-mediatek, llvm
In-Reply-To: <3bbacda3-4225-4536-a4b4-3aa31a47a3aa@bootlin.com>

On Mon, Jun 15, 2026 at 03:31:20PM +0200, Maxime Chevallier wrote:
> Hi Christian,
> 
> On 6/15/26 14:29, Christian Marangi wrote:
> > Introduce internal handling of PCS for phylink. This is an alternative
> > way to .mac_select_pcs that moves the selection logic of the PCS entirely
> > to phylink with the usage of the supported_interface value in the PCS
> > struct.
> > 
> > MAC should now provide a callback to fill the available PCS in
> > phylink_config in .fill_available_pcs and fill the .num_possible_pcs with
> > the number of elements in the array. MAC should also define a new bitmap,
> > pcs_interfaces, in phylink_config to define for what interface mode a
> > dedicated PCS is required.
> > 
> > On phylink_create(), an array of PCS pointer is allocated of size
> > .num_possible_pcs from phylink_config and .fill_available_pcs from
> > phylink_config is called passing as args the just allocated array and
> > the number of possible element in it.
> > 
> > MAC will fill this passed array with all the available PCS.
> > 
> > This array is then parsed and a linked list of PCS is created based on
> > the allocated PCS array filled by MAC via .fill_available_pcs().
> > 
> > Every PCS in phylink PCS list gets then linked to the phylink instance
> > by setting the phylink value in phylink_pcs struct to the phylink instance.
> > Also the supported_interface value in phylink struct is updated with
> > the new supported_interface from the provided PCS.
> > 
> > On phylink_destroy(), every PCS in phylink PCS list is unlinked from the
> > phylink instance by setting the phylink value in phylink_pcs struct to NULL
> > and removed from the PCS list.
> > 
> > phylink_validate_mac_and_pcs(), phylink_major_config() and
> > phylink_inband_caps() are updated to support this new implementation
> > with the PCS list stored in phylink.
> > 
> > They will make use of phylink_validate_pcs_interface() that will loop
> > for every PCS in the phylink PCS available list and find one that supports
> > the passed interface.
> > 
> > phylink_validate_pcs_interface() applies the same logic of .mac_select_pcs
> > where if a supported_interface value is not set for the PCS struct, then
> > it's assumed every interface is supported.
> > 
> > A MAC is required to implement either a .mac_select_pcs or make use of
> > the PCS list implementation. Implementing both will result in a fail
> > on phylink_create().
> > 
> > A MAC defining .num_possible_pcs in phylink_config MUST also define a
> > .fill_available_pcs or phylink_create() will fail with an negative error.
> > 
> > phylink value in phylink_pcs struct with this implementation is used to
> > track from PCS side when it's attached to a phylink instance. PCS driver
> > will make use of this information to correctly detach from a phylink
> > instance if needed.
> > 
> > phylink_pcs_change() is also changed to verify that the PCS that triggered
> > a link change is the one that is currently used by the phylink instance.
> > 
> > The .mac_select_pcs implementation is not changed but it's expected that
> > every MAC driver migrates to the new implementation to later deprecate
> > and remove .mac_select_pcs.
> > 
> > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> > ---
> 
> [...]
> 
> > @@ -1872,10 +1993,28 @@ struct phylink *phylink_create(struct phylink_config *config,
> >  	mutex_init(&pl->phydev_mutex);
> >  	mutex_init(&pl->state_mutex);
> >  	INIT_WORK(&pl->resolve, phylink_resolve);
> > +	INIT_LIST_HEAD(&pl->pcs_list);
> > +
> > +	/* Fill the PCS list with available PCS from phylink config */
> > +	ret = phylink_fill_available_pcs(pl, config);
> > +	if (ret < 0) {
> > +		kfree(pl);
> > +		return ERR_PTR(ret);
> > +	}
> > +
> > +	/* Link available PCS to phylink */
> > +	list_for_each_entry(pcs, &pl->pcs_list, list)
> > +		pcs->phylink = pl;
> >  
> >  	phy_interface_copy(pl->supported_interfaces,
> >  			   config->supported_interfaces);
> >  
> > +	/* Update supported interfaces */
> > +	list_for_each_entry(pcs, &pl->pcs_list, list)
> > +		phy_interface_or(pl->supported_interfaces,
> > +				 pl->supported_interfaces,
> > +				 pcs->supported_interfaces);
> > +
> 
> I'm not entirely sure about that, we may need to restrict the supported_interfaces
> from the MAC.
> 
> As an example, take mvpp2. We have 2 PCSs, one for BaseX/SGMII, one for BaseR. But
> if we don't have a comphy (generic PHY) device, then we can't use all the
> combination of modes our PCSs can provide :
> 
> https://elixir.bootlin.com/linux/v7.1-rc7/source/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c#L7074
> 
> These aren't external PCS IPs, but from what I understand you'd like to
> handle these the same way as purely external PCSs, right ?
> 
> I'd say the MAC driver utltimately has the knowledge of all possible interfaces.
> 
> The way I see it, it's probably safer to let the MAC give a wide range of interfaces,
> and filter that down with what the PCSs can provide (i.e. turn that or into an and,
> while handling the case where the pcs supported interfaces is empty).
> 
> What do you think ?
>

The idea is that supported_interface is a mask of every possible interface
from MAC and PCS. Then it's phylink_validate_mac_and_pcs that actually use
that mask and validates it on both MAC and PCS.

This is why the OR was used instead of AND. The idea is to have the PCS as
external standalone entry (even if they are internal to the MAC). So each
entry should have they own set of supported mask.

The previous patch and this try to address this problem where phylink is
actually clueless of what is actually supported exactly because it's has
been given MAC too much freedom of modelling limitation internally.

I feel limitation should be handled by their dedicated function with
.pcs_validate and .mac_get_caps.

Just my idea on this, if needed it's totally ok to simplify this and let
MAC entirely handle the mask. (but I feel the current idea of phylink code
was to have a generic mask in supported_interfaces and then verify MAC and
PCS in phylink_validate_mac_and_pcs())

But by thinking on it more, following your case of mvpp2, with this new
PCS:

- You need a PCS for the .get_state.
- And such PCS will have the supported interface set 1000baseX and
  2500BaseX (as that is what is actually supported in HW)

Either some magic is done in .pcs_validate to deny changing the interface
that was initially configured or this gets limited at the
supported_interface configured by the MAC.

I need to check if this might be problematic for the other driver where
this is being used on OpenWrt but maybe changing the logic to an AND might
be sensible for these kind of case.

(for the other it shouldn't change anything)

-- 
	Ansuel


^ permalink raw reply

* Re: [PATCH v2 04/11] ASoC: fsl_esai: Use guard() for spin locks
From: Frank Li @ 2026-06-15 14:15 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-5-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:17PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for spin locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/fsl_esai.c | 16 +++++-----------
>  1 file changed, 5 insertions(+), 11 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
> index cde0b0c6c1ef..4a530a6c33f0 100644
> --- a/sound/soc/fsl/fsl_esai.c
> +++ b/sound/soc/fsl/fsl_esai.c
> @@ -709,10 +709,9 @@ static void fsl_esai_hw_reset(struct work_struct *work)
>  {
>  	struct fsl_esai *esai_priv = container_of(work, struct fsl_esai, work);
>  	bool tx = true, rx = false, enabled[2];
> -	unsigned long lock_flags;
>  	u32 tfcr, rfcr;
>
> -	spin_lock_irqsave(&esai_priv->lock, lock_flags);
> +	guard(spinlock_irqsave)(&esai_priv->lock);
>  	/* Save the registers */
>  	regmap_read(esai_priv->regmap, REG_ESAI_TFCR, &tfcr);
>  	regmap_read(esai_priv->regmap, REG_ESAI_RFCR, &rfcr);
> @@ -750,8 +749,6 @@ static void fsl_esai_hw_reset(struct work_struct *work)
>  		fsl_esai_trigger_start(esai_priv, tx);
>  	if (enabled[rx])
>  		fsl_esai_trigger_start(esai_priv, rx);
> -
> -	spin_unlock_irqrestore(&esai_priv->lock, lock_flags);
>  }
>
>  static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
> @@ -759,7 +756,6 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
>  {
>  	struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
>  	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
> -	unsigned long lock_flags;
>
>  	esai_priv->channels[tx] = substream->runtime->channels;
>
> @@ -767,16 +763,14 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
>  	case SNDRV_PCM_TRIGGER_START:
>  	case SNDRV_PCM_TRIGGER_RESUME:
>  	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> -		spin_lock_irqsave(&esai_priv->lock, lock_flags);
> -		fsl_esai_trigger_start(esai_priv, tx);
> -		spin_unlock_irqrestore(&esai_priv->lock, lock_flags);
> +		scoped_guard(spinlock_irqsave, &esai_priv->lock)
> +			fsl_esai_trigger_start(esai_priv, tx);
>  		break;
>  	case SNDRV_PCM_TRIGGER_SUSPEND:
>  	case SNDRV_PCM_TRIGGER_STOP:
>  	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> -		spin_lock_irqsave(&esai_priv->lock, lock_flags);
> -		fsl_esai_trigger_stop(esai_priv, tx);
> -		spin_unlock_irqrestore(&esai_priv->lock, lock_flags);
> +		scoped_guard(spinlock_irqsave, &esai_priv->lock)
> +			fsl_esai_trigger_stop(esai_priv, tx);
>  		break;
>  	default:
>  		return -EINVAL;
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH v2 10/11] ASoC: fsl: mpc5200_dma: Use guard() for spin locks
From: Frank Li @ 2026-06-15 14:14 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-11-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:23PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for spin locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/mpc5200_dma.c | 56 ++++++++++++++++++-------------------
>  1 file changed, 28 insertions(+), 28 deletions(-)
>
> diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
> index 56e2cf2f727b..bfedb2dea0b3 100644
> --- a/sound/soc/fsl/mpc5200_dma.c
> +++ b/sound/soc/fsl/mpc5200_dma.c
> @@ -77,18 +77,20 @@ static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
>  {
>  	struct psc_dma_stream *s = _psc_dma_stream;
>
> -	spin_lock(&s->psc_dma->lock);
> -	/* For each finished period, dequeue the completed period buffer
> -	 * and enqueue a new one in it's place. */
> -	while (bcom_buffer_done(s->bcom_task)) {
> -		bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
> +	scoped_guard(spinlock, &s->psc_dma->lock) {
> +		/*
> +		 * For each finished period, dequeue the completed period buffer
> +		 * and enqueue a new one in its place
> +		 */
> +		while (bcom_buffer_done(s->bcom_task)) {
> +			bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
>
> -		s->period_current = (s->period_current+1) % s->runtime->periods;
> -		s->period_count++;
> +			s->period_current = (s->period_current+1) % s->runtime->periods;
> +			s->period_count++;
>
> -		psc_dma_bcom_enqueue_next_buffer(s);
> +			psc_dma_bcom_enqueue_next_buffer(s);
> +		}
>  	}
> -	spin_unlock(&s->psc_dma->lock);
>
>  	/* If the stream is active, then also inform the PCM middle layer
>  	 * of the period finished event. */
> @@ -116,7 +118,6 @@ static int psc_dma_trigger(struct snd_soc_component *component,
>  	struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
>  	struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
>  	u16 imr;
> -	unsigned long flags;
>  	int i;
>
>  	switch (cmd) {
> @@ -135,19 +136,18 @@ static int psc_dma_trigger(struct snd_soc_component *component,
>  		/* Fill up the bestcomm bd queue and enable DMA.
>  		 * This will begin filling the PSC's fifo.
>  		 */
> -		spin_lock_irqsave(&psc_dma->lock, flags);
> -
> -		if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
> -			bcom_gen_bd_rx_reset(s->bcom_task);
> -		else
> -			bcom_gen_bd_tx_reset(s->bcom_task);
> +		scoped_guard(spinlock_irqsave, &psc_dma->lock) {
> +			if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
> +				bcom_gen_bd_rx_reset(s->bcom_task);
> +			else
> +				bcom_gen_bd_tx_reset(s->bcom_task);
>
> -		for (i = 0; i < runtime->periods; i++)
> -			if (!bcom_queue_full(s->bcom_task))
> -				psc_dma_bcom_enqueue_next_buffer(s);
> +			for (i = 0; i < runtime->periods; i++)
> +				if (!bcom_queue_full(s->bcom_task))
> +					psc_dma_bcom_enqueue_next_buffer(s);
>
> -		bcom_enable(s->bcom_task);
> -		spin_unlock_irqrestore(&psc_dma->lock, flags);
> +			bcom_enable(s->bcom_task);
> +		}
>
>  		out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
>
> @@ -158,13 +158,13 @@ static int psc_dma_trigger(struct snd_soc_component *component,
>  			substream->pstr->stream, s->period_count);
>  		s->active = 0;
>
> -		spin_lock_irqsave(&psc_dma->lock, flags);
> -		bcom_disable(s->bcom_task);
> -		if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
> -			bcom_gen_bd_rx_reset(s->bcom_task);
> -		else
> -			bcom_gen_bd_tx_reset(s->bcom_task);
> -		spin_unlock_irqrestore(&psc_dma->lock, flags);
> +		scoped_guard(spinlock_irqsave, &psc_dma->lock) {
> +			bcom_disable(s->bcom_task);
> +			if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
> +				bcom_gen_bd_rx_reset(s->bcom_task);
> +			else
> +				bcom_gen_bd_tx_reset(s->bcom_task);
> +		}
>
>  		break;
>
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH v2 09/11] ASoC: fsl_rpmsg: Use guard() for mutex & spin locks
From: Frank Li @ 2026-06-15 14:12 UTC (permalink / raw)
  To: phucduc.bui
  Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Shengjiu Wang, Xiubo Li, Frank Li, Fabio Estevam, Nicolin Chen,
	Sascha Hauer, Pengutronix Kernel Team, linux-sound, linux-kernel,
	linux-arm-kernel, imx, linuxppc-dev
In-Reply-To: <20260615093824.115751-10-phucduc.bui@gmail.com>

On Mon, Jun 15, 2026 at 04:38:22PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
>
> Clean up the code using guard() for mutex & spin locks.
> Merely code refactoring, and no behavior change.
>
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---

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

>  sound/soc/fsl/imx-pcm-rpmsg.c | 69 +++++++++++++++--------------------
>  1 file changed, 30 insertions(+), 39 deletions(-)
>
> diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
> index 031e5272215d..7210393dfa5d 100644
> --- a/sound/soc/fsl/imx-pcm-rpmsg.c
> +++ b/sound/soc/fsl/imx-pcm-rpmsg.c
> @@ -39,10 +39,9 @@ static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
>  	struct rpmsg_device *rpdev = info->rpdev;
>  	int ret = 0;
>
> -	mutex_lock(&info->msg_lock);
> +	guard(mutex)(&info->msg_lock);
>  	if (!rpdev) {
>  		dev_err(info->dev, "rpmsg channel not ready\n");
> -		mutex_unlock(&info->msg_lock);
>  		return -EINVAL;
>  	}
>
> @@ -55,15 +54,12 @@ static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
>  			 sizeof(struct rpmsg_s_msg));
>  	if (ret) {
>  		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
> -		mutex_unlock(&info->msg_lock);
>  		return ret;
>  	}
>
>  	/* No receive msg for TYPE_C command */
> -	if (msg->s_msg.header.type == MSG_TYPE_C) {
> -		mutex_unlock(&info->msg_lock);
> +	if (msg->s_msg.header.type == MSG_TYPE_C)
>  		return 0;
> -	}
>
>  	/* wait response from rpmsg */
>  	ret = wait_for_completion_timeout(&info->cmd_complete,
> @@ -71,7 +67,6 @@ static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
>  	if (!ret) {
>  		dev_err(&rpdev->dev, "rpmsg_send cmd %d timeout!\n",
>  			msg->s_msg.header.cmd);
> -		mutex_unlock(&info->msg_lock);
>  		return -ETIMEDOUT;
>  	}
>
> @@ -100,8 +95,6 @@ static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
>  	dev_dbg(&rpdev->dev, "cmd:%d, resp %d\n", msg->s_msg.header.cmd,
>  		info->r_msg.param.resp);
>
> -	mutex_unlock(&info->msg_lock);
> -
>  	return 0;
>  }
>
> @@ -109,14 +102,13 @@ static int imx_rpmsg_insert_workqueue(struct snd_pcm_substream *substream,
>  				      struct rpmsg_msg *msg,
>  				      struct rpmsg_info *info)
>  {
> -	unsigned long flags;
>  	int ret = 0;
>
>  	/*
>  	 * Queue the work to workqueue.
>  	 * If the queue is full, drop the message.
>  	 */
> -	spin_lock_irqsave(&info->wq_lock, flags);
> +	guard(spinlock_irqsave)(&info->wq_lock);
>  	if (info->work_write_index != info->work_read_index) {
>  		int index = info->work_write_index;
>
> @@ -130,7 +122,6 @@ static int imx_rpmsg_insert_workqueue(struct snd_pcm_substream *substream,
>  		info->msg_drop_count[substream->stream]++;
>  		ret = -EPIPE;
>  	}
> -	spin_unlock_irqrestore(&info->wq_lock, flags);
>
>  	return ret;
>  }
> @@ -523,7 +514,6 @@ static int imx_rpmsg_pcm_ack(struct snd_soc_component *component,
>  	snd_pcm_sframes_t avail;
>  	struct timer_list *timer;
>  	struct rpmsg_msg *msg;
> -	unsigned long flags;
>  	int buffer_tail = 0;
>  	int written_num;
>
> @@ -553,11 +543,11 @@ static int imx_rpmsg_pcm_ack(struct snd_soc_component *component,
>  		msg->s_msg.param.buffer_tail = buffer_tail;
>
>  		/* The notification message is updated to latest */
> -		spin_lock_irqsave(&info->lock[substream->stream], flags);
> -		memcpy(&info->notify[substream->stream], msg,
> -		       sizeof(struct rpmsg_s_msg));
> -		info->notify_updated[substream->stream] = true;
> -		spin_unlock_irqrestore(&info->lock[substream->stream], flags);
> +		scoped_guard(spinlock_irqsave, &info->lock[substream->stream]) {
> +			memcpy(&info->notify[substream->stream], msg,
> +			       sizeof(struct rpmsg_s_msg));
> +			info->notify_updated[substream->stream] = true;
> +		}
>
>  		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
>  			avail = snd_pcm_playback_hw_avail(runtime);
> @@ -640,7 +630,7 @@ static void imx_rpmsg_pcm_work(struct work_struct *work)
>  	bool is_notification = false;
>  	struct rpmsg_info *info;
>  	struct rpmsg_msg msg;
> -	unsigned long flags;
> +	bool updated;
>
>  	work_of_rpmsg = container_of(work, struct work_of_rpmsg, work);
>  	info = work_of_rpmsg->info;
> @@ -651,25 +641,26 @@ static void imx_rpmsg_pcm_work(struct work_struct *work)
>  	 * enough data in M core side, need to let M core know
>  	 * data is updated immediately.
>  	 */
> -	spin_lock_irqsave(&info->lock[TX], flags);
> -	if (info->notify_updated[TX]) {
> -		memcpy(&msg, &info->notify[TX], sizeof(struct rpmsg_s_msg));
> -		info->notify_updated[TX] = false;
> -		spin_unlock_irqrestore(&info->lock[TX], flags);
> -		info->send_message(&msg, info);
> -	} else {
> -		spin_unlock_irqrestore(&info->lock[TX], flags);
> +	scoped_guard(spinlock_irqsave, &info->lock[TX]) {
> +		updated = info->notify_updated[TX];
> +		if (updated) {
> +			memcpy(&msg, &info->notify[TX], sizeof(struct rpmsg_s_msg));
> +			info->notify_updated[TX] = false;
> +		}
>  	}
> -
> -	spin_lock_irqsave(&info->lock[RX], flags);
> -	if (info->notify_updated[RX]) {
> -		memcpy(&msg, &info->notify[RX], sizeof(struct rpmsg_s_msg));
> -		info->notify_updated[RX] = false;
> -		spin_unlock_irqrestore(&info->lock[RX], flags);
> +	if (updated)
>  		info->send_message(&msg, info);
> -	} else {
> -		spin_unlock_irqrestore(&info->lock[RX], flags);
> +
> +	scoped_guard(spinlock_irqsave, &info->lock[RX]) {
> +		updated = info->notify_updated[RX];
> +		if (updated) {
> +			memcpy(&msg, &info->notify[RX], sizeof(struct rpmsg_s_msg));
> +			info->notify_updated[RX] = false;
> +		}
>  	}
> +	if (updated)
> +		info->send_message(&msg, info);
> +
>
>  	/* Skip the notification message for it has been processed above */
>  	if (work_of_rpmsg->msg.s_msg.header.type == MSG_TYPE_C &&
> @@ -681,10 +672,10 @@ static void imx_rpmsg_pcm_work(struct work_struct *work)
>  		info->send_message(&work_of_rpmsg->msg, info);
>
>  	/* update read index */
> -	spin_lock_irqsave(&info->wq_lock, flags);
> -	info->work_read_index++;
> -	info->work_read_index %= WORK_MAX_NUM;
> -	spin_unlock_irqrestore(&info->wq_lock, flags);
> +	scoped_guard(spinlock_irqsave, &info->wq_lock) {
> +		info->work_read_index++;
> +		info->work_read_index %= WORK_MAX_NUM;
> +	}
>  }
>
>  static int imx_rpmsg_pcm_probe(struct platform_device *pdev)
> --
> 2.43.0
>
>


^ permalink raw reply

* Re: [PATCH 0/2] iio: adc: Initialize completions before requesting IRQs
From: Andy Shevchenko @ 2026-06-15 14:11 UTC (permalink / raw)
  To: Maxwell Doose
  Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Vladimir Zapolskiy, Piotr Wojtaszczyk, Hartmut Knaack,
	open list:IIO SUBSYSTEM AND DRIVERS,
	moderated list:ARM/LPC32XX SOC SUPPORT, open list, Sangyun Kim,
	Kyungwook Boo, Jaeyoung Chung
In-Reply-To: <20260613005812.160572-1-m32285159@gmail.com>

On Fri, Jun 12, 2026 at 07:58:09PM -0500, Maxwell Doose wrote:
> Hi all,
> 
> This short patch series fixes the issues raised by Jaeyoung Chung,
> Sangyun Kim, and Kyungwook Boo regarding init_completion() and spurious
> IRQs. The report is linked below [1], but I will also put it here
> inline:
> 
> "lpc32xx_adc_probe() in drivers/iio/adc/lpc32xx_adc.c and
> spear_adc_probe() in drivers/iio/adc/spear_adc.c register their
> interrupt handler with devm_request_irq() before they initialize
> st->completion with init_completion(). If an interrupt arrives after
> devm_request_irq() and before init_completion(), the handler calls
> complete() on an uninitialized completion, causing a kernel panic.
> 
> The probe path, in lpc32xx_adc_probe():
> 
>     iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); /* st kzalloc-zeroed */
>     ...
>     retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
>                               LPC32XXAD_NAME, st);           /* register handler */
>     ...
>     init_completion(&st->completion);                       /* initialize completion */
> 
> spear_adc_probe() has the same ordering: devm_request_irq() for
> spear_adc_isr() before init_completion(&st->completion).
> 
> Both interrupt handlers, lpc32xx_adc_isr() and spear_adc_isr(), call
> complete():
> 
>     complete(&st->completion);
> 
> If the device raises an interrupt before init_completion() runs,
> complete() acquires the uninitialized wait.lock and walks the zeroed
> task_list in swake_up_locked(). The zeroed task_list makes list_empty()
> return false, so swake_up_locked() dereferences a NULL list entry,
> triggering a KASAN wild-memory-access.
> 
> Suggested fix: move init_completion(&st->completion) above
> devm_request_irq(), so the completion is valid before the handler can run.
> 
> Reported-by: Sangyun Kim <sangyun.kim@snu.ac.kr>
> Reported-by: Kyungwook Boo <bookyungwook@gmail.com>"

Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>

-- 
With Best Regards,
Andy Shevchenko




^ permalink raw reply

* Re: [PATCH net-next v7 05/12] net: phylink: support late PCS provider attach
From: Christian Marangi @ 2026-06-15 14:10 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan, Lorenzo Bianconi,
	Heiner Kallweit, Russell King, Saravana Kannan, Philipp Zabel,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	netdev, devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-mediatek, llvm
In-Reply-To: <867a39de-ccc2-4dcf-be24-ab2542d20ab6@bootlin.com>

On Mon, Jun 15, 2026 at 04:07:03PM +0200, Maxime Chevallier wrote:
> Hi Christian,
> 
> On 6/15/26 14:29, Christian Marangi wrote:
> > Add support for late PCS provider attachment to a phylink instance.
> > This works by creating a global notifier for the PCS provider and
> > making each phylink instance that makes use of fwnode subscribe to
> > this notifier.
> > 
> > The PCS notifier will emit the event FWNODE_PCS_PROVIDER_ADD every time
> > a new PCS provider is added.
> > 
> > phylink will then react to this event and will call the new function
> > fwnode_phylink_pcs_get_from_fwnode() that will check if the PCS fwnode
> > provided by the event is present in the pcs-handle property of the
> > phylink instance.
> > 
> > If a related PCS is found, then such PCS is added to the phylink
> > instance PCS list.
> > 
> > Then we link the PCS to the phylink instance and we refresh the supported
> > interfaces of the phylink instance.
> > 
> > Finally we check if we are in a major_config_failed scenario and trigger
> > an interface reconfiguration in the next phylink resolve.
> > 
> > In the example scenario where the link was previously torn down due to
> > removal of PCS, the link will be established again as the PCS came back
> > and is now available to phylink.
> > 
> > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> > ---
> 
> [...]
> 
> > @@ -2151,6 +2204,10 @@ void phylink_destroy(struct phylink *pl)
> >  	if (pl->link_gpio)
> >  		gpiod_put(pl->link_gpio);
> >  
> > +	/* Unregister notifier for late PCS attach */
> > +	if (pl->fwnode_pcs_nb.notifier_call)
> > +		unregister_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
> 
> I wanted to try this out, but I get :
> 
> drivers/net/phy/phylink.c:2218:17: error: implicit declaration of function ‘unregister_fwnode_pcs_notifier’; did you mean ‘register_fwnode_pcs_notifier’? [-Werror=implicit-function-declaration]
>  2218 |                 unregister_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
>       |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>       |                 register_fwnode_pcs_notifier
> 
> I guess you either need to stub this, or there's a missing Kconfig
> dependency somewhere
>

Hi yes if you want toi test just enable CONFIG_FWNODE_PCS. I forgot to add
the static declaration for unregister_fwnode_pcs_notifier. 

-- 
	Ansuel


^ permalink raw reply

* [PATCH net-next v7 01/12] net: phylink: keep and use MAC supported_interfaces in phylink struct
From: Christian Marangi @ 2026-06-15 12:29 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan, Christian Marangi,
	Lorenzo Bianconi, Heiner Kallweit, Russell King, Saravana Kannan,
	Philipp Zabel, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, netdev, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-mediatek, llvm
In-Reply-To: <20260615122950.22281-1-ansuelsmth@gmail.com>

Add in phylink struct a copy of supported_interfaces from phylink_config
and make use of that instead of relying on phylink_config value.

This in preparation for support of PCS handling internally to phylink
where a PCS can be removed or added after the phylink is created and we
need both a reference of the supported_interfaces value from
phylink_config and an internal value that can be updated with the new
PCS info.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
 drivers/net/phy/phylink.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 087ac63f9193..4d59c0dd78db 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -60,6 +60,11 @@ struct phylink {
 	/* The link configuration settings */
 	struct phylink_link_state link_config;
 
+	/* What interface are supported by the current link.
+	 * Can change on removal or addition of new PCS.
+	 */
+	DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
+
 	/* The current settings */
 	phy_interface_t cur_interface;
 
@@ -629,7 +634,7 @@ static int phylink_validate_mask(struct phylink *pl, struct phy_device *phy,
 static int phylink_validate(struct phylink *pl, unsigned long *supported,
 			    struct phylink_link_state *state)
 {
-	const unsigned long *interfaces = pl->config->supported_interfaces;
+	const unsigned long *interfaces = pl->supported_interfaces;
 
 	if (state->interface == PHY_INTERFACE_MODE_NA)
 		return phylink_validate_mask(pl, NULL, supported, state,
@@ -1868,6 +1873,9 @@ struct phylink *phylink_create(struct phylink_config *config,
 	mutex_init(&pl->state_mutex);
 	INIT_WORK(&pl->resolve, phylink_resolve);
 
+	phy_interface_copy(pl->supported_interfaces,
+			   config->supported_interfaces);
+
 	pl->config = config;
 	if (config->type == PHYLINK_NETDEV) {
 		pl->netdev = to_net_dev(config->dev);
@@ -2026,7 +2034,7 @@ static int phylink_validate_phy(struct phylink *pl, struct phy_device *phy,
 		 * those which the host supports.
 		 */
 		phy_interface_and(interfaces, phy->possible_interfaces,
-				  pl->config->supported_interfaces);
+				  pl->supported_interfaces);
 
 		if (phy_interface_empty(interfaces)) {
 			phylink_err(pl, "PHY has no common interfaces\n");
@@ -2828,12 +2836,12 @@ static phy_interface_t phylink_sfp_select_interface(struct phylink *pl,
 		return interface;
 	}
 
-	if (!test_bit(interface, pl->config->supported_interfaces)) {
+	if (!test_bit(interface, pl->supported_interfaces)) {
 		phylink_err(pl,
 			    "selection of interface failed, SFP selected %s (%u) but MAC supports %*pbl\n",
 			    phy_modes(interface), interface,
 			    (int)PHY_INTERFACE_MODE_MAX,
-			    pl->config->supported_interfaces);
+			    pl->supported_interfaces);
 		return PHY_INTERFACE_MODE_NA;
 	}
 
@@ -3761,14 +3769,14 @@ static int phylink_sfp_config_optical(struct phylink *pl)
 
 	phylink_dbg(pl, "optical SFP: interfaces=[mac=%*pbl, sfp=%*pbl]\n",
 		    (int)PHY_INTERFACE_MODE_MAX,
-		    pl->config->supported_interfaces,
+		    pl->supported_interfaces,
 		    (int)PHY_INTERFACE_MODE_MAX,
 		    pl->sfp_interfaces);
 
 	/* Find the union of the supported interfaces by the PCS/MAC and
 	 * the SFP module.
 	 */
-	phy_interface_and(pl->sfp_interfaces, pl->config->supported_interfaces,
+	phy_interface_and(pl->sfp_interfaces, pl->supported_interfaces,
 			  pl->sfp_interfaces);
 	if (phy_interface_empty(pl->sfp_interfaces)) {
 		phylink_err(pl, "unsupported SFP module: no common interface modes\n");
@@ -3939,7 +3947,7 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
 
 	/* Set the PHY's host supported interfaces */
 	phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces,
-			  pl->config->supported_interfaces);
+			  pl->supported_interfaces);
 
 	/* Do the initial configuration */
 	return phylink_sfp_config_phy(pl, phy);
-- 
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