Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v6 09/13] coresight: etm4x: missing cscfg_csdev_disable_active_config() in perf enable
From: Yeoreum Yun @ 2026-05-15 13:35 UTC (permalink / raw)
  To: Leo Yan
  Cc: coresight, linux-arm-kernel, linux-kernel, suzuki.poulose,
	mike.leach, james.clark, alexander.shishkin, jie.gan
In-Reply-To: <20260515093923.GJ34802@e132581.arm.com>

Hi Leo,

> On Wed, Apr 22, 2026 at 02:21:59PM +0100, Yeoreum Yun wrote:
> 
> [...]
> 
> > @@ -895,6 +895,8 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
> >  			 * Missing BB support could cause silent decode errors
> >  			 * so fail to open if it's not supported.
> >  			 */
> > +			if (cfg_hash)
> > +				cscfg_csdev_disable_active_config(csdev);
> 
> I prefer do a bit refactoring for this.
> 
> we just save cfg_hash and cfg_preset into drvdata in
> etm4_parse_event_config():
> 
>   drvdata->cfg_hash = ATTR_CFG_GET_FLD(attr, configid);
>   if (drvdata->cfg_hash)
>         drvdata->preset = ATTR_CFG_GET_FLD(attr, preset);
> 
> Then create two helpers:
> 
>   etm4_cscfg_enable(csdev) {
>     struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> 
>     return cscfg_csdev_enable_active_config(csdev, drvdata->cfg_hash,
>                                             drvdata->preset);
>   }
> 
>   etm4_cscfg_disable(csdev) {
>     cscfg_csdev_disable_active_config(csdev);
>   }
> 
> These helpers will be used by etm4_{enable|disable}_perf()
> and etm4_{enable|disable}_sysfs(). This might benefit the future cscfg
> refactoring.

I think this seems some over-engineering since the
etm4_cscfg_enable/disable() just an wrapper for
cscfg_csdev_enable/disable_active_config() but just increase size of drvdata.

It's not late to delay when we do refactoring the cscfg
and at that time, we can consider some place to save cfg_hash and
preset. If we do right now, personally, there seems no benefit for this.

Am I missing something?

Thanks.

[...]

-- 
Sincerely,
Yeoreum Yun


^ permalink raw reply

* [PATCH] arm64: probes: Handle probes on hinted conditional branch instructions
From: Vladimir Murzin @ 2026-05-15 13:37 UTC (permalink / raw)
  To: linux-arm-kernel

BC.cond instructions introduced by FEAT_HBC cannot be executed
out-of-line, like other branch instructions. However, they can be
simulated in the same way as B.cond instructions.

Extend the B.cond decoder mask to match BC.cond instructions as well,
and handle them using the existing B.cond simulation path.

Fixes: 7f86d128e437 ("arm64: add HWCAP for FEAT_HBC (hinted conditional branches)")
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
---
 arch/arm64/include/asm/insn.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index f463a654a2bb..cc0702fa64a7 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -409,7 +409,7 @@ __AARCH64_INSN_FUNCS(cbz,	0x7F000000, 0x34000000)
 __AARCH64_INSN_FUNCS(cbnz,	0x7F000000, 0x35000000)
 __AARCH64_INSN_FUNCS(tbz,	0x7F000000, 0x36000000)
 __AARCH64_INSN_FUNCS(tbnz,	0x7F000000, 0x37000000)
-__AARCH64_INSN_FUNCS(bcond,	0xFF000010, 0x54000000)
+__AARCH64_INSN_FUNCS(bcond,	0xFF000000, 0x54000000)
 __AARCH64_INSN_FUNCS(svc,	0xFFE0001F, 0xD4000001)
 __AARCH64_INSN_FUNCS(hvc,	0xFFE0001F, 0xD4000002)
 __AARCH64_INSN_FUNCS(smc,	0xFFE0001F, 0xD4000003)
-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH v2] soc: ti: k3-ringacc: Fix access mode for k3_ringacc_ring_pop_tail_io/proxy
From: Nishanth Menon @ 2026-05-15 13:48 UTC (permalink / raw)
  To: ssantosh, gehariprasath, Siddharth Vadapalli
  Cc: Nishanth Menon, stable, linux-kernel, linux-arm-kernel, srk
In-Reply-To: <20260501124129.362192-1-s-vadapalli@ti.com>

Hi Siddharth Vadapalli,

On Fri, 01 May 2026 18:10:54 +0530, Siddharth Vadapalli wrote:
> k3_ringacc_ring_pop_tail_io() and k3_ringacc_ring_pop_tail_proxy()
> incorrectly use K3_RINGACC_ACCESS_MODE_POP_HEAD instead of
> K3_RINGACC_ACCESS_MODE_POP_TAIL. This will result in ring elements being
> popped in the reverse order of that which the caller expects. Fix this.

I have applied the following to branch ti-drivers-soc-next on [1].

I am queuing this up for the next window as things seem functional at
this point as well and was a bug that was present for a long time, so
I dont see this introduced in the current window.

Thank you!

[1/1] soc: ti: k3-ringacc: Fix access mode for k3_ringacc_ring_pop_tail_io/proxy
      commit: b920352cfd2b0fcd1249ff006618c939b64fc8f7

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
-- 
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3  1A34 DDB5 849D 1736 249D
https://ti.com/opensource



^ permalink raw reply

* Re: [PATCH v2] soc: ti: knav_qmss_queue: Implement resource cleanup in remove()
From: Nishanth Menon @ 2026-05-15 13:48 UTC (permalink / raw)
  To: ssantosh, linux-arm-kernel, linux-kernel, Md Shofiqul Islam
  Cc: Nishanth Menon
In-Reply-To: <20260506154114.2288-1-shofiqtest@gmail.com>

Hi Md Shofiqul Islam,

On Wed, 06 May 2026 18:41:14 +0300, Md Shofiqul Islam wrote:
> Implement the TODO in knav_queue_remove() by stopping PDSPs and
> freeing queue regions and queue ranges before disabling runtime PM,
> mirroring the cleanup performed in the probe error path.
> 
> Set device_ready to false before cleanup to prevent any further
> use of the device during teardown.
> 
> [...]

I have applied the following to branch ti-drivers-soc-next on [1].

Thank you!

[1/1] soc: ti: knav_qmss_queue: Implement resource cleanup in remove()
      commit: 10a1969353b20caa50c320717e054601631c0d3e

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
-- 
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3  1A34 DDB5 849D 1736 249D
https://ti.com/opensource



^ permalink raw reply

* Re: [PATCH v1] arm64: dts: ti: k3-am62-verdin: Add DSI to HDMI adapter overlay
From: Nishanth Menon @ 2026-05-15 13:49 UTC (permalink / raw)
  To: Vignesh Raghavendra, Tero Kristo, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Francesco Dolcini,
	Vitor Soares
  Cc: Nishanth Menon, Vitor Soares, linux-arm-kernel, devicetree,
	linux-kernel
In-Reply-To: <20260506143427.348806-2-ivitro@gmail.com>

Hi Vitor Soares,

On Wed, 06 May 2026 15:34:26 +0100, Vitor Soares wrote:
> Add a device-tree overlay for the Toradex DSI to HDMI Adapter, an
> accessory that connects to the Verdin DSI_1 interface and provides a
> full-size HDMI Type-A output. The adapter is based on the Lontium
> LT8912B DSI-to-HDMI bridge.
> 
> The overlay is also combined with the Verdin AM62 carrier board device
> trees to provide ready-to-use DTBs for the Dahlia and Development Board
> carriers, in both WiFi and non-WiFi SoM variants.
> 
> [...]

I have applied the following to branch ti-k3-dts-next on [1].
Thank you!

[1/1] arm64: dts: ti: k3-am62-verdin: Add DSI to HDMI adapter overlay
      commit: 48f1f6f480741f014f3774096236fff91cdcc297

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
-- 
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3  1A34 DDB5 849D 1736 249D
https://ti.com/opensource



^ permalink raw reply

* Re: [PATCH 2/3] iommu/io-pgtable-arm: Rework to use the iommu-pages API
From: Jason Gunthorpe @ 2026-05-15 13:54 UTC (permalink / raw)
  To: Mostafa Saleh
  Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, will, joro
In-Reply-To: <20260513215203.3852661-3-smostafa@google.com>

On Wed, May 13, 2026 at 09:52:02PM +0000, Mostafa Saleh wrote:
> Update the io-pgtable-arm allocator to use the iommu-pages API.
> 
> Replace the DMA API usage from __arm_lpae_alloc_pages() with
> iommu_pages_start_incoherent() and from __arm_lpae_free_pages() with
> iommu_pages_free_incoherent().
> 
> Since the iommu-pages API relies on metadata stored in the struct page
> during iommu_alloc_pages_node_sz(), it cannot be used safely with memory
> allocated via the custom cfg->alloc (which may not be backed by pages).
> So, isolate that logic and keep it as it.
> 
> Suggested-by: Jason Gunthorpe <jgg@ziepe.ca>
> Signed-off-by: Mostafa Saleh <smostafa@google.com>
> ---
>  drivers/iommu/io-pgtable-arm.c | 79 ++++++++++++++++++++++++----------
>  1 file changed, 56 insertions(+), 23 deletions(-)

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>

I feel the setup for incoherent walk for panthor is kind of sketchy,
if you select incoherent walk and pass in a random GPU driver struct
device there are alot of assumptions suddenly to know the dma API is
doing the right thing..

Jason


^ permalink raw reply

* Re: [PATCH] arm64: mm: use u32 for FDT size in fixmap_remap_fdt()
From: Sang-Heon Jeon @ 2026-05-15 13:55 UTC (permalink / raw)
  To: catalin.marinas, will; +Cc: linux-arm-kernel
In-Reply-To: <20260514171304.2034930-1-ekffu200098@gmail.com>

On Fri, May 15, 2026 at 2:13 AM Sang-Heon Jeon <ekffu200098@gmail.com> wrote:
>
> fixmap_remap_fdt() uses a signed int for the FDT size, so a malformed
> totalsize bigger than INT_MAX wrongly passes the MAX_FDT_SIZE check.
> Then create_mapping_noalloc() is called with a huge size and triggers
> a BUG_ON() in the MMU code, with no diagnostic about the malformed FDT.
>
> Change the FDT size from int to u32, which is the return type of
> fdt_totalsize(). So a malformed totalsize no longer wrongly passes the
> MAX_FDT_SIZE check, and setup_machine_fdt() prints a pr_crit
> diagnostic for it, not a BUG_ON in the MMU code.
>
> Fixes: 61bd93ce801b ("arm64: use fixmap region for permanent FDT mapping")
> Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
> ---
>  arch/arm64/include/asm/mmu.h | 2 +-
>  arch/arm64/kernel/setup.c    | 4 ++--
>  arch/arm64/mm/fixmap.c       | 4 ++--
>  3 files changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
> index 5e1211c540ab..a6b388ef4c3f 100644
> --- a/arch/arm64/include/asm/mmu.h
> +++ b/arch/arm64/include/asm/mmu.h
> @@ -68,7 +68,7 @@ extern void create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
>  extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
>                                unsigned long virt, phys_addr_t size,
>                                pgprot_t prot, bool page_mappings_only);
> -extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot);
> +extern void *fixmap_remap_fdt(phys_addr_t dt_phys, u32 *size, pgprot_t prot);
>  extern void mark_linear_text_alias_ro(void);
>  extern int split_kernel_leaf_mapping(unsigned long start, unsigned long end);
>  extern void linear_map_maybe_split_to_ptes(void);
> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
> index 23c05dc7a8f2..7cabac0546dc 100644
> --- a/arch/arm64/kernel/setup.c
> +++ b/arch/arm64/kernel/setup.c
> @@ -169,7 +169,7 @@ static void __init smp_build_mpidr_hash(void)
>
>  static void __init setup_machine_fdt(phys_addr_t dt_phys)
>  {
> -       int size = 0;
> +       u32 size = 0;
>         void *dt_virt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL);
>         const char *name;
>
> @@ -182,7 +182,7 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
>          */
>         if (!early_init_dt_scan(dt_virt, dt_phys)) {
>                 pr_crit("\n"
> -                       "Error: invalid device tree blob: PA=%pa, VA=%px, size=%d bytes\n"
> +                       "Error: invalid device tree blob: PA=%pa, VA=%px, size=%u bytes\n"
>                         "The dtb must be 8-byte aligned and must not exceed 2 MB in size.\n"
>                         "\nPlease check your bootloader.\n",
>                         &dt_phys, dt_virt, size);
> diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c
> index c5c5425791da..c692e6ac2405 100644
> --- a/arch/arm64/mm/fixmap.c
> +++ b/arch/arm64/mm/fixmap.c
> @@ -134,11 +134,11 @@ void __set_fixmap(enum fixed_addresses idx,
>         }
>  }
>
> -void *__init fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> +void *__init fixmap_remap_fdt(phys_addr_t dt_phys, u32 *size, pgprot_t prot)
>  {
>         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
>         phys_addr_t dt_phys_base;
> -       int offset;
> +       u32 offset;

Also sashiko found another issue with malformed total size. And I
think that can be resolved by the following changes.

        *size = fdt_totalsize(dt_virt);
  +     if (*size < sizeof(struct fdt_header))
  +             return NULL;

Before sending a separate patch about malformed totalsize. First, I'd
rather check reviewers' opinions.

1. Do we need to care about malformed totalsize? (including addressed
by the current patch)
2. Does the above change need to be merged with the current patch or not?

Looking forward to your feedback.

Best Regards,
Sang-Heon Jeon

>         void *dt_virt;
>
>         /*
> --
> 2.43.0
>


^ permalink raw reply

* Re: [PATCH] arm64: mm: use u32 for FDT size in fixmap_remap_fdt()
From: Sang-Heon Jeon @ 2026-05-15 13:59 UTC (permalink / raw)
  To: catalin.marinas, will; +Cc: linux-arm-kernel
In-Reply-To: <CABFDxMHngr+cyjZdiJTZATh2D5jC=qO+92B1VVrr0w9TNtx6nw@mail.gmail.com>

On Fri, May 15, 2026 at 10:55 PM Sang-Heon Jeon <ekffu200098@gmail.com> wrote:
>
> On Fri, May 15, 2026 at 2:13 AM Sang-Heon Jeon <ekffu200098@gmail.com> wrote:
> >
> > fixmap_remap_fdt() uses a signed int for the FDT size, so a malformed
> > totalsize bigger than INT_MAX wrongly passes the MAX_FDT_SIZE check.
> > Then create_mapping_noalloc() is called with a huge size and triggers
> > a BUG_ON() in the MMU code, with no diagnostic about the malformed FDT.
> >
> > Change the FDT size from int to u32, which is the return type of
> > fdt_totalsize(). So a malformed totalsize no longer wrongly passes the
> > MAX_FDT_SIZE check, and setup_machine_fdt() prints a pr_crit
> > diagnostic for it, not a BUG_ON in the MMU code.
> >
> > Fixes: 61bd93ce801b ("arm64: use fixmap region for permanent FDT mapping")
> > Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
> > ---
> >  arch/arm64/include/asm/mmu.h | 2 +-
> >  arch/arm64/kernel/setup.c    | 4 ++--
> >  arch/arm64/mm/fixmap.c       | 4 ++--
> >  3 files changed, 5 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
> > index 5e1211c540ab..a6b388ef4c3f 100644
> > --- a/arch/arm64/include/asm/mmu.h
> > +++ b/arch/arm64/include/asm/mmu.h
> > @@ -68,7 +68,7 @@ extern void create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
> >  extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
> >                                unsigned long virt, phys_addr_t size,
> >                                pgprot_t prot, bool page_mappings_only);
> > -extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot);
> > +extern void *fixmap_remap_fdt(phys_addr_t dt_phys, u32 *size, pgprot_t prot);
> >  extern void mark_linear_text_alias_ro(void);
> >  extern int split_kernel_leaf_mapping(unsigned long start, unsigned long end);
> >  extern void linear_map_maybe_split_to_ptes(void);
> > diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
> > index 23c05dc7a8f2..7cabac0546dc 100644
> > --- a/arch/arm64/kernel/setup.c
> > +++ b/arch/arm64/kernel/setup.c
> > @@ -169,7 +169,7 @@ static void __init smp_build_mpidr_hash(void)
> >
> >  static void __init setup_machine_fdt(phys_addr_t dt_phys)
> >  {
> > -       int size = 0;
> > +       u32 size = 0;
> >         void *dt_virt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL);
> >         const char *name;
> >
> > @@ -182,7 +182,7 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
> >          */
> >         if (!early_init_dt_scan(dt_virt, dt_phys)) {
> >                 pr_crit("\n"
> > -                       "Error: invalid device tree blob: PA=%pa, VA=%px, size=%d bytes\n"
> > +                       "Error: invalid device tree blob: PA=%pa, VA=%px, size=%u bytes\n"
> >                         "The dtb must be 8-byte aligned and must not exceed 2 MB in size.\n"
> >                         "\nPlease check your bootloader.\n",
> >                         &dt_phys, dt_virt, size);
> > diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c
> > index c5c5425791da..c692e6ac2405 100644
> > --- a/arch/arm64/mm/fixmap.c
> > +++ b/arch/arm64/mm/fixmap.c
> > @@ -134,11 +134,11 @@ void __set_fixmap(enum fixed_addresses idx,
> >         }
> >  }
> >
> > -void *__init fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
> > +void *__init fixmap_remap_fdt(phys_addr_t dt_phys, u32 *size, pgprot_t prot)
> >  {
> >         const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
> >         phys_addr_t dt_phys_base;
> > -       int offset;
> > +       u32 offset;
>
> Also sashiko found another issue with malformed total size. And I
> think that can be resolved by the following changes.

Add missing sashiko review link :
https://sashiko.dev/#/patchset/20260514171304.2034930-1-ekffu200098%40gmail.com

>         *size = fdt_totalsize(dt_virt);
>   +     if (*size < sizeof(struct fdt_header))
>   +             return NULL;
>
> Before sending a separate patch about malformed totalsize. First, I'd
> rather check reviewers' opinions.
>
> 1. Do we need to care about malformed totalsize? (including addressed
> by the current patch)
> 2. Does the above change need to be merged with the current patch or not?
>
> Looking forward to your feedback.
>
> Best Regards,
> Sang-Heon Jeon
>
> >         void *dt_virt;
> >
> >         /*
> > --
> > 2.43.0
> >


^ permalink raw reply

* Re: [PATCH v2 1/1] arm64: dts: imx8mq-evk: Enable MIPI CSI and dual OV5640 cameras
From: Frank Li @ 2026-05-15 14:01 UTC (permalink / raw)
  To: Robby Cai
  Cc: robh, krzk+dt, conor+dt, s.hauer, festevam,
	sebastian.krzyszkowiak, kernel, devicetree, imx, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260515111143.2980956-1-robby.cai@nxp.com>

On Fri, May 15, 2026 at 07:11:43PM +0800, Robby Cai wrote:
> Enable the MIPI CSI bridges and corresponding CSI-2 host interfaces
> on the i.MX8MQ EVK, and add two OV5640 camera sensors.
>
> The sensors are connected via I2C1 and I2C2, each with proper
> endpoint descriptions to form complete media pipelines.
>
> The resulting pipelines are:
>
>   - OV5640 (I2C2) -> MIPI CSI1 -> CSI1 bridge
>   - OV5640 (I2C1) -> MIPI CSI2 -> CSI2 bridge
>
> Both pipelines have been validated on the i.MX8MQ EVK using the
> upstream OV5640 driver.
>
> Both OV5640 sensors share a single reset GPIO on this board,
> which prevents independent hardware reset when both cameras
> are enabled. As a result, the reset line is kept deasserted
> via a GPIO hog, and sensor reset is performed via software.

Does reset_control_get_shared() resolve this problem?

Frank


^ permalink raw reply

* [PATCH v3 0/3] x86,fs/resctrl,arm_mpam: Factor MBA parse-time conversion to be per-arch
From: Ben Horgan @ 2026-05-15 14:06 UTC (permalink / raw)
  To: ben.horgan
  Cc: james.morse, reinette.chatre, fenghuay, linux-kernel,
	linux-arm-kernel, tglx, mingo, bp, dave.hansen, hpa, corbet, x86,
	linux-doc, dave.martin

This is a new version of Dave Martin's patch [1] to delegate rounding of
bandwidth control user values to the arch code. As there is now more than one
architecture using resctrl, I split the original patch into two, a core resctrl
patch and an x86 patch, and added an MPAM patch. Please let me know if the patch
break down and ordering is sensible and whether the pattern should be followed
for any future similar changes.

This does have a user visible effect on MB schema when using MPAM hardware
with 'bandwidth_gran' greater than 1. I'm not sure if MPAM hardware with such
coarse controls exists in the wild but it is spec compliant and I've tested it
on a model.

[1] https://lore.kernel.org/lkml/20251031154225.14799-1-Dave.Martin@arm.com/

Ben Horgan (2):
  x86/resctrl: Add resctrl_arch_preconvert_bw()
  arm_mpam: resctrl: Add pass-through resctrl_arch_preconvert_bw()

Dave Martin (1):
  fs/resctrl: Factor MBA parse-time conversion to be per-arch

 Documentation/filesystems/resctrl.rst     | 17 +++++++++--------
 arch/x86/kernel/cpu/resctrl/ctrlmondata.c |  6 ++++++
 drivers/resctrl/mpam_resctrl.c            |  5 +++++
 fs/resctrl/ctrlmondata.c                  |  6 +++---
 include/linux/resctrl.h                   | 19 +++++++++++++++++++
 5 files changed, 42 insertions(+), 11 deletions(-)

-- 
2.43.0



^ permalink raw reply

* [PATCH v3 1/3] x86/resctrl: Add resctrl_arch_preconvert_bw()
From: Ben Horgan @ 2026-05-15 14:06 UTC (permalink / raw)
  To: ben.horgan
  Cc: james.morse, reinette.chatre, fenghuay, linux-kernel,
	linux-arm-kernel, tglx, mingo, bp, dave.hansen, hpa, corbet, x86,
	linux-doc, dave.martin
In-Reply-To: <20260515140612.1205251-1-ben.horgan@arm.com>

On MPAM systems the rounding behaviour of the MBA control would be improved
if the rounding in the fs/resctrl code is removed but this is not the
case for x86. To allow any rounding or conversion of the bandwidth value
provided by the user to be specified by the arch code a new arch hook is
required.

Introduce resctrl_arch_preconvert_bw(), and add its x86 implementation.
This is currently unused in resctrl but when plumbed in it will replace the
call to roundup() in bw_validate().

Signed-off-by: Dave Martin <dave.martin@arm.com>
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
---
Changes since Dave's v2:
Split from larger patch and add commit message
Update kernel-doc (Reinette)
---
 arch/x86/kernel/cpu/resctrl/ctrlmondata.c |  6 ++++++
 include/linux/resctrl.h                   | 19 +++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index b20e705606b8..19ae596f6b30 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -16,9 +16,15 @@
 #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
 
 #include <linux/cpu.h>
+#include <linux/math.h>
 
 #include "internal.h"
 
+u32 resctrl_arch_preconvert_bw(u32 val, const struct rdt_resource *r)
+{
+	return roundup(val, (unsigned long)r->membw.bw_gran);
+}
+
 int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
 			    u32 closid, enum resctrl_conf_type t, u32 cfg_val)
 {
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 006e57fd7ca5..33a6742da4f9 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -500,6 +500,25 @@ bool resctrl_arch_mbm_cntr_assign_enabled(struct rdt_resource *r);
  */
 int resctrl_arch_mbm_cntr_assign_set(struct rdt_resource *r, bool enable);
 
+/**
+ * resctrl_arch_preconvert_bw() - Prepare bandwidth control value for arch use.
+ * @val:	Bandwidth control value written to the schemata file by userspace.
+ * @r:		Resource whose schema was written.
+ *
+ * Convert the user provided bandwidth control value to an appropriate form for
+ * consumption by the hardware driver for resource @r. Converted value is stored
+ * in rdt_ctrl_domain::staged_config[] for later consumption by
+ * resctrl_arch_update_domains(). Is not called when MBA software controller is
+ * enabled.
+ *
+ * Architectures for which this pre-conversion hook is not useful should supply
+ * an implementation of this function that just returns val unmodified.
+ *
+ * Return:
+ * The converted value.
+ */
+u32 resctrl_arch_preconvert_bw(u32 val, const struct rdt_resource *r);
+
 /*
  * Update the ctrl_val and apply this config right now.
  * Must be called on one of the domain's CPUs.
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 2/3] arm_mpam: resctrl: Add pass-through resctrl_arch_preconvert_bw()
From: Ben Horgan @ 2026-05-15 14:06 UTC (permalink / raw)
  To: ben.horgan
  Cc: james.morse, reinette.chatre, fenghuay, linux-kernel,
	linux-arm-kernel, tglx, mingo, bp, dave.hansen, hpa, corbet, x86,
	linux-doc, dave.martin
In-Reply-To: <20260515140612.1205251-1-ben.horgan@arm.com>

resctrl rounds up the percentage value of the MBA based on the bw_gran. As
MPAM uses a binary fixed point fraction format for MBA rather than a
decimal percentage, this introduces rounding errors.

Without this additional rounding, if the user reads the value in an MB
schema and then writes it back to the schema, the value in hardware won't
change. However, with this additional rounding, this guarantee is broken
for systems with mbw_wd < 7.

resctrl is introducing resctrl_arch_preconvert_bw() to allow the arch code
to specify the conversion resctrl does to the user-provided bandwidth
value. Add the MPAM version of resctrl_arch_preconvert_bw(). This does no
conversion.

Signed-off-by: Ben Horgan <ben.horgan@arm.com>
---
 drivers/resctrl/mpam_resctrl.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index 226ff6f532fa..5a2104af22cc 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -167,6 +167,11 @@ bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level rid)
 	return mpam_resctrl_controls[rid].cdp_enabled;
 }
 
+u32 resctrl_arch_preconvert_bw(u32 val, const struct rdt_resource *r)
+{
+	return val;
+}
+
 /**
  * resctrl_reset_task_closids() - Reset the PARTID/PMG values for all tasks.
  *
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 3/3] fs/resctrl: Factor MBA parse-time conversion to be per-arch
From: Ben Horgan @ 2026-05-15 14:06 UTC (permalink / raw)
  To: ben.horgan
  Cc: james.morse, reinette.chatre, fenghuay, linux-kernel,
	linux-arm-kernel, tglx, mingo, bp, dave.hansen, hpa, corbet, x86,
	linux-doc, dave.martin, Dave Martin, Ben Horgan
In-Reply-To: <20260515140612.1205251-1-ben.horgan@arm.com>

From: Dave Martin <Dave.Martin@arm.com>

The control value parser for the MB resource currently coerces the
memory bandwidth percentage value from userspace to be an exact
multiple of the rdt_resource::resctrl_membw::bw_gran parameter.

On MPAM systems, this results in somewhat worse-than-worst-case
rounding, since the bandwidth granularity advertised to resctrl by the
MPAM driver is in general only an approximation to the actual hardware
granularity on these systems, and the hardware bandwidth allocation
control value is not natively a percentage -- necessitating a further
conversion in the resctrl_arch_update_domains() path, regardless of the
conversion done at parse time.

For MPAM and x86 use their custom pre-prepared parse-time conversion,
resctrl_arch_preconvert_bw(). This will avoid accumulated error
from rounding the value twice on MPAM systems. For x86 systems there
is no functional change.

Clarify the documentation, but avoid overly exact promises.

Clamping to bw_min and bw_max still feels generic: leave it in the core
code, for now.

[ BH: Split out x86 specific changes ]
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Signed-off-by: Ben Horgan <Ben.Horgan@arm.com>
Reviewed-by: Ben Horgan <ben.horgan@arm.com>
---
 Documentation/filesystems/resctrl.rst | 17 +++++++++--------
 fs/resctrl/ctrlmondata.c              |  6 +++---
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/Documentation/filesystems/resctrl.rst b/Documentation/filesystems/resctrl.rst
index b003bed339fd..4322d8025453 100644
--- a/Documentation/filesystems/resctrl.rst
+++ b/Documentation/filesystems/resctrl.rst
@@ -236,12 +236,11 @@ with respect to allocation:
 		user can request.
 
 "bandwidth_gran":
-		The granularity in which the memory bandwidth
-		percentage is allocated. The allocated
-		b/w percentage is rounded off to the next
-		control step available on the hardware. The
-		available bandwidth control steps are:
-		min_bandwidth + N * bandwidth_gran.
+		The approximate granularity in which the memory bandwidth
+		percentage is allocated. The allocated bandwidth percentage
+		is rounded up to the next control step available on the
+		hardware. The available hardware steps are no larger than
+		this value.
 
 "delay_linear":
 		Indicates if the delay scale is linear or
@@ -871,8 +870,10 @@ The minimum bandwidth percentage value for each cpu model is predefined
 and can be looked up through "info/MB/min_bandwidth". The bandwidth
 granularity that is allocated is also dependent on the cpu model and can
 be looked up at "info/MB/bandwidth_gran". The available bandwidth
-control steps are: min_bw + N * bw_gran. Intermediate values are rounded
-to the next control step available on the hardware.
+control steps are, approximately, min_bw + N * bw_gran.  The steps may
+appear irregular due to rounding to an exact percentage: bw_gran is the
+maximum interval between the percentage values corresponding to any two
+adjacent steps in the hardware.
 
 The bandwidth throttling is a core specific mechanism on some of Intel
 SKUs. Using a high bandwidth and a low bandwidth setting on two threads
diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c
index 9a7dfc48cb2e..934e12f5d145 100644
--- a/fs/resctrl/ctrlmondata.c
+++ b/fs/resctrl/ctrlmondata.c
@@ -37,8 +37,8 @@ typedef int (ctrlval_parser_t)(struct rdt_parse_data *data,
 /*
  * Check whether MBA bandwidth percentage value is correct. The value is
  * checked against the minimum and max bandwidth values specified by the
- * hardware. The allocated bandwidth percentage is rounded to the next
- * control step available on the hardware.
+ * hardware. The allocated bandwidth percentage is converted as
+ * appropriate for consumption by the specific hardware driver.
  */
 static bool bw_validate(char *buf, u32 *data, struct rdt_resource *r)
 {
@@ -71,7 +71,7 @@ static bool bw_validate(char *buf, u32 *data, struct rdt_resource *r)
 		return false;
 	}
 
-	*data = roundup(bw, (unsigned long)r->membw.bw_gran);
+	*data = resctrl_arch_preconvert_bw(bw, r);
 	return true;
 }
 
-- 
2.43.0



^ permalink raw reply related

* [PATCH 3/5] powerpc/pci: Use official API to iterate over PCI buses
From: Gerd Bayer @ 2026-05-15 14:22 UTC (permalink / raw)
  To: Richard Henderson, Matt Turner, Magnus Lindholm, Russell King,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Bjorn Helgaas, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin
  Cc: Yinghai Lu, linux-alpha, linux-kernel, linux-arm-kernel,
	linuxppc-dev, linux-pci, Gerd Bayer
In-Reply-To: <20260515-priv_root_buses-v1-0-f8e393c57390@linux.ibm.com>

Replace iterating over pci_root_buses with the official
pci_find_next_bus() call provided by PCI core. This allows to make
pci_root_buses private to PCI core.

Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
 arch/powerpc/kernel/pci-common.c | 7 ++++---
 arch/powerpc/kernel/pci_64.c     | 4 ++--
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 8efe95a0c4ff..1e0be7bcaa56 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1417,10 +1417,10 @@ static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus)
 
 void __init pcibios_resource_survey(void)
 {
-	struct pci_bus *b;
+	struct pci_bus *b = NULL;
 
 	/* Allocate and assign resources */
-	list_for_each_entry(b, &pci_root_buses, node)
+	while ((b = pci_find_next_bus(b)) != NULL)
 		pcibios_allocate_bus_resources(b);
 	if (!pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
 		pcibios_allocate_resources(0);
@@ -1432,7 +1432,8 @@ void __init pcibios_resource_survey(void)
 	 * bus available resources to avoid allocating things on top of them
 	 */
 	if (!pci_has_flag(PCI_PROBE_ONLY)) {
-		list_for_each_entry(b, &pci_root_buses, node)
+		b = NULL; /* Start all over */
+		while ((b = pci_find_next_bus(b)) != NULL)
 			pcibios_reserve_legacy_regions(b);
 	}
 
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index e27342ef128b..f816d063b984 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -227,7 +227,7 @@ SYSCALL_DEFINE3(pciconfig_iobase, long, which, unsigned long, in_bus,
 			  unsigned long, in_devfn)
 {
 	struct pci_controller* hose;
-	struct pci_bus *tmp_bus, *bus = NULL;
+	struct pci_bus *tmp_bus = NULL, *bus = NULL;
 	struct device_node *hose_node;
 
 	/* Argh ! Please forgive me for that hack, but that's the
@@ -248,7 +248,7 @@ SYSCALL_DEFINE3(pciconfig_iobase, long, which, unsigned long, in_bus,
 	 * used on pre-domains setup. We return the first match
 	 */
 
-	list_for_each_entry(tmp_bus, &pci_root_buses, node) {
+	while ((tmp_bus = pci_find_next_bus(tmp_bus)) != NULL) {
 		if (in_bus >= tmp_bus->number &&
 		    in_bus <= tmp_bus->busn_res.end) {
 			bus = tmp_bus;

-- 
2.54.0



^ permalink raw reply related

* [PATCH 4/5] x86/pci: Use official API to iterate over PCI buses
From: Gerd Bayer @ 2026-05-15 14:22 UTC (permalink / raw)
  To: Richard Henderson, Matt Turner, Magnus Lindholm, Russell King,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Bjorn Helgaas, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin
  Cc: Yinghai Lu, linux-alpha, linux-kernel, linux-arm-kernel,
	linuxppc-dev, linux-pci, Gerd Bayer
In-Reply-To: <20260515-priv_root_buses-v1-0-f8e393c57390@linux.ibm.com>

Replace iterating over pci_root_buses with the official
pci_find_next_bus() call provided by PCI core. This allows to make
pci_root_buses private to PCI core.

Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
 arch/x86/pci/i386.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index e2de26b82940..194d0fa3cec8 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -357,10 +357,10 @@ static void pcibios_allocate_rom_resources(struct pci_bus *bus)
 
 static int __init pcibios_assign_resources(void)
 {
-	struct pci_bus *bus;
+	struct pci_bus *bus = NULL;
 
 	if (!(pci_probe & PCI_ASSIGN_ROMS))
-		list_for_each_entry(bus, &pci_root_buses, node)
+		while ((bus = pci_find_next_bus(bus)) != NULL)
 			pcibios_allocate_rom_resources(bus);
 
 	pci_assign_unassigned_resources();
@@ -390,16 +390,18 @@ void pcibios_resource_survey_bus(struct pci_bus *bus)
 
 void __init pcibios_resource_survey(void)
 {
-	struct pci_bus *bus;
+	struct pci_bus *bus = NULL;
 
 	DBG("PCI: Allocating resources\n");
 
-	list_for_each_entry(bus, &pci_root_buses, node)
+	while ((bus = pci_find_next_bus(bus)) != NULL)
 		pcibios_allocate_bus_resources(bus);
 
-	list_for_each_entry(bus, &pci_root_buses, node)
+	bus = NULL; /* start all over */
+	while ((bus = pci_find_next_bus(bus)) != NULL)
 		pcibios_allocate_resources(bus, 0);
-	list_for_each_entry(bus, &pci_root_buses, node)
+	bus = NULL; /* start all over */
+	while ((bus = pci_find_next_bus(bus)) != NULL)
 		pcibios_allocate_resources(bus, 1);
 
 	e820__reserve_resources_late();

-- 
2.54.0



^ permalink raw reply related

* [PATCH 2/5] arm/pci: Use official API to iterate over PCI buses
From: Gerd Bayer @ 2026-05-15 14:22 UTC (permalink / raw)
  To: Richard Henderson, Matt Turner, Magnus Lindholm, Russell King,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Bjorn Helgaas, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin
  Cc: Yinghai Lu, linux-alpha, linux-kernel, linux-arm-kernel,
	linuxppc-dev, linux-pci, Gerd Bayer
In-Reply-To: <20260515-priv_root_buses-v1-0-f8e393c57390@linux.ibm.com>

Replace iterating over pci_root_buses with the official
pci_find_next_bus() call provided by PCI core. This allows to make
pci_root_buses private to PCI core.

Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
 arch/arm/kernel/bios32.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index ac0e890510da..35642c9ba054 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -59,9 +59,9 @@ static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, in
 
 void pcibios_report_status(u_int status_mask, int warn)
 {
-	struct pci_bus *bus;
+	struct pci_bus *bus = NULL;
 
-	list_for_each_entry(bus, &pci_root_buses, node)
+	while ((bus = pci_find_next_bus(bus)) != NULL)
 		pcibios_bus_report_status(bus, status_mask, warn);
 }
 

-- 
2.54.0



^ permalink raw reply related

* [PATCH 1/5] alpha/pci: Use official API to iterate over PCI buses
From: Gerd Bayer @ 2026-05-15 14:22 UTC (permalink / raw)
  To: Richard Henderson, Matt Turner, Magnus Lindholm, Russell King,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Bjorn Helgaas, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin
  Cc: Yinghai Lu, linux-alpha, linux-kernel, linux-arm-kernel,
	linuxppc-dev, linux-pci, Gerd Bayer
In-Reply-To: <20260515-priv_root_buses-v1-0-f8e393c57390@linux.ibm.com>

Replace iterating over pci_root_buses with the official
pci_find_next_bus() call provided by PCI core. This allows to make
pci_root_buses private to PCI core.

Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
 arch/alpha/kernel/pci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 11df411b1d18..02ec4dbb3ac6 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -312,9 +312,9 @@ pcibios_claim_one_bus(struct pci_bus *b)
 static void __init
 pcibios_claim_console_setup(void)
 {
-	struct pci_bus *b;
+	struct pci_bus *b = NULL;
 
-	list_for_each_entry(b, &pci_root_buses, node)
+	while ((b = pci_find_next_bus(b)) != NULL)
 		pcibios_claim_one_bus(b);
 }
 

-- 
2.54.0



^ permalink raw reply related

* [PATCH 0/5] PCI: Finally make pci_root_buses private
From: Gerd Bayer @ 2026-05-15 14:22 UTC (permalink / raw)
  To: Richard Henderson, Matt Turner, Magnus Lindholm, Russell King,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Bjorn Helgaas, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin
  Cc: Yinghai Lu, linux-alpha, linux-kernel, linux-arm-kernel,
	linuxppc-dev, linux-pci, Gerd Bayer

Hi all!

The ominous warning about pci_root_buses in drivers/pci/probe.c caught
my attention. Looking closer, I found that there are uses in four
arch-specific files left before we can stop exposing that symbol outside
of drivers/pci.

Finish off the job that Yinghai Lu started in 2013 - see
https://msgid.link/1359265003-16166-23-git-send-email-yinghai@kernel.org/

The entire series has been compile-tested only - with defconfigs on
alpha, arm, powerpc, and x86.

Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
Gerd Bayer (5):
      alpha/pci: Use official API to iterate over PCI buses
      arm/pci: Use official API to iterate over PCI buses
      powerpc/pci: Use official API to iterate over PCI buses
      x86/pci: Use official API to iterate over PCI buses
      PCI: Make pci_root_buses private to PCI core

 arch/alpha/kernel/pci.c          |  4 ++--
 arch/arm/kernel/bios32.c         |  4 ++--
 arch/powerpc/kernel/pci-common.c |  7 ++++---
 arch/powerpc/kernel/pci_64.c     |  4 ++--
 arch/x86/pci/i386.c              | 14 ++++++++------
 drivers/pci/pci.h                |  3 +++
 drivers/pci/probe.c              |  2 --
 include/linux/pci.h              |  4 ----
 8 files changed, 21 insertions(+), 21 deletions(-)
---
base-commit: 5d6919055dec134de3c40167a490f33c74c12581
change-id: 20260508-priv_root_buses-0263ef2679ad

Best regards,
-- 
Gerd Bayer <gbayer@linux.ibm.com>



^ permalink raw reply

* [PATCH 5/5] PCI: Make pci_root_buses private to PCI core
From: Gerd Bayer @ 2026-05-15 14:22 UTC (permalink / raw)
  To: Richard Henderson, Matt Turner, Magnus Lindholm, Russell King,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy (CS GROUP), Bjorn Helgaas, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin
  Cc: Yinghai Lu, linux-alpha, linux-kernel, linux-arm-kernel,
	linuxppc-dev, linux-pci, Gerd Bayer
In-Reply-To: <20260515-priv_root_buses-v1-0-f8e393c57390@linux.ibm.com>

After all users of pci_root_buses external to PCI core have been
converted to using pci_find_next_bus(), move its declaration to the
PCI core code and stop exporting the symbol.

Signed-off-by: Gerd Bayer <gbayer@linux.ibm.com>
---
 drivers/pci/pci.h   | 3 +++
 drivers/pci/probe.c | 2 --
 include/linux/pci.h | 4 ----
 3 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4a14f88e543a..1f36d400c9e0 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -366,6 +366,9 @@ static inline void pci_create_legacy_files(struct pci_bus *bus) { }
 static inline void pci_remove_legacy_files(struct pci_bus *bus) { }
 #endif
 
+/* List of all known PCI buses */
+extern struct list_head pci_root_buses;
+
 /* Lock for read/write access to pci device and bus lists */
 extern struct rw_semaphore pci_bus_sem;
 extern struct mutex pci_slot_mutex;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index b63cd0c310bc..2e97ab125ead 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -33,9 +33,7 @@ static struct resource busn_resource = {
 	.flags	= IORESOURCE_BUS,
 };
 
-/* Ugh.  Need to stop exporting this to modules. */
 LIST_HEAD(pci_root_buses);
-EXPORT_SYMBOL(pci_root_buses);
 
 static LIST_HEAD(pci_domain_busn_res_list);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2c4454583c11..1c4610848b5c 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1192,10 +1192,6 @@ extern enum pcie_bus_config_types pcie_bus_config;
 
 extern const struct bus_type pci_bus_type;
 
-/* Do NOT directly access these two variables, unless you are arch-specific PCI
- * code, or PCI core code. */
-extern struct list_head pci_root_buses;	/* List of all known PCI buses */
-
 void pcibios_resource_survey_bus(struct pci_bus *bus);
 void pcibios_bus_add_device(struct pci_dev *pdev);
 void pcibios_add_bus(struct pci_bus *bus);

-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH RFC 05/12] usb: hub: Power on connected M.2 E-key connectors
From: Alan Stern @ 2026-05-15 14:39 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, linux-pm, linux-usb, devicetree,
	linux-mediatek, linux-arm-kernel, linux-kernel,
	Manivannan Sadhasivam
In-Reply-To: <20260515090149.3169406-6-wenst@chromium.org>

On Fri, May 15, 2026 at 05:01:41PM +0800, Chen-Yu Tsai wrote:
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 90ea597d42ae..4165f71e212b 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -31,7 +31,9 @@
>  #include <linux/minmax.h>
>  #include <linux/mutex.h>
>  #include <linux/random.h>
> +#include <linux/of_graph.h>
>  #include <linux/pm_qos.h>
> +#include <linux/pwrseq/consumer.h>
>  #include <linux/kobject.h>
>  
>  #include <linux/bitfield.h>
> @@ -888,13 +890,25 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
>  {
>  	int ret;
>  
> +	if (set)
> +		ret = pwrseq_power_on(hub->ports[port1 - 1]->pwrseq);
> +	else
> +		ret = pwrseq_power_off(hub->ports[port1 - 1]->pwrseq);
> +	if (ret)
> +		return ret;
> +
>  	if (set)
>  		ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
>  	else
>  		ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
>  
> -	if (ret)
> +	if (ret) {
> +		if (set)
> +			pwrseq_power_off(hub->ports[port1 - 1]->pwrseq);
> +		else
> +			pwrseq_power_on(hub->ports[port1 - 1]->pwrseq);
>  		return ret;
> +	}
>  
>  	if (set)
>  		set_bit(port1, hub->power_bits);
> @@ -1867,6 +1881,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
>  	struct usb_host_interface *desc;
>  	struct usb_device *hdev;
>  	struct usb_hub *hub;
> +	int ret;
>  
>  	desc = intf->cur_altsetting;
>  	hdev = interface_to_usbdev(intf);

This change is totally useless.  Didn't you get a warning from the 
compiler when you built it?

> diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
> index 9ebc5ef54a32..6039e5f5dcd7 100644
> --- a/drivers/usb/core/hub.h
> +++ b/drivers/usb/core/hub.h
> @@ -85,6 +85,7 @@ struct usb_hub {
>   * @port_owner: port's owner
>   * @peer: related usb2 and usb3 ports (share the same connector)
>   * @connector: USB Type-C connector
> + * @pwrseq: power sequencing descriptor for the port
>   * @req: default pm qos request for hubs without port power control
>   * @connect_type: port's connect type
>   * @state: device state of the usb device attached to the port
> @@ -104,6 +105,7 @@ struct usb_port {
>  	struct usb_dev_state *port_owner;
>  	struct usb_port *peer;
>  	struct typec_connector *connector;
> +	struct pwrseq_desc *pwrseq;
>  	struct dev_pm_qos_request *req;
>  	enum usb_port_connect_type connect_type;
>  	enum usb_device_state state;

The fact that hub.h uses struct pwrseq_desc indicates that it ought to 
#include <linux/pwrseq/consumer.h>, instead of making the .c files do 
so themselves.  Then you wouldn't have to add the #include lines to 
hub.c and port.c.

> diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
> index b1364f0c384c..2d09037fee93 100644
> --- a/drivers/usb/core/port.c
> +++ b/drivers/usb/core/port.c
> @@ -7,11 +7,14 @@
>   * Author: Lan Tianyu <tianyu.lan@intel.com>
>   */
>  
> +#include <linux/cleanup.h>

Why is this needed?

>  #include <linux/kstrtox.h>
>  #include <linux/slab.h>
>  #include <linux/string_choices.h>
>  #include <linux/sysfs.h>
> +#include <linux/of_graph.h>
>  #include <linux/pm_qos.h>
> +#include <linux/pwrseq/consumer.h>
>  #include <linux/component.h>
>  #include <linux/usb/of.h>
>  

Alan Stern


^ permalink raw reply

* Re: [PATCH 01/19] btrfs: require at least 4 devices for RAID 6
From: David Sterba @ 2026-05-15 14:51 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: kreijack, Goffredo Baroncelli, Christoph Hellwig, Andrew Morton,
	Catalin Marinas, Will Deacon, Ard Biesheuvel, Huacai Chen,
	WANG Xuerui, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP), Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
	Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
	Sven Schnelle, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, Herbert Xu, Dan Williams, Chris Mason,
	David Sterba, Arnd Bergmann, Song Liu, Yu Kuai, Li Nan,
	linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
	linux-riscv, linux-s390, linux-crypto, linux-btrfs, linux-arch,
	linux-raid
In-Reply-To: <0507CCEF-0548-442F-8703-1D006B5E068B@zytor.com>

On Thu, May 14, 2026 at 12:57:53PM -0700, H. Peter Anvin wrote:
> On May 14, 2026 12:51:59 PM PDT, Goffredo Baroncelli <kreijack@libero.it> wrote:
> >On 13/05/2026 07.47, Christoph Hellwig wrote:
> >> On Tue, May 12, 2026 at 01:42:31PM +0200, David Sterba wrote:
> >
> >> 
> >>> The degenerate modes of
> >>> raid0, 5, or 6 are explicit as a possible middle step when converting
> >>> profiles.  We can use a fallback implementation for this case if the
> >>> accelerated implementations cannot do it.
> >> 
> >> This is not about a degenerated mode.  For a degenerated RAID 6, parity
> >> generation uses the RAID 5 XOR routines as the second parity will be
> >> missing.  This is about generating two parities for a single data disk,
> >> which must be explicitly selected.
> >> 
> >
> >I think that the David concern is : "what happens for an already
> >existing btrfs raid6 3 disks filesystem when the user upgrade the kernel ?"
> >(I am thinking when a new BG needs to be allocated)...
> 
> That's what I'm saying – it should invoke the RAID-1 code under the cover (as with 3 disks, D = P = Q.)

Thanks, it was not clear to me what you meant. For the two edge cases
the code should do simple memcpy for both calculations of parity and
recovery.


^ permalink raw reply

* Re: [PATCH v2 6/8] PCI: aardvark: Add 100 ms delay after link training
From: Hans Zhang @ 2026-05-15 15:04 UTC (permalink / raw)
  To: Pali Rohár
  Cc: bhelgaas, lpieralisi, kwilczynski, mani, vigneshr, jingoohan1,
	thomas.petazzoni, ryder.lee, jianjun.wang, claudiu.beznea.uj,
	mpillai, robh, s-vadapalli, linux-omap, linux-arm-kernel,
	linux-mediatek, linux-renesas-soc, linux-pci, linux-kernel
In-Reply-To: <20260513185442.mw3md5te7dhojyd7@pali>



On 5/14/26 02:54, Pali Rohár wrote:
> On Wednesday 13 May 2026 15:34:46 Hans Zhang wrote:
>> On 5/13/26 15:20, Pali Rohár wrote:
>>> On Wednesday 13 May 2026 15:00:04 Hans Zhang wrote:
>>>>
>>>>
>>>> On 5/13/26 05:25, Pali Rohár wrote:
>>>>> On Wednesday 06 May 2026 23:23:44 Hans Zhang wrote:
>>>>>> The Aardvark PCIe controller driver waits for the link to come up but
>>>>>> does not implement the mandatory 100 ms delay after link training
>>>>>> completes for speeds greater than 5.0 GT/s (PCIe r6.0 sec 6.6.1).
>>>>>>
>>>>>> The driver already maintains a 'link_gen' field that holds the negotiated
>>>>>> link speed. Use it together with pcie_wait_after_link_train() to insert
>>>>>> the required delay immediately after confirming that the link is up.
>>>>>>
>>>>>> Signed-off-by: Hans Zhang <18255117159@163.com>
>>>>>> ---
>>>>>>     drivers/pci/controller/pci-aardvark.c | 4 +++-
>>>>>>     1 file changed, 3 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
>>>>>> index e34bea1ff0ac..526351c21c49 100644
>>>>>> --- a/drivers/pci/controller/pci-aardvark.c
>>>>>> +++ b/drivers/pci/controller/pci-aardvark.c
>>>>>> @@ -350,8 +350,10 @@ static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
>>>>>>     	/* check if the link is up or not */
>>>>>>     	for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
>>>>>> -		if (advk_pcie_link_up(pcie))
>>>>>> +		if (advk_pcie_link_up(pcie)) {
>>>>>> +			pcie_wait_after_link_train(pcie->link_gen);
>>>>>>     			return 0;
>>>>>> +		}
>>>>>>     		usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
>>>>>>     	}
>>>>>> -- 
>>>>>> 2.34.1
>>>>>>
>>>>>
>>>>> Are you sure that this is correct to do? Have you checked the A3720
>>>>> Functional Specification which describes how to bring PCIe link up?
>>>>>
>>>>> A3720 PCIe controller is buggy and needs more timing hacks to make it
>>>>> behave. Playing with random sleeps can break its internal logic.
>>>>> I'm not sure if it could be safe without proper testing.
>>>>>
>>>>> And IIRC A3720 PCIe controller is just PCIe2.0 with 5 GT/s.
>>>>
>>>>
>>>> Hi Pali,
>>>>
>>>> 1. This driver does not support A3720.
>>>>
>>>> static const struct of_device_id advk_pcie_of_match_table[] = {
>>>> 	{ .compatible = "marvell,armada-3700-pcie", },
>>>> 	{},
>>>> };
>>>> MODULE_DEVICE_TABLE(of, advk_pcie_of_match_table);
>>>>
>>>> If you need support for A3720, please submit the corresponding patch so that
>>>> Bjorn and Mani can review it.
>>>
>>> 3700 (or 37xx) is family and covers both a3710 and a3720. In most cases is the
>>> a3720 dominant and hence identifiers 3700 and 3720 are begin mixed.
>>>
>>>>
>>>> 2. If A3720 only supports GEN2, you can configure "max-link-speed" to be 2
>>>> in the DT. This will not affect the functionality of this patch.
>>>
>>> Whole A37xx supports only GEN2. And in DT files for 37xx should be
>>> already there max-link-speed.
>>>
>>> Seems that in advk_pcie_of_match_table there is no GEN3 device
>>> specified.
>>>
>>
>> Hi Pali,
>>
>> However, I saw many GEN3 assignments and conditions in the code.
>>
>> ret = of_pci_get_max_link_speed(dev->of_node);
>> if (ret <= 0 || ret > 3)
>> 	pcie->link_gen = 3;
>> else
>> 	pcie->link_gen = ret;
>>
>>
>> static void advk_pcie_train_link(struct advk_pcie *pcie)
>> {
>> 	struct device *dev = &pcie->pdev->dev;
>> 	u32 reg;
>> 	int ret;
>>
>> 	/*
>> 	 * Setup PCIe rev / gen compliance based on device tree property
>> 	 * 'max-link-speed' which also forces maximal link speed.
>> 	 */
>> 	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
>> 	reg &= ~PCIE_GEN_SEL_MSK;
>> 	if (pcie->link_gen == 3)
>> 		reg |= SPEED_GEN_3;
>> 	else if (pcie->link_gen == 2)
>> 		reg |= SPEED_GEN_2;
>> 	else
>> 		reg |= SPEED_GEN_1;
>> 	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
>>
>> 	/*
>> 	 * Set maximal link speed value also into PCIe Link Control 2 register.
>> 	 * Armada 3700 Functional Specification says that default value is based
>> 	 * on SPEED_GEN but tests showed that default value is always 8.0 GT/s.
>> 	 */
>> 	reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
>> 	reg &= ~PCI_EXP_LNKCTL2_TLS;
>> 	if (pcie->link_gen == 3)
>> 		reg |= PCI_EXP_LNKCTL2_TLS_8_0GT;
>> 	else if (pcie->link_gen == 2)
>> 		reg |= PCI_EXP_LNKCTL2_TLS_5_0GT;
>> 	else
>> 		reg |= PCI_EXP_LNKCTL2_TLS_2_5GT;
>> 	advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
>>
>> ....
>>
>>
>> If you are certain about the relevant information. Is it understandable that
>> we need to delete the code related to GEN3?
> 
> Ok. So some explanation. pci-aardvark.c is implementing driver for PCIe
> controller with codename aardvark. I have no idea from what this
> codename comes and what is represents. What we know that the driver was
> written for A37xx SoC platform according to A37xx functional specification.
> As it is common in SoC world, vendors just buy some IP and integrate it
> into SoC. In this case Marvell bought this PCIe controller IP and
> integrated it into the A37xx. In past I tried to investigate what it
> could be and IIRC my assumption was that it was PCIe IP from Denali.
> Denali was acquired by Cadence, and when I compared Cadence PCIe
> controller registers and PCIe controller registers in A37xx functional
> specification there were large overlap. For me it looked like new
> Cadence PCIe controller is an evolution (or new version) of what is in
> A37xx. So this was some confirmation of my theory. Linux kernel has
> separate driver for PCIe controller from Cadence and for refactoring
> there were ideas to merge these two drivers... But there were more
> important things, fix issues related to A37xx PCIe, lot of changes
> which address these issues were sent to the list but they were not
> taken. I do not think that it makes sense to do refactoring or doing any
> other changes before addressing any existing issues with these
> drivers (like PCIe card is not working correctly).
> 
> There are reported more HW erratas for this PCIe controller which needs
> to be addressed in the software (meaning in Linux kernel) to make PCIe
> card working properly. And there are more design HW decision which needs
> does not conform to the PCIe specification and those deviations needs to
> be "fixed" or "adjusted" in software (meaning in pci-aardvark.c driver)
> to make PCI/PCIe compatible drivers to work correctly.
> 
> Now about GEN3. From register allocation it looks like that PCIe IP
> supports GEN3. A37xx does not support it (or at least officially). This
> does not mean that there cannot be some SoC with this "aardvark" PCIe IP
> that is GEN3 capable. Just we see that such SoC is not supported by Linux.
> Also as the comment in above code says, by default the speed is reported
> as 8.0 GT/s, so changing it to 5.0 GT/s or 2.5 GT/s is needed as so code
> some parts of GEN3 code in the driver is needed.
> 
> Does it makes sense to remove it? Does it makes sense to spend time on
> such thing which does not address any existing issue? For me not.
> Because it does not fix any _real_ issue with existing PCIe cards. And
> for refactoring it is better to merge drivers as explained above and
> IIRC cadence driver has HW on which is GEN3 used.
> 
> Now about your change. If you are sure that pcie_wait_after_link_train()
> function is noop for pcie->link_gen == 2 || pcie->link_gen == 1 then go
> ahead, I have no objects. I have not looked deeply at the change. I just
> spotted some change which is touching timing critical code path which
> was problematic in the past and broke many wifi cards. So I'm really
> careful to prevent breaking Linux support again.
> 

Hi Pali,

This condition, pcie->link_gen == 2 || pcie->link_gen == 1, will have no 
effect.


Best regards,
Hans

> As maintainers decided to not take any new changes from me for this
> driver, I have no motivation to prepare any new changes. I will rather
> spend my free time on something which will make sense and not be wasting
> of my free time.
>



^ permalink raw reply

* [PATCH 0/4] ASoC: meson: aiu: align I2S design to the AXG one
From: Valerio Setti @ 2026-05-15 15:10 UTC (permalink / raw)
  To: Jerome Brunet, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Neil Armstrong, Kevin Hilman, Martin Blumenstingl
  Cc: linux-kernel, linux-sound, linux-arm-kernel, linux-amlogic,
	Valerio Setti

This is the first follow-up patch series based on RFC [1]. The goal here
is simply to reshape Amlogic GX's AIU implementation for I2S to follow
the same design as in AXG's TDM. Keeping the same design allows for
unifying the two platform implementations in the future.

The first commit introduces gx-formatter as the basic block which takes
care of properly formatting audio data. Formatters are DAPM widgets
(c.f. axg-tdm-formatter in AXG) which are dynamically attached/detached
to the streams when the latters starts/stop, respectively.
aiu-formatter-i2s is introduced as formatter implementation for the i2s
output.

By the end aiu-encoder-i2s will only need to handle interface clocks and
enforce interface wide rate symmetry (c.f axg-tdm-interface on the AXG
platform). Right now rate symmetry is not relevant because only i2s output
is supported, but it will become useful when following patch series will
introduce the i2s input part.

This series was tested on an OdroidC2 board (Amlogic S905 SOC) with an
NXP SGTL5000 codec connected to its I2S input port.

Changes from RFC:
- Use devm_ variant of snd_soc_register_component in gx_formatte_probe.
- Return on failures in aiu_encoder_i2s_set_sysclk.
- MCLK and i2s_divider clocks enablement moved from hw_params() to
  prepare(). Stream's "clk_enabled" is used as simple refcounting to
  prevent multiple enable/disable.
- Improved the mechanism to ensure rate symmetry on the interface.
  Previous implementation had issues with alsaloop when both capture and
  playback streams are opened before any hw_params is set on any of them.

Thanks to Mark Brown and Jerome Brunet for the review of the RFC.

[1]: https://lore.kernel.org/linux-sound/20260411-audin-rfc-v2-0-4c8a6ec5fcab@baylibre.com/

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
---
Valerio Setti (4):
      ASoC: meson: gx: add gx-formatter and gx-interface
      ASoC: meson: aiu-encoder-i2s: use gx_iface and gx_stream structures
      ASoC: meson: aiu: introduce I2S output formatter
      ASoC: meson: aiu: use aiu-formatter-i2s to format I2S output data

 sound/soc/meson/Makefile            |   2 +
 sound/soc/meson/aiu-encoder-i2s.c   | 250 +++++++++++++++++++++-----------
 sound/soc/meson/aiu-formatter-i2s.c | 106 ++++++++++++++
 sound/soc/meson/aiu.c               |  30 +++-
 sound/soc/meson/aiu.h               |   4 +
 sound/soc/meson/gx-formatter.c      | 277 ++++++++++++++++++++++++++++++++++++
 sound/soc/meson/gx-formatter.h      |  47 ++++++
 sound/soc/meson/gx-interface.h      |  45 ++++++
 8 files changed, 675 insertions(+), 86 deletions(-)
---
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
change-id: 20260515-reshape-aiu-as-axg-1dac9037cad3

Best regards,
-- 
Valerio Setti <vsetti@baylibre.com>



^ permalink raw reply

* [PATCH 4/4] ASoC: meson: aiu: use aiu-formatter-i2s to format I2S output data
From: Valerio Setti @ 2026-05-15 15:10 UTC (permalink / raw)
  To: Jerome Brunet, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Neil Armstrong, Kevin Hilman, Martin Blumenstingl
  Cc: linux-kernel, linux-sound, linux-arm-kernel, linux-amlogic,
	Valerio Setti
In-Reply-To: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com>

Create a new DAPM widget for "I2S formatter" and place it on the path
between FIFO and output DAI interface. Remove I2S output formatting code
from aiu-encoder-i2s since it's now implemented from aiu-formatter-i2s.

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
---
 sound/soc/meson/aiu-encoder-i2s.c | 56 ---------------------------------------
 sound/soc/meson/aiu.c             | 30 ++++++++++++++++++---
 sound/soc/meson/aiu.h             |  1 +
 3 files changed, 27 insertions(+), 60 deletions(-)

diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c
index 39accd396affb8beb49fa7cca394244730b24574..9f935a93aeab7a27f880fbde2d29041a4802e3a3 100644
--- a/sound/soc/meson/aiu-encoder-i2s.c
+++ b/sound/soc/meson/aiu-encoder-i2s.c
@@ -13,13 +13,6 @@
 #include "gx-formatter.h"
 #include "gx-interface.h"
 
-#define AIU_I2S_SOURCE_DESC_MODE_8CH	BIT(0)
-#define AIU_I2S_SOURCE_DESC_MODE_24BIT	BIT(5)
-#define AIU_I2S_SOURCE_DESC_MODE_32BIT	BIT(9)
-#define AIU_I2S_SOURCE_DESC_MODE_SPLIT	BIT(11)
-#define AIU_RST_SOFT_I2S_FAST		BIT(0)
-
-#define AIU_I2S_DAC_CFG_MSB_FIRST	BIT(2)
 #define AIU_CLK_CTRL_I2S_DIV_EN		BIT(0)
 #define AIU_CLK_CTRL_I2S_DIV		GENMASK(3, 2)
 #define AIU_CLK_CTRL_AOCLK_INVERT	BIT(6)
@@ -37,49 +30,6 @@ static void aiu_encoder_i2s_divider_enable(struct snd_soc_component *component,
 				      enable ? AIU_CLK_CTRL_I2S_DIV_EN : 0);
 }
 
-static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component,
-				      struct snd_pcm_hw_params *params)
-{
-	/* Always operate in split (classic interleaved) mode */
-	unsigned int desc = AIU_I2S_SOURCE_DESC_MODE_SPLIT;
-
-	/* Reset required to update the pipeline */
-	snd_soc_component_write(component, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST);
-	snd_soc_component_read(component, AIU_I2S_SYNC);
-
-	switch (params_physical_width(params)) {
-	case 16: /* Nothing to do */
-		break;
-
-	case 32:
-		desc |= (AIU_I2S_SOURCE_DESC_MODE_24BIT |
-			 AIU_I2S_SOURCE_DESC_MODE_32BIT);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	switch (params_channels(params)) {
-	case 2: /* Nothing to do */
-		break;
-	case 8:
-		desc |= AIU_I2S_SOURCE_DESC_MODE_8CH;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	snd_soc_component_update_bits(component, AIU_I2S_SOURCE_DESC,
-				      AIU_I2S_SOURCE_DESC_MODE_8CH |
-				      AIU_I2S_SOURCE_DESC_MODE_24BIT |
-				      AIU_I2S_SOURCE_DESC_MODE_32BIT |
-				      AIU_I2S_SOURCE_DESC_MODE_SPLIT,
-				      desc);
-
-	return 0;
-}
-
 static int aiu_encoder_i2s_set_legacy_div(struct snd_soc_component *component,
 					  struct gx_stream *ts,
 					  unsigned int bs)
@@ -201,12 +151,6 @@ static int aiu_encoder_i2s_hw_params(struct snd_pcm_substream *substream,
 	ts->width = params_width(params);
 	ts->channels = params_channels(params);
 
-	ret = aiu_encoder_i2s_setup_desc(component, params);
-	if (ret) {
-		dev_err(dai->dev, "setting i2s desc failed: %d\n", ret);
-		return ret;
-	}
-
 	ret = aiu_encoder_i2s_set_clocks(component, ts);
 	if (ret) {
 		dev_err(dai->dev, "setting i2s clocks failed: %d\n", ret);
diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c
index f2890111c1d2cfa2213bf01849957a796744b9ae..b09c2058eacaf2998d0d3cd6682910f94ec89912 100644
--- a/sound/soc/meson/aiu.c
+++ b/sound/soc/meson/aiu.c
@@ -29,13 +29,22 @@ static SOC_ENUM_SINGLE_DECL(aiu_spdif_encode_sel_enum, AIU_I2S_MISC,
 static const struct snd_kcontrol_new aiu_spdif_encode_mux =
 	SOC_DAPM_ENUM("SPDIF Buffer Src", aiu_spdif_encode_sel_enum);
 
-static const struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] = {
-	SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0,
-			 &aiu_spdif_encode_mux),
+#define AIU_WIDGET_SPDIF_SRC_SEL	0
+#define AIU_WIDGET_I2S_FORMATTER	1
+
+static struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] = {
+	[AIU_WIDGET_SPDIF_SRC_SEL] =
+		SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0,
+				 &aiu_spdif_encode_mux),
+	[AIU_WIDGET_I2S_FORMATTER] =
+		SND_SOC_DAPM_PGA_E("I2S Formatter", SND_SOC_NOPM, 0, 0, NULL, 0,
+				   gx_formatter_event,
+				   (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD)),
 };
 
 static const struct snd_soc_dapm_route aiu_cpu_dapm_routes[] = {
-	{ "I2S Encoder Playback", NULL, "I2S FIFO Playback" },
+	{ "I2S Formatter", NULL, "I2S FIFO Playback" },
+	{ "I2S Encoder Playback", NULL, "I2S Formatter" },
 	{ "SPDIF SRC SEL", "SPDIF", "SPDIF FIFO Playback" },
 	{ "SPDIF SRC SEL", "I2S", "I2S FIFO Playback" },
 	{ "SPDIF Encoder Playback", NULL, "SPDIF SRC SEL" },
@@ -172,6 +181,11 @@ static const struct regmap_config aiu_regmap_cfg = {
 	.max_register	= 0x2ac,
 };
 
+const struct gx_formatter_driver aiu_formatter_i2s_drv = {
+	.regmap_cfg	= &aiu_regmap_cfg,
+	.ops		= &aiu_formatter_i2s_ops,
+};
+
 static int aiu_clk_bulk_get(struct device *dev,
 			    const char * const *ids,
 			    unsigned int num,
@@ -291,6 +305,14 @@ static int aiu_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	/* Allocate the aiu-formatter into its widget */
+	ret = gx_formatter_create(dev, &aiu_cpu_dapm_widgets[AIU_WIDGET_I2S_FORMATTER],
+				  &aiu_formatter_i2s_drv, map);
+	if (ret) {
+		dev_err(dev, "Failed to allocate aiu formatter\n");
+		goto err;
+	}
+
 	/* Register the hdmi codec control component */
 	ret = aiu_hdmi_ctrl_register_component(dev);
 	if (ret) {
diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h
index 68310de0bdf7a97d8de2ff306c159248ee9b0ede..7d0b98c1f351b3c526ca06c43a4c04ee5f4b6dfa 100644
--- a/sound/soc/meson/aiu.h
+++ b/sound/soc/meson/aiu.h
@@ -61,6 +61,7 @@ extern const struct snd_soc_dai_ops aiu_fifo_i2s_dai_ops;
 extern const struct snd_soc_dai_ops aiu_fifo_spdif_dai_ops;
 extern const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops;
 extern const struct snd_soc_dai_ops aiu_encoder_spdif_dai_ops;
+extern const struct gx_formatter_ops aiu_formatter_i2s_ops;
 
 #define AIU_IEC958_BPF			0x000
 #define AIU_958_MISC			0x010

-- 
2.39.5



^ permalink raw reply related

* [PATCH 2/4] ASoC: meson: aiu-encoder-i2s: use gx_iface and gx_stream structures
From: Valerio Setti @ 2026-05-15 15:10 UTC (permalink / raw)
  To: Jerome Brunet, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Neil Armstrong, Kevin Hilman, Martin Blumenstingl
  Cc: linux-kernel, linux-sound, linux-arm-kernel, linux-amlogic,
	Valerio Setti
In-Reply-To: <20260515-reshape-aiu-as-axg-v1-0-53b457784ff3@baylibre.com>

Start using gx_iface and gx_stream to store interface and stream info,
respectively. probe()/remove() functions are added to allocate/free the
gx_stream structures for each PCM stream.

Clock-wise instead of bulk enabling all the clocks on startup and disabling
them on shutdown, only the peripheral's internal ones are enabled/disabled
in those functions, whereas MCLK and I2S clock divider are handled in
hw_params/hw_free.
Interface wide rate symmetry is also enforced here. This is useful when the
interface is used for playback and capture at the same time.

Finally a trigger() callback is also added to start/stop the associated
I2S data formatter.

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
---
 sound/soc/meson/aiu-encoder-i2s.c | 200 ++++++++++++++++++++++++++++++++------
 sound/soc/meson/aiu.h             |   3 +
 2 files changed, 174 insertions(+), 29 deletions(-)

diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c
index 3b4061508c18047fe8d6f3f98061720f8ce238f2..39accd396affb8beb49fa7cca394244730b24574 100644
--- a/sound/soc/meson/aiu-encoder-i2s.c
+++ b/sound/soc/meson/aiu-encoder-i2s.c
@@ -10,6 +10,8 @@
 #include <sound/soc-dai.h>
 
 #include "aiu.h"
+#include "gx-formatter.h"
+#include "gx-interface.h"
 
 #define AIU_I2S_SOURCE_DESC_MODE_8CH	BIT(0)
 #define AIU_I2S_SOURCE_DESC_MODE_24BIT	BIT(5)
@@ -79,7 +81,7 @@ static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component,
 }
 
 static int aiu_encoder_i2s_set_legacy_div(struct snd_soc_component *component,
-					  struct snd_pcm_hw_params *params,
+					  struct gx_stream *ts,
 					  unsigned int bs)
 {
 	switch (bs) {
@@ -109,7 +111,7 @@ static int aiu_encoder_i2s_set_legacy_div(struct snd_soc_component *component,
 }
 
 static int aiu_encoder_i2s_set_more_div(struct snd_soc_component *component,
-					struct snd_pcm_hw_params *params,
+					struct gx_stream *ts,
 					unsigned int bs)
 {
 	/*
@@ -119,7 +121,7 @@ static int aiu_encoder_i2s_set_more_div(struct snd_soc_component *component,
 	 * increased by 50% to get the correct output rate.
 	 * No idea why !
 	 */
-	if (params_width(params) == 16 && params_channels(params) == 8) {
+	if (ts->width == 16 && ts->channels == 8) {
 		if (bs % 2) {
 			dev_err(component->dev,
 				"Cannot increase i2s divider by 50%%\n");
@@ -142,24 +144,18 @@ static int aiu_encoder_i2s_set_more_div(struct snd_soc_component *component,
 }
 
 static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component,
-				      struct snd_pcm_hw_params *params)
+				      struct gx_stream *ts)
 {
 	struct aiu *aiu = snd_soc_component_get_drvdata(component);
-	unsigned int srate = params_rate(params);
 	unsigned int fs, bs;
 	int ret;
 
 	/* Get the oversampling factor */
-	fs = DIV_ROUND_CLOSEST(clk_get_rate(aiu->i2s.clks[MCLK].clk), srate);
+	fs = DIV_ROUND_CLOSEST(ts->iface->mclk_rate, ts->iface->rate);
 
 	if (fs % 64)
 		return -EINVAL;
 
-	/* Send data MSB first */
-	snd_soc_component_update_bits(component, AIU_I2S_DAC_CFG,
-				      AIU_I2S_DAC_CFG_MSB_FIRST,
-				      AIU_I2S_DAC_CFG_MSB_FIRST);
-
 	/* Set bclk to lrlck ratio */
 	snd_soc_component_update_bits(component, AIU_CODEC_DAC_LRCLK_CTRL,
 				      AIU_CODEC_DAC_LRCLK_CTRL_DIV,
@@ -169,9 +165,9 @@ static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component,
 	bs = fs / 64;
 
 	if (aiu->platform->has_clk_ctrl_more_i2s_div)
-		ret = aiu_encoder_i2s_set_more_div(component, params, bs);
+		ret = aiu_encoder_i2s_set_more_div(component, ts, bs);
 	else
-		ret = aiu_encoder_i2s_set_legacy_div(component, params, bs);
+		ret = aiu_encoder_i2s_set_legacy_div(component, ts, bs);
 
 	if (ret)
 		return ret;
@@ -188,25 +184,55 @@ static int aiu_encoder_i2s_hw_params(struct snd_pcm_substream *substream,
 				     struct snd_pcm_hw_params *params,
 				     struct snd_soc_dai *dai)
 {
+	struct gx_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
+	struct gx_iface *iface = ts->iface;
 	struct snd_soc_component *component = dai->component;
 	int ret;
 
-	/* Disable the clock while changing the settings */
-	aiu_encoder_i2s_divider_enable(component, false);
+	/* Enforce interface wide rate symmetry. */
+	if (iface->rate && (iface->rate != params_rate(params))) {
+		dev_err(dai->dev, "can't set iface rate (%d != %d)\n",
+			iface->rate, params_rate(params));
+		return -EINVAL;
+	}
+
+	iface->rate = params_rate(params);
+	ts->physical_width = params_physical_width(params);
+	ts->width = params_width(params);
+	ts->channels = params_channels(params);
 
 	ret = aiu_encoder_i2s_setup_desc(component, params);
 	if (ret) {
-		dev_err(dai->dev, "setting i2s desc failed\n");
+		dev_err(dai->dev, "setting i2s desc failed: %d\n", ret);
 		return ret;
 	}
 
-	ret = aiu_encoder_i2s_set_clocks(component, params);
+	ret = aiu_encoder_i2s_set_clocks(component, ts);
 	if (ret) {
-		dev_err(dai->dev, "setting i2s clocks failed\n");
+		dev_err(dai->dev, "setting i2s clocks failed: %d\n", ret);
 		return ret;
 	}
 
-	aiu_encoder_i2s_divider_enable(component, true);
+	return 0;
+}
+
+static int aiu_encoder_i2s_prepare(struct snd_pcm_substream *substream,
+				   struct snd_soc_dai *dai)
+{
+	struct gx_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
+	struct snd_soc_component *component = dai->component;
+	int ret;
+
+	if (ts->clk_enabled)
+		return 0;
+
+	ret = clk_prepare_enable(ts->iface->mclk);
+	if (ret)
+		return ret;
+
+	ts->clk_enabled = true;
+
+	aiu_encoder_i2s_divider_enable(component, 1);
 
 	return 0;
 }
@@ -214,9 +240,20 @@ static int aiu_encoder_i2s_hw_params(struct snd_pcm_substream *substream,
 static int aiu_encoder_i2s_hw_free(struct snd_pcm_substream *substream,
 				   struct snd_soc_dai *dai)
 {
+	struct gx_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
 	struct snd_soc_component *component = dai->component;
 
-	aiu_encoder_i2s_divider_enable(component, false);
+	/*
+	 * Disable the i2s clock divider only if this is the last substream
+	 * being closed.
+	 */
+	if (snd_soc_dai_active(dai) <= 1)
+		aiu_encoder_i2s_divider_enable(component, 0);
+
+	if (ts->clk_enabled) {
+		clk_disable_unprepare(ts->iface->mclk);
+		ts->clk_enabled = false;
+	}
 
 	return 0;
 }
@@ -224,6 +261,8 @@ static int aiu_encoder_i2s_hw_free(struct snd_pcm_substream *substream,
 static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct snd_soc_component *component = dai->component;
+	struct aiu *aiu = snd_soc_component_get_drvdata(component);
+	struct gx_iface *iface = &aiu->i2s.iface;
 	unsigned int inv = fmt & SND_SOC_DAIFMT_INV_MASK;
 	unsigned int val = 0;
 	unsigned int skew;
@@ -255,9 +294,12 @@ static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 		skew = 0;
 		break;
 	default:
+		dev_err(dai->dev, "unsupported dai format\n");
 		return -EINVAL;
 	}
 
+	iface->fmt = fmt;
+
 	val |= FIELD_PREP(AIU_CLK_CTRL_LRCLK_SKEW, skew);
 	snd_soc_component_update_bits(component, AIU_CLK_CTRL,
 				      AIU_CLK_CTRL_LRCLK_INVERT |
@@ -281,10 +323,14 @@ static int aiu_encoder_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 		return 0;
 
 	ret = clk_set_rate(aiu->i2s.clks[MCLK].clk, freq);
-	if (ret)
-		dev_err(dai->dev, "Failed to set sysclk to %uHz", freq);
+	if (ret) {
+		dev_err(dai->dev, "Failed to set sysclk to %uHz: %d", freq, ret);
+		return ret;
+	}
 
-	return ret;
+	aiu->i2s.iface.mclk_rate = freq;
+
+	return 0;
 }
 
 static const unsigned int hw_channels[] = {2, 8};
@@ -305,30 +351,126 @@ static int aiu_encoder_i2s_startup(struct snd_pcm_substream *substream,
 					 SNDRV_PCM_HW_PARAM_CHANNELS,
 					 &hw_channel_constraints);
 	if (ret) {
-		dev_err(dai->dev, "adding channels constraints failed\n");
+		dev_err(dai->dev, "adding channels constraints failed: %d\n", ret);
 		return ret;
 	}
 
-	ret = clk_bulk_prepare_enable(aiu->i2s.clk_num, aiu->i2s.clks);
-	if (ret)
-		dev_err(dai->dev, "failed to enable i2s clocks\n");
+	/*
+	 * Enable only clocks which are required for the interface internal
+	 * logic. MCLK is enabled/disabled from the formatter and the I2S
+	 * divider is enabled/disabled in "hw_params"/"hw_free", respectively.
+	 */
+	ret = clk_prepare_enable(aiu->i2s.clks[PCLK].clk);
+	if (ret) {
+		dev_err(dai->dev, "failed to enable PCLK: %d\n", ret);
+		return ret;
+	}
+	ret = clk_prepare_enable(aiu->i2s.clks[MIXER].clk);
+	if (ret) {
+		dev_err(dai->dev, "failed to enable MIXER: %d\n", ret);
+		clk_disable_unprepare(aiu->i2s.clks[PCLK].clk);
+		return ret;
+	}
+	ret = clk_prepare_enable(aiu->i2s.clks[AOCLK].clk);
+	if (ret) {
+		dev_err(dai->dev, "failed to enable AOCLK: %d\n", ret);
+		clk_disable_unprepare(aiu->i2s.clks[MIXER].clk);
+		clk_disable_unprepare(aiu->i2s.clks[PCLK].clk);
+		return ret;
+	}
 
-	return ret;
+	return 0;
 }
 
 static void aiu_encoder_i2s_shutdown(struct snd_pcm_substream *substream,
 				     struct snd_soc_dai *dai)
 {
 	struct aiu *aiu = snd_soc_component_get_drvdata(dai->component);
+	struct gx_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
+	struct gx_iface *iface = ts->iface;
+
+	if (!snd_soc_dai_active(dai))
+		iface->rate = 0;
+
+	clk_disable_unprepare(aiu->i2s.clks[AOCLK].clk);
+	clk_disable_unprepare(aiu->i2s.clks[MIXER].clk);
+	clk_disable_unprepare(aiu->i2s.clks[PCLK].clk);
+}
 
-	clk_bulk_disable_unprepare(aiu->i2s.clk_num, aiu->i2s.clks);
+static int aiu_encoder_i2s_trigger(struct snd_pcm_substream *substream,
+				   int cmd,
+				   struct snd_soc_dai *dai)
+{
+	struct gx_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
+	int ret;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		ret = gx_stream_start(ts);
+		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_STOP:
+		gx_stream_stop(ts);
+		ret = 0;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int aiu_encoder_i2s_remove_dai(struct snd_soc_dai *dai)
+{
+	int stream;
+
+	for_each_pcm_streams(stream) {
+		struct gx_stream *ts = snd_soc_dai_dma_data_get(dai, stream);
+
+		if (ts)
+			gx_stream_free(ts);
+	}
+
+	return 0;
+}
+
+static int aiu_encoder_i2s_probe_dai(struct snd_soc_dai *dai)
+{
+	struct aiu *aiu = snd_soc_dai_get_drvdata(dai);
+	struct gx_iface *iface = &aiu->i2s.iface;
+	int stream;
+
+	for_each_pcm_streams(stream) {
+		struct gx_stream *ts;
+
+		if (!snd_soc_dai_get_widget(dai, stream))
+			continue;
+
+		ts = gx_stream_alloc(iface);
+		if (!ts) {
+			aiu_encoder_i2s_remove_dai(dai);
+			return -ENOMEM;
+		}
+		snd_soc_dai_dma_data_set(dai, stream, ts);
+	}
+
+	iface->mclk = aiu->i2s.clks[MCLK].clk;
+
+	return 0;
 }
 
 const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = {
+	.probe		= aiu_encoder_i2s_probe_dai,
+	.remove		= aiu_encoder_i2s_remove_dai,
 	.hw_params	= aiu_encoder_i2s_hw_params,
+	.prepare	= aiu_encoder_i2s_prepare,
 	.hw_free	= aiu_encoder_i2s_hw_free,
 	.set_fmt	= aiu_encoder_i2s_set_fmt,
 	.set_sysclk	= aiu_encoder_i2s_set_sysclk,
 	.startup	= aiu_encoder_i2s_startup,
 	.shutdown	= aiu_encoder_i2s_shutdown,
+	.trigger	= aiu_encoder_i2s_trigger,
 };
diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h
index 0f94c8bf608181112d78402532b832eb50c2d409..68310de0bdf7a97d8de2ff306c159248ee9b0ede 100644
--- a/sound/soc/meson/aiu.h
+++ b/sound/soc/meson/aiu.h
@@ -7,6 +7,8 @@
 #ifndef _MESON_AIU_H
 #define _MESON_AIU_H
 
+#include "gx-formatter.h"
+
 struct clk;
 struct clk_bulk_data;
 struct device;
@@ -25,6 +27,7 @@ struct aiu_interface {
 	struct clk_bulk_data *clks;
 	unsigned int clk_num;
 	int irq;
+	struct gx_iface iface;
 };
 
 struct aiu_platform_data {

-- 
2.39.5



^ 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