Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v13 3/4] gpio: rpmsg: add generic rpmsg GPIO driver
From: Mathieu Poirier @ 2026-05-14 17:35 UTC (permalink / raw)
  To: Shenwei Wang
  Cc: Arnaud POULIQUEN, Beleswar Prasad Padhi, Andrew Lunn,
	Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Frank Li,
	Sascha Hauer, Shuah Khan, linux-gpio@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	devicetree@vger.kernel.org, linux-remoteproc@vger.kernel.org,
	imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	dl-linux-imx, Bartosz Golaszewski
In-Reply-To: <PAXPR04MB9185BFA6E7375FAD0B15B021893C2@PAXPR04MB9185.eurprd04.prod.outlook.com>

On Thu, May 07, 2026 at 07:43:33PM +0000, Shenwei Wang wrote:
> 
> 
> > -----Original Message-----
> > From: Mathieu Poirier <mathieu.poirier@linaro.org>
> > Sent: Thursday, May 7, 2026 12:13 PM
> > To: Arnaud POULIQUEN <arnaud.pouliquen@foss.st.com>
> > Cc: Beleswar Prasad Padhi <b-padhi@ti.com>; Shenwei Wang
> > <shenwei.wang@nxp.com>; Andrew Lunn <andrew@lunn.ch>; Linus Walleij
> > <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>; Jonathan Corbet
> > <corbet@lwn.net>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski
> > <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn Andersson
> > <andersson@kernel.org>; Frank Li <frank.li@nxp.com>; Sascha Hauer
> > <s.hauer@pengutronix.de>; Shuah Khan <skhan@linuxfoundation.org>; linux-
> > gpio@vger.kernel.org; linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org;
> > Pengutronix Kernel Team <kernel@pengutronix.de>; Fabio Estevam
> > <festevam@gmail.com>; Peng Fan <peng.fan@nxp.com>;
> > devicetree@vger.kernel.org; linux-remoteproc@vger.kernel.org;
> > imx@lists.linux.dev; linux-arm-kernel@lists.infradead.org; dl-linux-imx <linux-
> > imx@nxp.com>; Bartosz Golaszewski <brgl@bgdev.pl>
> > Subject: [EXT] Re: [PATCH v13 3/4] gpio: rpmsg: add generic rpmsg GPIO driver
> > > > >  From my perspective, based on your proposal:
> > > > >   1) Linux should send a get_config message to the remote proc (0x405 ->
> > 0xD). 2) The remote processor would respond with the list of ports, associated
> > > > >      with an remote endpoint addresses.
> > > >
> > > >
> > > > Agreed, we can scale it for multiple remote endpoints like this.
> > > >
> > > > >   3) Linux would parse the response, compare it with the DT, enable the
> > GPIO
> > > > >      ports accordingly, creating it local endpoint and associating it with
> > > > >      the remote endpoint.
> > > > > Using name service to identify the ports should avoid step 1 & 2 ...
> > > >
> > > >
> > > > Yes, but won't that make a lot of hard-codings in the driver?
> > > >
> > > > +static struct rpmsg_device_id rpmsg_gpio_channel_id_table[] = {
> > > > +    { .name = "rpmsg-io-25" },
> > > > +    { .name = "rpmsg-io-32" },
> > > > +    { .name = "rpmsg-io-35" },
> > > > +    { },
> > > > +};
> > > >
> > > > What if tomorrow another vendor decides to add more remoteproc
> > > > controlled GPIO ports to Linux, they would have to update this
> > > > struct in the driver everytime. And the port indexes (25/32/35)
> > > > could also differ between vendors. We should make the driver dynamic
> > > > i.e. vendor agnostic.
> > > >
> > > > I think querying the remote firmware at runtime (step 1 & 2 above)
> > > > is a common design pattern and makes the driver vendor agnostic. But
> > > > feel free to correct me.
> > > >
> > >
> > > You are right. My proposal would require a patch in rpmsg-core. The
> > > idea of allowing a postfix in the compatible string has been discussed
> > > before, but, if I remember correctly, it was not concluded.
> > >
> > 
> > I also remember discussing this.  I even reviewed one of Arnaud's patch and
> > submitted one myself.  This must have been in 2020 and the reason why it wasn't
> > merged has escaped my memory.
> > 
> > > /* rpmsg devices and drivers are matched using the service name */
> > > static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
> > >                                 const struct rpmsg_device_id *id) {
> > >       size_t len;
> > >
> > > +     len = strnlen(id->name, RPMSG_NAME_SIZE);
> > > +     if (len && id->name[len - 1] == '*')
> > > +             return !strncmp(id->name, rpdev->id.name, len - 1);
> > >
> > >       return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
> > > }
> > >
> > > Then, in rpmsg-gpio, and possibly in other drivers such as rpmsg-tty
> > > and a future rpmsg-i2c, we could use:
> > > static struct rpmsg_device_id rpmsg_gpio_channel_id_table[] = {
> > >     { .name = "rpmsg-io" },
> > >     { .name = "rpmsg-io-*" },
> > >     { },
> > > };
> > 
> > That was my initial approach.  We don't even need an additional "rpmsg-io-*" in
> > rpmsg_gpio_channel_id_table[].  All we need is:
> > 
> > /* rpmsg devices and drivers are matched using the service name */ static inline
> > int rpmsg_id_match(const struct rpmsg_device *rpdev,
> >                                  const struct rpmsg_device_id *id) {
> >  +     size_t len = strnlen(id->name, RPMSG_NAME_SIZE);
> > 
> >  -     return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
> >  +     return strncmp(id->name, rpdev->id.name, len) == 0;
> > }
> > 
> 
> If we encode the port index directly into ept->src, for example:
> 
>     ept->src = (baseaddr << 8) | port_index;
>

There is no rpmsg_endpoint::src.  You likely meant ept->addr.  This would work
but not optimal on two front:

(1) rpms_endpoint::addr is a u32 and idr_alloc() returns an 'int'.  As such
there is a possibility of conflict.  I concede the possibility is marginal, but
it still exists.

(2) By proceeding this way, the kernel exposes the GPIO controller it knows
about.  It is preferrable to have the remote processor tell the kernel about the
GPIO controller it wants.

I am done reviewing this revision.  Given the amount of refactoring needed, I
will not look at the code.  Please refer to this reply [1] for what I am
expecting in the next revision. 

[1]. https://lwn.net/ml/all/CANLsYkwBk0KbN-k9ce+5=oT+scdZ3nU5AOr3Fz4zT=0AFzghDA@mail.gmail.com/
 
> where baseaddr can be derived from the channel address, we can avoid the possible address conflict.
> 
> With this approach, the patch to rpmsg-core would no longer be necessary.
> 
> Thanks,
> Shenwei
> 
> > And let the rpmsg-virtio-gpio driver parse @rpdev->id.name to match with a
> > GPIO controller in the DT.
> > 
> > >
> > > If exact name matching is strongly required, then this proposal would
> > > not be suitablea.
> > >
> > > A third option would be a combination of both approaches: instantiate
> > > the device using the same name service from the remote side, as done
> > > in rpmsg-tty. In that case, a get_config message, or a similar
> > > mechanism, would also be needed to retrieve the port information from the
> > remote side.
> > >
> > 
> > I'm not overly fond of a get_config message because it is one more thing we have
> > to define and maintain.
> > 
> > Arnaud: is there a get_config message already defined for rpmsg_tty?
> > 
> > Beleswar: Can you provide a link to a virtio device that would use a get_config
> > message?
> > 
> > > Tanmaya also proposed another alternative based on reserved addresses.
> > >
> > > At this point, I suggest letting Mathieu review the discussion and
> > > recommend the most suitable approach.
> > >
> > > Thanks,
> > > Arnaud
> > >
> > > > >
> > > > > At the end, whatever solution is implemented, my main concern is
> > > > > that the Linux driver design should, if possible, avoid adding
> > > > > unnecessary complexity or limitations on the remote side (for instance in
> > openAMP project).
> > > >
> > > >
> > > > Yes definitely, I want the same. Feel free to let me know if this
> > > > does not suit with the OpenAMP project.
> > > >
> > > > Thanks,
> > > > Beleswar
> > > >
> > > > >
> > > > > Thanks,
> > > > > Arnaud
> > > > >
> > > > >
> > > > > > So Linux does not need to send the port idx everytime while
> > > > > > sending a gpio message anymore.
> > > > > >
> > > > > > Thanks,
> > > > > > Beleswar
> > > > > >
> > > > > > [...]
> > > > > >
> > > > >
> > >


^ permalink raw reply

* Re: [PATCH v2] drivers: altera_edac: Guard SDRAM irq2 retrieval for Arria10 only
From: Dinh Nguyen @ 2026-05-14 17:23 UTC (permalink / raw)
  To: muhammad.nazim.amirul.nazle.asmade, bp, tony.luck
  Cc: linux-edac, linux-arm-kernel, linux-kernel
In-Reply-To: <20260514034007.11541-1-muhammad.nazim.amirul.nazle.asmade@altera.com>



On 5/13/26 22:40, muhammad.nazim.amirul.nazle.asmade@altera.com wrote:
> From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
> 
> Guard the irq2 retrieval with an of_machine_is_compatible() check so
> that platform_get_irq(pdev, 1) is only called on Arria10 platforms.
> 
> Signed-off-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
> ---
> v2: Move irq2 = platform_get_irq(pdev, 1) inside the existing
>      of_machine_is_compatible("altr,socfpga-arria10") block instead of
>      adding a separate duplicate guard around it.
> ---


Please get into the habit of looking at previous commmits and their 
formatting.

This commit header should be:

EDAC/altera: Guard SDRAM irq2 retrieval for Arria10 only

Dinh



^ permalink raw reply

* Re: [PATCH] arm64: mm: drop redundant remap of FDT first page
From: Sang-Heon Jeon @ 2026-05-14 17:15 UTC (permalink / raw)
  To: catalin.marinas, will; +Cc: linux-arm-kernel
In-Reply-To: <20260513170101.1858213-1-ekffu200098@gmail.com>

On Thu, May 14, 2026 at 2:01 AM Sang-Heon Jeon <ekffu200098@gmail.com> wrote:
>
> fixmap_remap_fdt() calls create_mapping_noalloc() to map the first
> page of the FDT to read its magic and totalsize from the header. If
> the FDT does not fit in a single page, it calls create_mapping_noalloc()
> again to map the rest.
>
> The second mapping redundantly covers the first page that was just
> mapped by the first mapping.
>
> Start the second mapping at dt_phys_base + PAGE_SIZE so it only covers
> the pages that have not been mapped yet. No functional change.
>
> Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
> ---
> QEMU-based test results
>
> $ qemu-system-aarch64 -M virt -singlestep -d nochain,exec ...
>
> Count log lines from fixmap_remap_fdt() entry to return
> - entry PC : address of the <fixmap_remap_fdt> symbol
> - return PC : next address of each bl ... <fixmap_remap_fdt>
>
> 1) AS-IS
>   - 1st call (KERNEL) : 4935
>   - 2nd call (KERNEL_RO) : 14151
> 2) TO-BE
>   - 1st call : 4888
>   - 2nd call : 14104
>
> ---
> Hello,
>
> While looking into boot information, I found a minor cleanup point.
> If I misunderstood anything, please feel free to let me know.
>
> Thank you for taking valuable time to review this work.
>
> Best Regards,
> Sang-Heon Jeon
> ---
>  arch/arm64/mm/fixmap.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c
> index c5c5425791da..f8aea5572f7c 100644
> --- a/arch/arm64/mm/fixmap.c
> +++ b/arch/arm64/mm/fixmap.c
> @@ -167,8 +167,9 @@ void *__init fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
>                 return NULL;
>
>         if (offset + *size > PAGE_SIZE) {

Based on sashiko review [1], I made another patch [2].
Please check that patch as well. Thank you.

[1] https://sashiko.dev/#/patchset/20260513170101.1858213-1-ekffu200098%40gmail.com
[2] https://lore.kernel.org/all/20260514171304.2034930-1-ekffu200098@gmail.com/

Best Regards,
Sang-Heon Jeon



> -               create_mapping_noalloc(dt_phys_base, dt_virt_base,
> -                                      offset + *size, prot);
> +               create_mapping_noalloc(dt_phys_base + PAGE_SIZE,
> +                       dt_virt_base + PAGE_SIZE,
> +                       offset + *size - PAGE_SIZE, prot);
>         }
>
>         return dt_virt;
> --
> 2.43.0
>


^ permalink raw reply

* Re: [PATCH v5 1/3] firmware: smccc: coco: Manage arm-smccc platform device and CCA auxiliary drivers
From: Greg KH @ 2026-05-14 17:14 UTC (permalink / raw)
  To: Aneesh Kumar K.V
  Cc: Suzuki K Poulose, linux-coco, linux-arm-kernel, linux-kernel,
	Catalin Marinas, Jeremy Linton, Jonathan Cameron,
	Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Will Deacon,
	Steven Price
In-Reply-To: <yq5alddm5a6w.fsf@kernel.org>

On Thu, May 14, 2026 at 08:07:27PM +0530, Aneesh Kumar K.V wrote:
> Greg KH <gregkh@linuxfoundation.org> writes:
> 
> > On Thu, May 14, 2026 at 12:04:13PM +0100, Suzuki K Poulose wrote:
> >> Hi Aneesh
> >> 
> >> On 14/05/2026 10:40, Aneesh Kumar K.V (Arm) wrote:
> >> > Make the SMCCC driver responsible for registering the arm-smccc platform
> >> > device and after confirming the relevant SMCCC function IDs, create
> >> > the arm_cca_guest auxiliary device.
> >> > 
> >> 
> >> There are a few changes squashed in to this patch. Please could we
> >> split the patch in the following order ?
> >> 
> >> 1. Add platform device for arm-smccc
> >
> > Do not make any more "fake" platform devices please.
> >
> >> 2. Move TRNG to Auxilliary Device - (Even though it is a later patch, move
> >> it before the RSI changes)
> >
> > No, move it to the faux api please.
> >
> 
> 
> Maybe I was not complete in my previous reply. I did not want to repeat
> the entire thread, so I quoted the lore link for more details.
> 
> 1. We have platform firmware-provided SMCCC interfaces. Based on the
> support/availability of these function IDs, we want to load multiple
> drivers.
> 2. This patch series adds a platform device to represent the
> firmware-provided SMCCC resource.
> 3. Different SMCCC ranges are now represented as auxiliary devices.
> 4. Different subsystems, such as TSM, can autoload their backend drivers
> based on the availability of these SMCCC ranges, which are now
> represented as auxiliary devices.
> 
> You had agreed to all of this in the previous discussion here:
> https://lore.kernel.org/all/2025101516-handbook-hyphen-62ec@gregkh

Then why did someone say "this is a fake platform device with no actual
resources"?  That's what I was triggering off of.

Again, if you have actual platform resources, GREAT, use a platform
device and aux.  If you do not, then do NOT use a platform device.

totally confused,

greg k-h


^ permalink raw reply

* Re: [PATCH v5 1/3] firmware: smccc: coco: Manage arm-smccc platform device and CCA auxiliary drivers
From: Greg KH @ 2026-05-14 17:13 UTC (permalink / raw)
  To: Aneesh Kumar K.V
  Cc: Catalin Marinas, Suzuki K Poulose, linux-coco, linux-arm-kernel,
	linux-kernel, Jeremy Linton, Jonathan Cameron, Lorenzo Pieralisi,
	Mark Rutland, Sudeep Holla, Will Deacon, Steven Price
In-Reply-To: <yq5ajyt65a5y.fsf@kernel.org>

On Thu, May 14, 2026 at 08:08:01PM +0530, Aneesh Kumar K.V wrote:
> Catalin Marinas <catalin.marinas@arm.com> writes:
> 
> > On Thu, May 14, 2026 at 02:55:48PM +0200, Greg Kroah-Hartman wrote:
> >> On Thu, May 14, 2026 at 12:04:13PM +0100, Suzuki K Poulose wrote:
> >> > On 14/05/2026 10:40, Aneesh Kumar K.V (Arm) wrote:
> >> > > Make the SMCCC driver responsible for registering the arm-smccc platform
> >> > > device and after confirming the relevant SMCCC function IDs, create
> >> > > the arm_cca_guest auxiliary device.
> >> > > 
> >> > 
> >> > There are a few changes squashed in to this patch. Please could we
> >> > split the patch in the following order ?
> >> > 
> >> > 1. Add platform device for arm-smccc
> >> 
> >> Do not make any more "fake" platform devices please.
> >> 
> >> > 2. Move TRNG to Auxilliary Device - (Even though it is a later patch, move
> >> > it before the RSI changes)
> >> 
> >> No, move it to the faux api please.
> >
> > So should we end up with:
> >
> >   /sys/devices/faux/arm-smccc/
> >     smccc_trng/
> >     arm-rsi-dev/
> >       tsm/tsm0
> >
> >   /sys/class/tsm/tsm0
> >     -> ../../devices/faux/arm-smccc/arm-rsi-dev/tsm/tsm0
> >
> >   /sys/firmware/cca/
> >     realm_guest
> 
> But we need the ability to autoload different TSM backend drivers based
> on the support/availability of these SMCCC function-id ranges. faux
> device don't support that.

If you really need to "autoload" things, then do it like any other
normal bus or class does this, and send the proper uevents as needed.
Don't abuse the auxbus code for this please!

thanks,

greg k-h


^ permalink raw reply

* [PATCH] arm64: mm: use u32 for FDT size in fixmap_remap_fdt()
From: Sang-Heon Jeon @ 2026-05-14 17:13 UTC (permalink / raw)
  To: catalin.marinas, will; +Cc: linux-arm-kernel, Sang-Heon Jeon

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;
 	void *dt_virt;
 
 	/*
-- 
2.43.0



^ permalink raw reply related

* Re: [PATCH v5 1/3] firmware: smccc: coco: Manage arm-smccc platform device and CCA auxiliary drivers
From: Catalin Marinas @ 2026-05-14 17:10 UTC (permalink / raw)
  To: Aneesh Kumar K.V
  Cc: Greg KH, Suzuki K Poulose, linux-coco, linux-arm-kernel,
	linux-kernel, Jeremy Linton, Jonathan Cameron, Lorenzo Pieralisi,
	Mark Rutland, Sudeep Holla, Will Deacon, Steven Price
In-Reply-To: <yq5ajyt65a5y.fsf@kernel.org>

On Thu, May 14, 2026 at 08:08:01PM +0530, Aneesh Kumar K.V wrote:
> Catalin Marinas <catalin.marinas@arm.com> writes:
> > On Thu, May 14, 2026 at 02:55:48PM +0200, Greg Kroah-Hartman wrote:
> >> On Thu, May 14, 2026 at 12:04:13PM +0100, Suzuki K Poulose wrote:
> >> > On 14/05/2026 10:40, Aneesh Kumar K.V (Arm) wrote:
> >> > > Make the SMCCC driver responsible for registering the arm-smccc platform
> >> > > device and after confirming the relevant SMCCC function IDs, create
> >> > > the arm_cca_guest auxiliary device.
> >> > > 
> >> > 
> >> > There are a few changes squashed in to this patch. Please could we
> >> > split the patch in the following order ?
> >> > 
> >> > 1. Add platform device for arm-smccc
> >> 
> >> Do not make any more "fake" platform devices please.
> >> 
> >> > 2. Move TRNG to Auxilliary Device - (Even though it is a later patch, move
> >> > it before the RSI changes)
> >> 
> >> No, move it to the faux api please.
> >
> > So should we end up with:
> >
> >   /sys/devices/faux/arm-smccc/
> >     smccc_trng/
> >     arm-rsi-dev/
> >       tsm/tsm0
> >
> >   /sys/class/tsm/tsm0
> >     -> ../../devices/faux/arm-smccc/arm-rsi-dev/tsm/tsm0
> >
> >   /sys/firmware/cca/
> >     realm_guest
> 
> But we need the ability to autoload different TSM backend drivers based
> on the support/availability of these SMCCC function-id ranges. faux
> device don't support that.

It breaks this but can we not have some systemd rule that checks
/sys/firmware/cca/realm_guest and modprobes arm_cca_guest?

Alternatively, we could do a request_module("arm_cca_guest") if
RSI is available when we check it in smccc_devices_init(). Or make it
even fancier with a request_module("arm-smccc-service-...") (some ID
range while arm-cca-guest.c has a corresponding MODULE_ALIAS() for that
SMCCC range.

-- 
Catalin


^ permalink raw reply

* Re: [PATCH v7 0/3] ARM: omap1: use real firmware node lookup for GPIOs on Nokia 770
From: Aaro Koskinen @ 2026-05-14 17:09 UTC (permalink / raw)
  To: Andreas Kemnade
  Cc: Bartosz Golaszewski, Bartosz Golaszewski, Greg Kroah-Hartman,
	Rafael J. Wysocki, Danilo Krummrich, Andy Shevchenko,
	Daniel Scally, Heikki Krogerus, Sakari Ailus, Janusz Krzysztofik,
	Tony Lindgren, Russell King, Dmitry Torokhov, Kevin Hilman,
	Arnd Bergmann, driver-core, linux-kernel, linux-acpi,
	linux-arm-kernel, linux-omap
In-Reply-To: <20260513145926.2dc4d037@kemnade.info>

Hi,

On Wed, May 13, 2026 at 02:59:26PM +0200, Andreas Kemnade wrote:
> On Mon, 11 May 2026 15:34:39 +0200
> Bartosz Golaszewski <brgl@kernel.org> wrote:
> > > This converts Nokia 770 to using real firmware node lookup for GPIOs by
> > > attaching the software nodes describing GPIO controllers to their target
> > > devices.
> > >
> > > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> > 
> > Hi!
> > 
> > Gentle ping, can this be queued now for v7.2?
> > 
> So any objections from your side, Aaro?

It's fine.

Acked-by: Aaro Koskinen <aaro.koskinen@iki.fi>

A.


^ permalink raw reply

* Re: [PATCH v8 next 04/10] arm_mpam: Refactor rmid to reqPARTID/PMG mapping
From: James Morse @ 2026-05-14 17:07 UTC (permalink / raw)
  To: Zeng Heng, ben.horgan, Dave.Martin, tan.shaopeng, reinette.chatre,
	fenghuay, tglx, will, hpa, bp, babu.moger, dave.hansen, mingo,
	tony.luck, gshan, catalin.marinas
  Cc: linux-arm-kernel, x86, linux-kernel, wangkefeng.wang
In-Reply-To: <20260413085405.1166412-5-zengheng4@huawei.com>

Hi Zeng,

On 13/04/2026 09:53, Zeng Heng wrote:
> The Narrow-PARTID feature allows the MPAM driver to statically or
> dynamically allocate request PARTIDs (reqPARTIDs) to internal

(I think we should leave anything dynamic here for the further future,
 lets get static partitioning working first)


> PARTIDs (intPARTIDs). This enables expanding the number of monitoring
> groups beyond the hardware PMG limit.

> For systems with mixed MSCs (Memory System Components), MSCs that do
> not support Narrow-PARTID use PARTIDs exceeding the minimum number of
> intPARTIDs as reqPARTIDs to expand monitoring groups.
> 
> Expand RMID to include reqPARTID information:
> 
>   RMID = reqPARTID * NUM_PMG + PMG
> 
> To maintain compatibility with the existing resctrl layer, reqPARTIDs
> are allocated statically with a linear mapping to intPARTIDs via
> req2intpartid().
> 
> Mapping relationships (n = intPARTID count, m = reqPARTIDs per intPARTID):
> 
> P - Partition group
> M - Monitoring group
> 
> Group  closid rmid.reqPARTID  MSCs w/ Narrow-PARTID  MSCs w/o Narrow-PARTID
> P1     0                      intPARTID_1            PARTID_1
> M1_1   0      0               ├── reqPARTID_1_1      ├── PARTID_1
> M1_2   0      0+n             ├── reqPARTID_1_2      ├── PARTID_1_2
> M1_3   0      0+n*2           ├── reqPARTID_1_3      ├── PARTID_1_3
> ...                           ├── ...                ├── ...
> M1_m   0      0+n*(m-1)       └── reqPARTID_1_m      └── PARTID_1_m
> 
> P2     1                      intPARTID_2            PARTID_2
> M2_1   1      1               ├── reqPARTID_2_1      ├── PARTID_2
> M2_2   1      1+n             ├── reqPARTID_2_2      ├── PARTID_2_2
> M2_3   1      1+n*2           ├── reqPARTID_2_3      ├── PARTID_2_3
> ...                           ├── ...                ├── ...
> M2_m   1      1+n*(m-1)       └── reqPARTID_2_m      └── PARTID_2_m
> 
> Pn     n-1                    intPARTID_n            PARTID_n
> Mn_1   n-1    n-1             ├── reqPARTID_n_1      ├── PARTID_n
> Mn_2   n-1    n-1+n           ├── reqPARTID_n_2      ├── PARTID_n_2
> Mn_3   n-1    n-1+n*2         ├── reqPARTID_n_3      ├── PARTID_n_3
> ...                           ├── ...                ├── ...
> Mn_m   n-1    n*m-1           └── reqPARTID_n_m      └── PARTID_n_m

This table doesn't appear to say anything - you've got 'req' in the column
with narrowing .. that's about it.

Having an example is good, but I think it needs actual example values.
e.g.

my_control_group has CLOSID 0x8 using RMID 0.
It has two monitor groups with RMID 1 and 2.

mpam_partid_closid_shift is set to 1.

my_control_group uses two PARTID 0x10 and 0x11, both with PMG 0.
One monitor group uses PARTID 0x10 and PMG 1, the other uses PARTID 0x11
and PMG 1.


> Refactor the glue layer between resctrl abstractions (rmid) and MPAM
> hardware registers (reqPARTID/PMG) to support Narrow-PARTID. The resctrl
> layer uses rmid2reqpartid() and rmid2pmg() to extract components from
> rmid. The closid-to-intPARTID translation remains unchanged via
> resctrl_get_config_index().
> 
> Since Narrow-PARTID is a monitoring enhancement,

Please don't imply this is what the narrowing feature is for! We're abusing it.
The evidence its abuse is this breaks all the non-aliasing controls, meaning we
have to get rid of them.


> reqPARTID is only
> used in monitoring paths while configuration paths maintain the original
> semantics of closid.

I can't work out what this means. 'reqPARTID' is a term the architecture only uses
in the context of narrowing, which doesn't apply to monitors. Controls need to either
use the intPARTID or the set of PARTID. Monitors always need to use the set of PARTID.

I don't think we should use the terms intPARTID or reqPARTID everywhere - the spec
doesn't, and this thing is an optional feature.


> diff --git a/arch/arm64/include/asm/mpam.h b/arch/arm64/include/asm/mpam.h
> index 70d396e7b6da..40d60b0ab0fd 100644
> --- a/arch/arm64/include/asm/mpam.h
> +++ b/arch/arm64/include/asm/mpam.h

It shouldn't be necesary to touch the arch code's header file!


> @@ -63,6 +63,15 @@ static inline void mpam_set_task_partid_pmg(struct task_struct *tsk,
>  	WRITE_ONCE(task_thread_info(tsk)->mpam_partid_pmg, regval);
>  }
>  
> +u16 req2intpartid(u16 reqpartid);

Please don't add a dependency on something in a driver in the context-switch path.
This stuff needs to be standalone.


> +static inline u16 mpam_get_regval_partid(u64 regval)
> +{
> +	u16 reqpartid = (regval & MPAMSM_EL1_PARTID_D_MASK) >> MPAMSM_EL1_PARTID_D_SHIFT;
> +
> +	return req2intpartid(reqpartid);
> +}
> +
>  static inline void mpam_thread_switch(struct task_struct *tsk)
>  {
>  	u64 oldregval;
> @@ -72,7 +81,8 @@ static inline void mpam_thread_switch(struct task_struct *tsk)
>  	if (!static_branch_likely(&mpam_enabled))
>  		return;
>  
> -	if (regval == READ_ONCE(arm64_mpam_global_default))
> +	if (regval == READ_ONCE(arm64_mpam_global_default) ||
> +	   !mpam_get_regval_partid(regval))
>  		regval = READ_ONCE(per_cpu(arm64_mpam_default, cpu));
>  
>  	oldregval = READ_ONCE(per_cpu(arm64_mpam_current, cpu));

Why can't the resctrl glue code mess with the PARTID value for task using the existing
arch<->MPAM API? resctrl_arch_set_closid_rmid() already provides arbitrary values.
Please fix them up before they get stuffed in struct thread_info.


> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
> index 56859f354efa..9d0a7a4dffd1 100644
> --- a/drivers/resctrl/mpam_resctrl.c
> +++ b/drivers/resctrl/mpam_resctrl.c
> @@ -303,15 +303,60 @@ u32 resctrl_arch_system_num_rmid_idx(void)
>  	return (mpam_pmg_max + 1) * get_num_reqpartid();
>  }
>  
> +static u16 rmid2reqpartid(u32 rmid)

Surely you need the CLOSID as well to generate something you are going to use as a PARTID.
How can this work if you have multiple control groups?


> +{
> +	rmid /= (mpam_pmg_max + 1);
> +
> +	if (cdp_enabled)
> +		return resctrl_get_config_index(rmid, CDP_DATA);
> +
> +	return resctrl_get_config_index(rmid, CDP_NONE);
> +}
> +
> +static u8 rmid2pmg(u32 rmid)
> +{
> +	return rmid % (mpam_pmg_max + 1);
> +}
> +
> +u16 req2intpartid(u16 reqpartid)
> +{
> +	return reqpartid % (mpam_intpartid_max + 1);
> +}

As before, I'd prefer we don't call everything intPARTID or reqPARTID - not every
platform has narrowing. This makes it harder to think about the simpler platforms.

'mpam_intpartid_max' shouldn't exist as a global property from the mpam_devices
code - but it should be a mask chosen by the resctrl glue code at setup time.

Something like this psuedocode:
--------%<--------
u64 mpam_partid_closid_shift;

static partid_set_idx_t convert_closid_any_rmid_cdp_safe(struct mpam_resctrl_res *res,
							 enum resctrl_conf_type cdp_type,
							 u32 closid)
{
	int i;
	u16 partid_base;
	partid_set_idx_t partid_set = { 0 };
	u16 num_groups = 1 << mpam_partid_closid_shift;

	if (mpam_resctrl_hide_cdp(r->rid))
		cdp_type = CDP_CODE;

	partid_base = resctrl_get_config_index(closid, cdp_type);
	partid_base <<= mpam_partid_closid_shift;

	if (res->using_narrowing) {
		u16 intpartid = closid;
		__set_bit(intpartid, partid_set);
		return partid_set;
	}

	for (i = 0; i < num_groups; i++)
		__set_bit(partid_base + i, partid_set);

	return partid_set;
}


static partid_set_idx_t mpam_resctrl_convert_closid_any_rmid(struct mpam_resctrl_res *res,
							 enum resctrl_conf_type cdp_type,
							 u32 closid)
{
	int i;
	u16 partid_base;
	partid_set_idx_t partid_set = { 0 };
	u16 num_groups = 1 << mpam_partid_closid_shift;

	if (mpam_resctrl_hide_cdp(r->rid))
		cdp_type = CDP_CODE;
	partid_set = mpam_resctrl_convert_closid_any_rmid_cdp_safe(res, cdp_type, closid);

	if (mpam_resctrl_hide_cdp(r->rid)) {
		cdp_type = CDP_DATA;
		partid_set |= mpam_resctrl_convert_closid_any_rmid_cdp_safe(res, cdp_type, closid);
	}

	return partid_set;
}
--------%<--------

This is pretending we can deal with a set of PARTID as a bitmap - which might not work
well if we have to allocate memory all over the place. The table description I put in the
cover-letter is an alternative - pointing at a pre-computed set: but that probably won't
work well for CDP. A hybrid of the two might be the something to try.

The reason I prefer this is CDP and narrowing become a subset of the same problem: dealing
with a set of PARTID. This function ends up complicated, but its callers all use it in the
same way - and can ignore CDP and the narrowing support is simple. e.g:

--------%<--------
	if (res->using_narrowing) {
		mpam_set_feature(mpam_feat_narrowing, &cfg);
--------%<--------


> +/*
> + * To avoid the reuse of rmid across multiple control groups, check
> + * the incoming closid to prevent rmid from being reallocated by
> + * resctrl_find_free_rmid().
> + *
> + * If the closid and rmid do not match upon inspection, immediately
> + * returns an invalid rmid. A valid rmid must not exceed 24 bits.
> + */

This will cause an out of range set_bit() in add_rmid_to_limbo().
This function must accept the CLOSID/RMID range it advertised to resctrl.

Can you expand on the problem here?


I suspect its because in systems doing this you've accidentally decoupled the
RMID from CLOSID, meaning CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID should be false.

We might want to do this decoupling as part of making this something that resctrl
can trigger dynamically. (e.g. rescrl_arch_grow_closid() that allocates another PARTID
behind the scenes). But this would need resctrl changes - at least to make the above
KConfig something that can be changed at runtime.

I'd prefer we get the static grouping working first, before we work out what needs
changing in resctrl to do it dynamically.


>  u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid)
>  {
> -	return closid * (mpam_pmg_max + 1) + rmid;
> +	u32 reqpartid = rmid2reqpartid(rmid);
> +	u32 intpartid = req2intpartid(reqpartid);
> +
> +	if (cdp_enabled)
> +		intpartid >>= 1;
> +
> +	if (closid != intpartid)
> +		return U32_MAX;

This will cause out of range accesses. This function must accept the full range
of CLOSID/RMID that were advertised to resctrl. It can't return an error.


> +	return rmid;
>  }
>  
>  void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid)
>  {
> -	*closid = idx / (mpam_pmg_max + 1);
> -	*rmid = idx % (mpam_pmg_max + 1);
> +	u32 reqpartid = rmid2reqpartid(idx);
> +	u32 intpartid = req2intpartid(reqpartid);
> +
> +	if (rmid)
> +		*rmid = idx;
> +	if (closid) {
> +		if (cdp_enabled)
> +			intpartid >>= 1;
> +		*closid = intpartid;
> +	}
>  }

These idx encode/decode would remain simple if they worked on a mask/shift
that was calculated at setup time. Currently that is all hidden behind
your helpers.

We shouldn't have to deal with CDP in here because the 'idx' is for resctrl's
monitoring code - which can't monitor the two halfs of CDP separately. That's an mpam-ism.


>  void resctrl_arch_sched_in(struct task_struct *tsk)
> @@ -323,21 +368,17 @@ void resctrl_arch_sched_in(struct task_struct *tsk)
>  
>  void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid)
>  {
> -	WARN_ON_ONCE(closid > U16_MAX);
> -	WARN_ON_ONCE(rmid > U8_MAX);
> +	u32 reqpartid = rmid2reqpartid(rmid);
> +	u8 pmg = rmid2pmg(rmid);
>  
> -	if (!cdp_enabled) {
> -		mpam_set_cpu_defaults(cpu, closid, closid, rmid, rmid);
> -	} else {
> +	if (!cdp_enabled)
> +		mpam_set_cpu_defaults(cpu, reqpartid, reqpartid, pmg, pmg);
> +	else
>  		/*
>  		 * When CDP is enabled, resctrl halves the closid range and we
>  		 * use odd/even partid for one closid.
>  		 */
> -		u32 partid_d = resctrl_get_config_index(closid, CDP_DATA);
> -		u32 partid_i = resctrl_get_config_index(closid, CDP_CODE);
> -
> -		mpam_set_cpu_defaults(cpu, partid_d, partid_i, rmid, rmid);
> -	}
> +		mpam_set_cpu_defaults(cpu, reqpartid, reqpartid + 1, pmg, pmg);
>  }

Please don't '+1' the parameters like this. How do we know these are the right way
round? What if resctrl_get_config_index() chagnes which way round they are?

We should try and make the code easy to review and maintain.
Optimising things like this is for the compiler.


I'd like it to be clear from this function that one of the set of PARTID is being
picked. I think this falls out of the (hidden) shifting here, but its not at all
obivious.

You completely discard the PARTID here. I don't think that works if you have multiple
control groups.

[snip]

> @@ -478,6 +518,7 @@ static int __read_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_c
>  		      enum resctrl_conf_type cdp_type, u32 closid, u32 rmid, u64 *val)
>  {
>  	struct mon_cfg cfg;
> +	u32 reqpartid = rmid2reqpartid(rmid);
>  
>  	if (!mpam_is_enabled())
>  		return -EINVAL;
> @@ -493,8 +534,8 @@ static int __read_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_c
>  	cfg = (struct mon_cfg) {
>  		.mon = mon_idx,
>  		.match_pmg = true,
> -		.partid = closid,
> -		.pmg = rmid,
> +		.partid = (cdp_type == CDP_CODE) ? reqpartid + 1 : reqpartid,
> +		.pmg = rmid2pmg(rmid),

Not using the CLOSID here breaks multiple control groups.

>  	};
>  
>  	return mpam_msmon_read(mon_comp, &cfg, mon_type, val);


James


^ permalink raw reply

* Re: [PATCH v8 next 03/10] arm_mpam: Disable reqPARTID expansion when Narrow-PARTID is unavailable
From: James Morse @ 2026-05-14 17:06 UTC (permalink / raw)
  To: Zeng Heng, ben.horgan, Dave.Martin, tan.shaopeng, reinette.chatre,
	fenghuay, tglx, will, hpa, bp, babu.moger, dave.hansen, mingo,
	tony.luck, gshan, catalin.marinas
  Cc: linux-arm-kernel, x86, linux-kernel, wangkefeng.wang
In-Reply-To: <20260413085405.1166412-4-zengheng4@huawei.com>

Hi Zeng,

On 13/04/2026 09:53, Zeng Heng wrote:
> MPAM supports heterogeneous systems where some type of MSCs may implement
> Narrow-PARTID while others do not. However, when an MSC uses
> percentage-based throttling (non-bitmap partition control) and lacks
> Narrow-PARTID support, resctrl cannot correctly apply control group
> configurations across multiple PARTIDs.
> 
> To enable free assignment of multiple reqPARTIDs to resource control
> groups, all MSCs used by resctrl must either: Implement Narrow-PARTID,
> allowing explicit PARTID remapping, or only have stateless resource
> controls (non-percentage-based), such that splitting a control group
> across multiple PARTIDs does not affect behavior.

I prefer Dave's terminology for this: aliasing and non-aliasing. It implies
there are two controls, which stateless does not.


> The detection occurs at initialization time on the first call to
> get_num_reqpartid() from update_rmid_limits(). This call is guaranteed
> to occur after mpam_resctrl_pick_{mba,caches}() have set up the
> resource classes, ensuring the necessary properties are available
> for the Narrow-PARTID capability check.
> 
> When an MSC with percentage-based control lacks Narrow-PARTID support,
> get_num_reqpartid() falls back to returning the number of intPARTIDs,
> effectively disabling the reqPARTID expansion for monitoring groups.

No MSC has percentage based controls - that's an x86ism. The MSCs have
fixed point fractions, bitmaps or a cost/weight.


I think you're thinking about this the wrong way up - we should only enable
this on a small number of platforms that don't have any controls we'd have to discard.
(hopefully yours is such a platform!)

I don't think this should be added to resctrl_arch_system_num_rmid_idx(). Please make
this decision for resctrl at mpam_resctrl_setup() time.


> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
> index 5f4364c8101a..56859f354efa 100644
> --- a/drivers/resctrl/mpam_resctrl.c
> +++ b/drivers/resctrl/mpam_resctrl.c
> @@ -257,9 +257,50 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored)
>  	return mpam_intpartid_max + 1;
>  }
>  
> +/*
> + * Determine the effective number of PARTIDs available for resctrl.
> + *
> + * This function performs a one-time check to determine if Narrow-PARTID
> + * can be used. It must be called after mpam_resctrl_pick_{mba,caches}()
> + * have initialized the resource classes, as class properties are used
> + * to detect Narrow-PARTID support.

> + * The first call occurs in update_rmid_limits(), ensuring the
> + * prerequisite initialization is complete.

This is fragile to changes in the order resctrl makes these calls. We need these
properties to be fixed before we call resctrl_init().

(yes - I think CDP is fragile too!)


> + */
> +static u32 get_num_reqpartid(void)
> +{
> +	struct mpam_resctrl_res *res;
> +	struct mpam_props *cprops;
> +	static bool first = true;
> +	int rid;
> +
> +	if (first) {
> +		for_each_mpam_resctrl_control(res, rid) {
> +			if (!res->class)
> +				continue;
> +
> +			cprops = &res->class->props;
> +			if (mpam_has_feature(mpam_feat_partid_nrw, cprops))
> +				continue;


> +			if (mpam_has_feature(mpam_feat_mbw_max, cprops) ||
> +			    mpam_has_feature(mpam_feat_mbw_min, cprops) ||
> +			    mpam_has_feature(mpam_feat_cmax_cmax, cprops) ||
> +			    mpam_has_feature(mpam_feat_cmax_cmin, cprops)) {

Please make this a helper in mpam_internal.h with 'controls' and 'aliasing' in its name.
(maybe has_aliasing_controls()).

What about the priority for PRI and the proportional-stride?

I don't think proportional-stride aliases properly: if I have groups with stride 1 and 2,
I can't add a second '2' without decreasing the first groups stride from 1/3 to 1/5. If I
halve the second groups, they each get half the bandwidth instead of sharing it.

Can you check whether the priority for PRI aliases?


> +				mpam_partid_max = mpam_intpartid_max;
> +				break;
> +			}
> +		}
> +	}
> +
> +	first = false;
> +	return mpam_partid_max + 1;
> +}
> +
>  u32 resctrl_arch_system_num_rmid_idx(void)
>  {
> -	return (mpam_pmg_max + 1) * (mpam_partid_max + 1);
> +	return (mpam_pmg_max + 1) * get_num_reqpartid();
>  }


Thanks,

James


^ permalink raw reply

* Re: [PATCH v8 next 02/10] arm_mpam: Add intPARTID and reqPARTID support for Narrow-PARTID feature
From: James Morse @ 2026-05-14 17:06 UTC (permalink / raw)
  To: Zeng Heng, ben.horgan, Dave.Martin, tan.shaopeng, reinette.chatre,
	fenghuay, tglx, will, hpa, bp, babu.moger, dave.hansen, mingo,
	tony.luck, gshan, catalin.marinas
  Cc: linux-arm-kernel, x86, linux-kernel, wangkefeng.wang
In-Reply-To: <20260413085405.1166412-3-zengheng4@huawei.com>

Hi Zeng,

On 13/04/2026 09:53, Zeng Heng wrote:
> Introduce Narrow-PARTID (partid_nrw) feature support, which enables
> many-to-one mapping of request PARTIDs (reqPARTID) to internal PARTIDs
> (intPARTID). This expands monitoring capability by allowing a single
> control group to track more task types through multiple reqPARTIDs
> per intPARTID, bypassing the PMG limit in some extent.
> 
> intPARTID: Internal PARTID used for control group configuration.
> Configurations are synchronized to all reqPARTIDs mapped to the same
> intPARTID. Count is indicated by MPAMF_PARTID_NRW_IDR.INTPARTID_MAX, or
> defaults to PARTID count if Narrow-PARTID is unsupported.
> 
> reqPARTID: Request PARTID used to expand monitoring groups. Enables
> a single control group to monitor more task types by multiple reqPARTIDs
> within one intPARTID, overcoming the PMG count limitation.
> 
> For systems with homogeneous MSCs (all supporting Narrow-PARTID), the
> driver exposes the full reqPARTID range directly. For heterogeneous
> systems where some MSCs lack Narrow-PARTID support, the driver utilizes
> PARTIDs beyond the intPARTID range as reqPARTIDs to expand monitoring
> capacity.
> 
> So, the numbers of control group and monitoring group are calculated as:
> 
>   n = min(intPARTID, PARTID)  /* the number of control groups */
>   l = min(reqPARTID, PARTID)  /* the number of monitoring groups */
>   m = l // n                  /* monitoring groups per control group */
> 
> Where:
> 
>   intPARTID: intPARTIDs on Narrow-PARTID-capable MSCs
>   reqPARTID: reqPARTIDs on Narrow-PARTID-capable MSCs
>   PARTID:    PARTIDs on non-Narrow-PARTID-capable MSCs
> 
> Example: L3 cache (256 PARTIDs, without Narrow-PARTID feature) +
>          MATA (32 intPARTIDs, 256 reqPARTIDs):
> 
>   n = min( 32, 256) =  32 intPARTIDs
>   l = min(256, 256) = 256 reqPARTIDs
>   m = 256 / 32 = 8 reqPARTIDs per intPARTID
> 
> Implementation notes:
>   * Handle mixed MSC systems (some support Narrow-PARTID, some don't) by
>     taking minimum number of intPARTIDs across all MSCs.
>   * resctrl_arch_get_num_closid() now returns the number of intPARTIDs
>     (was PARTID).

What you're doing here is making intPARTID the fundamental unit in MPAM. I
don't think we should do this as its not true in the architecture: narrowing
is a single, optional feature. We have platforms that don't support narrowing
at all - so having to think in terms of "what is the intPARTID limit on this
platform that doesn't have the feature" is confusing.
Narrowing doesn't affect the monitoring, so you can't just string-replace the
driver.

The resctrl glue code is going to have to know about narrowing as it must
either duplicate the control values for aliasing PARTID, or remap them using
narrowing.

I'd prefer it if the mpam_devices code exposed an API to make use of narrowing
that makes sense given the MPAM architecture. (e.g. narrowing is optional!)
Whetever resctrl needs should then be built on top of that.


Currently the MAX PARTID/PMG are dealt with separately as we need a global value
at the end. It was done separately as it could be a patch on its own, to try and
keep each patch reviewable.
But it should probably have been dealt with the same way we deal with all MSC
features - stash them in struct mpam_msc_ris at hw_probe time, and combine them
up to the class level handling different values with __props_mismatch().
The global state that includes the requestors can be created after that point.

I think we should do this now to add intpartid_max to struct mpam_props so that the
resctrl glue code can find the intpartid_max per class. I don't think it makes sense as
a global property. (we should move partid_max and pmg_max at the same time)

... I think moving partid_max would just be cleanup. The resctrl glue code needs to
know the maximum PARTID for monitoring, but I think this would always be the global
PARTID max value.


> diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
> index 41b14344b16f..cf067bf5092e 100644
> --- a/drivers/resctrl/mpam_devices.c
> +++ b/drivers/resctrl/mpam_devices.c
> @@ -63,6 +63,7 @@ static DEFINE_MUTEX(mpam_cpuhp_state_lock);
>   * Generating traffic outside this range will result in screaming interrupts.
>   */
>  u16 mpam_partid_max;
> +u16 mpam_intpartid_max;
>  u8 mpam_pmg_max;
>  static bool partid_max_init, partid_max_published;
>  static DEFINE_SPINLOCK(partid_max_lock);

The global properties are supposed to mean "if you generate any traffic outside
this range, you'll get an out of range error causing mpam_disable()".

This doesn't hold for intPARTID.

In my hypothetical system from the cover letter: {
  64 PARTID at the L3
  64 PARTID and narrowing to 16 at the SLC
  64 PARTID and narrowing to 32 at the memory-controller

  The resctrl glue code could ignore the SLC if it wanted to use 32 PARTID, and just
  duplicate the aliasing controls at L3. (and remove the non-aliasing controls)
}


> @@ -2743,9 +2749,13 @@ static void mpam_enable_once(void)
>  	mpam_register_cpuhp_callbacks(mpam_cpu_online, mpam_cpu_offline,
>  				      "mpam:online");
>  
> -	/* Use printk() to avoid the pr_fmt adding the function name. */
> -	printk(KERN_INFO "MPAM enabled with %u PARTIDs and %u PMGs\n",
> -	       mpam_partid_max + 1, mpam_pmg_max + 1);
> +	if (mpam_partid_max == mpam_intpartid_max)
> +		/* Use printk() to avoid the pr_fmt adding the function name. */
> +		printk(KERN_INFO "MPAM enabled with %u PARTIDs and %u PMGs\n",
> +		       mpam_partid_max + 1, mpam_pmg_max + 1);
> +	else
> +		printk(KERN_INFO "MPAM enabled with %u reqPARTIDs, %u intPARTIDs and %u PMGs\n",
> +		       mpam_partid_max + 1, mpam_intpartid_max + 1, mpam_pmg_max + 1);

intPARTID is not a global property. It's also an optional feature, so its problematic
to print this on platforms that don't have the feature.


>  }
>  
>  static void mpam_reset_component_locked(struct mpam_component *comp)
>  
>  u32 resctrl_arch_system_num_rmid_idx(void)


Thanks,

James


^ permalink raw reply

* Re: [PATCH v8 next 01/10] fs/resctrl: Fix MPAM Partid parsing errors by preserving CDP state during umount
From: James Morse @ 2026-05-14 17:06 UTC (permalink / raw)
  To: Zeng Heng, ben.horgan, Dave.Martin, tan.shaopeng, reinette.chatre,
	fenghuay, tglx, will, hpa, bp, babu.moger, dave.hansen, mingo,
	tony.luck, gshan, catalin.marinas
  Cc: linux-arm-kernel, x86, linux-kernel, wangkefeng.wang
In-Reply-To: <20260413085405.1166412-2-zengheng4@huawei.com>

Hi Zeng,

I think this should be a separate patch as its fixing a problem not adding a feature. It's
not actually relevant to the rest of the series.

On 13/04/2026 09:53, Zeng Heng wrote:
> This patch fixes a pre-existing issue in the resctrl filesystem teardown
> sequence where premature clearing of cdp_enabled could lead to MPAM Partid
> parsing errors.

resctrl changes need to go via tip, which has a bunch of rules about commit messages,
see Documentation/process/maintainer-tip.rst

You end up with a structure describing the current state, e.g:
| When resctrl is umounted it disables CDP,

what the problem is, e.g:
| CLOSID remain in the limbo list, and the mbm monitors continue to be read
| after umount. MPAM changes the meaning of CLOSID when CDP is enabled/disabled,
| resulting in out of bounds accesses.

Then, what you do about it, here you are:
| Throwing away the limbo list on umount.

(I don't suggest you take this wording - its just an example)

"this patch" is a phrase to avoid, acronyms like CLOSID need capitalising, etc.


> The closid to partid conversion logic inherently depends on the global
> cdp_enabled state. However, rdt_disable_ctx() clears this flag early in
> the umount path, while free_rmid() operations will reference after that.
> This creates a window where partid parsing operates with inconsistent CDP
> state, potentially makes monitor reads with wrong partid mapping.
> 
> Additionally, rmid_entry remaining in limbo between mount sessions may
> trigger potential partid out-of-range errors, leading to MPAM fault
> interrupts and subsequent MPAM disablement.

Can you give more details on this. I assume its going from CDP-disable to
enabled, means MPAM doubles the CLOSID from the stale limbo list, making it
out of range.


> Reorder rdt_kill_sb() to delay rdt_disable_ctx() until after
> rmdir_all_sub() and resctrl_fs_teardown() complete. This ensures
> all rmid-related operations finish with correct CDP state.


> Introduce rdt_flush_limbo() to flush and cancel limbo work before the
> filesystem teardown completes.

So, discard the state in the hope we don't need it again.
What happens if the filesystem is mounted again quickly afterwards?
Surely we get noisy bandwidth results for ~minutes afterwards?


> An alternative approach would be to cancel limbo work on umount

Sounds like a move in the right direction - having bits of resctrl still
taking CPU time when its not in use is surprising.

I'd love to eventually remove the limbo worker and have the RMID alloc code
search the limbo list for a clean RMID when a control/monitor group is created.
By deferring the work as late as possible, we do less work overall.


> and restart it on remount with remaked bitmap.
> However, this would require substantial changes in the resctrl layer to
> handle CDP state transitions across mount sessions,

This would be necessary if the limbo timer was stopped on umount too.
It also covers cases where you kexec and re-mount resctrl.

I think this is a good idea. I agree its more work.


> which is beyond the
> scope of the reqpartid feature work this patchset focuses on.

Was it a mistake to include it in this series then?


> The current
> fix addresses the immediate correctness issue with minimal churn.

I'm not a fan of papering over problems in resctrl. Could we do it properly
by rebuilding the limbo list at mount time as you suggested above?



Thanks,

James


^ permalink raw reply

* Re: [PATCH v8 next 00/10] arm_mpam: Introduce Narrow-PARTID feature
From: James Morse @ 2026-05-14 17:06 UTC (permalink / raw)
  To: Zeng Heng, ben.horgan, Dave.Martin, tan.shaopeng, reinette.chatre,
	fenghuay, tglx, will, hpa, bp, babu.moger, dave.hansen, mingo,
	tony.luck, gshan, catalin.marinas
  Cc: linux-arm-kernel, x86, linux-kernel, wangkefeng.wang
In-Reply-To: <20260413085405.1166412-1-zengheng4@huawei.com>

Hi Zeng,

(beware this is the first version I've seen - arm have been silently deleting your mail,
 it looks like a problem with DKIM signatures)

On 13/04/2026 09:53, Zeng Heng wrote:
> Background
> ==========
> 
> On x86, the resctrl allows creating up to num_rmids monitoring groups
> under parent control group. However, ARM64 MPAM is currently limited by
> the PMG (Performance Monitoring Group) count, which is typically much
> smaller than the theoretical RMID limit.

The MPAM PMG limit is 255. Is that not enough?

I think the real problem is the CHI interconnect protocol is forcing people
to only have 1 bit of PMG - regardless of what the architecture says. This
isn't an MPAM problem as such - its an implementation issue.

(but we can try and work around it)


> This creates a significant
> scalability gap: users expecting fine-grained per-process or per-thread
> monitoring quickly exhaust the PMG space, even when plenty of reqPARTIDs
> remain available.

This is more about MPAM's philosophical stance that PMG extents PARTID, whereas
on x86 RMID is an independent number.

Please don't muddle these - it results in muddled patches!
If we want to try and attack both with narrowing, we should do them separately.


> The Narrow-PARTID feature, defined in the ARM MPAM architecture,
> addresses this by associating reqPARTIDs with intPARTIDs through a
> programmable many-to-one mapping. This allows the kernel to present more
> logical monitoring contexts.

I'd put this as "can be abused to avoid this problem"! We still have a problem with
controls that don't alias and need to be removed from MSC that don't support narrowing.
This isn't what the feature was designed for - but it is a really cool trick, it works
for some real platforms, and solves a problem seen in user-space.

However - throughout this series you seem to be discarding all the control-group support
for a monitoring-only setup that allocates intPARTID for everything. This might work for
your use-case on your platform, but it doesn't generalise to platforms without narrowing
or where multiple control-groups are needed.


> Design Overview
> ===============
> 
> The implementation extends the RMID encoding to carry reqPARTID
> information:
> 
>   RMID = reqPARTID * NUM_PMG + PMG
> 
> In this patchset, a monitoring group is uniquely identified by the
> combination of reqPARTID and PMG. The closid is represented by intPARTID,
> which is exactly the original PARTID.

The way I think of this is 'RMID' bits being spilled into PARTID. This
means each control group has a set of PARTID. For MSC using narrowing,
CLOSID would be the intPARTID value. But as you note, we need to support
mismatches:


> For systems with homogeneous MSCs (all supporting Narrow-PARTID), the
> driver exposes the full reqPARTID range directly. For heterogeneous
> systems where some MSCs lack Narrow-PARTID support, the driver utilizes
> PARTIDs beyond the intPARTID range as reqPARTIDs to expand monitoring
> capability. The sole exception is when any type of MSCs lack Narrow-PARTID
> support, their percentage-based control mechanism prevents the use of
> PARTIDs as reqPARTIDs.

It'd be good to have some discussion about what the interface between the
mpam_devices code and any other user (like resctrl) should be.

As a hypothetical system to think about:
  64 PARTID at the L3, which support CPOR and CCAP
  64 PARTID and narrowing to 16 at the SLC, which supoprts CPOR
  64 PARTID and narrowing to 32 at the memory-controller, which support MBWU_MAX

I think whether using intPARTID is a benefit needs to be user-space policy.
You've likely got a platform where that choice is obvious - but it is a
trade-off as you lose the non-aliasing controls. In the example above, using
narrowing on this system means losing the CCAP controls on L3 as they don't alias [*].
Where its a policy, its likely to be one policy for resctrl, and another for any other
user.
We can get the resctrl glue code to turn it on unconditionally if there is no trade off,
I think that means: no non-aliasing controls in any class that doesn't support narrowing
- including 'unknown'. (we couldn't add them to resctrl in the future if you already chose
to enable this).

As for the interface with mpam_devices:
I think this means the resctrl glue code needs to be able to discover which
classes support intPARTID, and how many controls they actually have. From there
it can apply to policy to determine whether its better to support fewer features
in resctrl to get more RMID. (the alternative is always to ignore the MSC with
narrowing - narrowing lets hardware lie about the features it supports).

Currently the resctrl glue code has to program a configuration for two PARTID
when CDP is being hidden on the MB resource. This is ugly and fragile. I'd like
to explore generalising it as this narrowing stuff will also need to apply a
configuration to a set of PARTID when that MSC doesn't support narrowing.
In the example above, we'd need to discard the CCAP controls and write the same
CPOR bitmap to each PARTID that is mapped together by narrowing.


I think this means the resctrl glue code will need to be able to write a configuration
to controls using the full partid_max range as it does today. But also be able to set
the narrowing mapping on classes that support it.
For the monitors, the resctrl glue code will need to allocate and configure a set of
monitors, and read and sum them. This will be regardless of whether narrowing is
supported.

I think this means allocating a table of CLOSID to PARTID(s). the intPARTID would
always match the CLOSID. Monitors and non-narrowing MSC would need to walk the list.
I'm hoping we can make CDP a subset of this problem.
Some clever arithmetic may save allocating memory for a table - but if we change resctrl
to do this dynamically, the numbers become arbitrary forcing it to be a table.
It might also be possible to support moving monitor-groups between control groups with
the table driven approach. (see what you think on how complex it ends up ...)

I'd like to keep that grouping static for now, the table needs creating at setup time,
(+/- CDP), to avoid problems like you've found with CDP. This means the intpartid mappings
can be written once at setup time.

I'd like to avoid exposing user ABI to control this until we get it working, then we can
talk about whether to try making the grouping dynamically managed by resctrl. (there were
some proposals in that area - but I can't find them on lore).
If there are platforms were its certainly not a trade-off, we can enable it
unconditionally - but I'm wary of this being "what we care about now", requiring user-abi
to enable features that were detectable.
e.g. we ignore an unknown MSC, and add a resctrl schema for it later - only we can't
expose it if we were using narrowing. Now its a trade-off.


> Capability Improvements
> =======================
> 
> --------------------------------------------------------------------------
> The maximum        |  Sub-monitoring groups            | System-wide
> number of          |  under a control group            | monitoring groups
> --------------------------------------------------------------------------
> Without reqPARTID  |  PMG                              | intPARTID * PMG
> --------------------------------------------------------------------------
> reqPARTID          |                                   |
> static allocation  | (reqPARTID // intPARTID) * PMG    | reqPARTID * PMG
> --------------------------------------------------------------------------
> reqPARTID          |                                   |
> dynamic allocation | (reqPARTID - intPARTID + 1) * PMG | reqPARTID * PMG
> --------------------------------------------------------------------------
> 
> Note: The number of intPARTIDs can be capped via the boot parameter
> mpam.intpartid_max. Under MPAM, reqPARTID count is always greater than
> or equal to intPARTID count.
> 
> Series Structure
> ================
> 
> Patch 1: Fix pre-existing out-of-range PARTID issue between mount sessions.
> Patches 2-6: Implement static reqPARTID allocation.
> Patches 7-10: Implement dynamic reqPARTID allocation.

I've had  a hard time following this series. You dive in with invasive changes, then
unbreak things in later patches.

Please added the needed infrastructure in mpam_devices.c first. This should be free of
resctrl-isms, and 'only' needs reviewing against the architecture.

Then add the resctrl glue code stuff. That needs to comply with what resctrl expects.

I think the cleanest way to think about this is to break the mapping between CLOSID and
PARTID. We're effectively moving bits of RMID out of PMG into PARTID. Adding helpers
to explicitly do this early in those patches will make your changes clearer.
Please avoid spraying the narrowing terms for things everywhere.


Thanks,

James


[*] It's terminology from discussing this with Dave, just in case a summary is needed:
  aliasing controls are like CPOR where two different PARTID with the same bitmap
  compete for the same resource. If you give them each the same 50% of the portions,
  they can't exceed that together.
  non-aliasing controls are like CCAP where to different PARTID with the same fraction
  compete for different resources. If you give them each 50% of the capacity, it adds
  up to 100%. You can't represent 'the same' 50% using these controls.

  Narrowing papers over this problem with its remapping table, which gives you a 'same'
  property. For MSC that have controls of that shape - and where more monitors are
  desired - we'd have to drop the controls.

  I think "more monitors are desired" is going to need to be user-space policy. But
  we can come back to how to do that later.



^ permalink raw reply

* Re: [PATCH] clk: samsung: exynos850: mark APM I3C clocks as critical
From: Krzysztof Kozlowski @ 2026-05-14 16:57 UTC (permalink / raw)
  To: Sam Protsenko, Sylwester Nawrocki, Chanwoo Choi, Alim Akhtar,
	Michael Turquette, Stephen Boyd, Alexey Klimov
  Cc: Tudor Ambarus, Brian Masney, linux-arm-kernel, linux-samsung-soc,
	linux-clk, linux-kernel
In-Reply-To: <20260430-exynos850-i3c-criticalclocks-v1-1-6e1fd8dfa21b@linaro.org>


On Thu, 30 Apr 2026 12:53:27 +0100, Alexey Klimov wrote:
> The Exynos850 APM co-processor relies on the I3C bus to communicate with
> the PMIC. Currently, there is no dedicated PMIC consumer driver managing
> these clocks, so the clock subsystem automatically gates them during the
> initialisation. Once gated, any subsequent ACPM communication with APM
> results in timeouts.
> 
> As a temporary workaround (and let's hope it doesn't become permanent),
> mark both `gout_i3c_pclk` and `gout_i3c_sclk` as CLK_IS_CRITICAL ones to
> prevent the clock subsystem from disabling them. This makes the ACPM
> communication functional. This workaround should be reverted once a
> proper ACPM PMIC driver is implemented to manage these clocks.
> 
> [...]

Applied, thanks!

[1/1] clk: samsung: exynos850: mark APM I3C clocks as critical
      (no commit info)

Best regards,
-- 
Krzysztof Kozlowski <krzk@kernel.org>



^ permalink raw reply

* Re: [PATCH v5 0/7] firmware: samsung: acpm: Various fixes for sashiko bug reports
From: Krzysztof Kozlowski @ 2026-05-14 16:56 UTC (permalink / raw)
  To: Alim Akhtar, Tudor Ambarus
  Cc: linux-kernel, linux-samsung-soc, linux-arm-kernel, peter.griffin,
	andre.draszik, jyescas, kernel-team, stable, Titouan Ameline
In-Reply-To: <20260505-acpm-fixes-sashiko-reports-v5-0-43b5ee7f1674@linaro.org>


On Tue, 05 May 2026 13:12:57 +0000, Tudor Ambarus wrote:
> Fixes for concurrency and memory ordering bugs that were identified by
> the Sashiko review tool when proposing the GS101 ACPM TMU addition.
> 
> While these bugs are genuine flaws, we haven't hit them yet, likely
> because we don't have enough ACPM clients upstreamed to trigger the
> race conditions.
> 
> [...]

Applied, thanks!

[1/7] firmware: samsung: acpm: Fix cross-thread RX length corruption
      https://git.kernel.org/krzk/linux/c/f133bd4b5daf71bccdde0ad1a4f47fac76a6bfb1
[2/7] firmware: samsung: acpm: Fix mailbox channel leak on probe error
      https://git.kernel.org/krzk/linux/c/b66829b17f6385cc9ffbcbe2476d532d2e3121ad
[3/7] firmware: samsung: acpm: Fix dummy stubs to return ERR_PTR
      https://git.kernel.org/krzk/linux/c/b4a38606991c0fad165f754db554961aadac247d
[4/7] firmware: samsung: acpm: Add memory barrier before advancing RX pointer
      https://git.kernel.org/krzk/linux/c/9dadf5a788164dc460a4f25e4e8798de510d63d5
[5/7] firmware: samsung: acpm: Fix false timeouts and Use-After-Free in polling
      https://git.kernel.org/krzk/linux/c/5ae6310453c7b1bc7848196a9acbd33584c4be75
[6/7] firmware: samsung: acpm: Fix missing LKMM barriers in sequence allocator
      https://git.kernel.org/krzk/linux/c/a7569019007a448826571f880d0010b7f1945e12
[7/7] firmware: samsung: acpm: Fix infinite loop on sequence number exhaustion
      https://git.kernel.org/krzk/linux/c/10313b4cca783ef2e38b2a76dc42dda481d7ebf3

Best regards,
-- 
Krzysztof Kozlowski <krzk@kernel.org>



^ permalink raw reply

* Re: [PATCH] clk: samsung: gs101: Fix missing USI7_USI DIV clock in peric0_clk_regs
From: Krzysztof Kozlowski @ 2026-05-14 16:56 UTC (permalink / raw)
  To: peter.griffin, s.nawrocki, cw00.choi, mturquette, sboyd,
	Kuan-Wei Chiu
  Cc: andre.draszik, tudor.ambarus, alim.akhtar, semen.protsenko, wllee,
	hsuanting, marscheng, jserv, linux-arm-kernel, linux-samsung-soc,
	linux-clk, linux-kernel, visitorckw, Yu-Chun Lin
In-Reply-To: <20260505171457.1960837-1-visitorckw@gmail.com>


On Tue, 05 May 2026 17:14:57 +0000, Kuan-Wei Chiu wrote:
> In the peric0_clk_regs array, the divider register offset for USI6 was
> accidentally listed twice, while the divider for USI7 was omitted.
> 
> Missing this DIV register causes the USI7 clock divider setting to be
> lost and reset to its hardware default value during a suspend/resume
> cycle.
> 
> [...]

Applied, thanks!

[1/1] clk: samsung: gs101: Fix missing USI7_USI DIV clock in peric0_clk_regs
      https://git.kernel.org/krzk/linux/c/78ee734b36284d82454e87a92094fdb926985b47

Best regards,
-- 
Krzysztof Kozlowski <krzk@kernel.org>



^ permalink raw reply

* Re: [PATCH v5 1/7] firmware: samsung: acpm: Fix cross-thread RX length corruption
From: Krzysztof Kozlowski @ 2026-05-14 16:55 UTC (permalink / raw)
  To: Alexey Klimov, Tudor Ambarus
  Cc: Alim Akhtar, linux-kernel, linux-samsung-soc, linux-arm-kernel,
	peter.griffin, andre.draszik, jyescas, kernel-team, stable,
	Titouan Ameline
In-Reply-To: <DIBOZA3G83XE.13MZJF4AJQAOU@linaro.org>

On 06/05/2026 17:17, Alexey Klimov wrote:
> On Tue May 5, 2026 at 2:12 PM BST, Tudor Ambarus wrote:
>> Sashiko identified a cross-thread RX length corruption bug when
>> reviewing the thermal addition to ACPM [1].
>>
>> When multiple threads concurrently send IPC requests, the ACPM polling
>> mechanism can encounter responses belonging to other threads. To drain
>> the queue, the driver saves these concurrent responses into an internal
>> cache (`rx_data->cmd`) to be retrieved later by the owning thread.
>>
>> Previously, the driver incorrectly used `xfer->rxcnt` (the expected
>> receive length of the *current* polling thread) when copying data for
>> *other* threads into this cache. If the threads expected responses of
>> different lengths, this resulted in buffer underflows (leading to reads
>> of uninitialized memory) or potential buffer overflows.
>>
>> Fix this by replacing the boolean `response` flag in
>> `struct acpm_rx_data` with `rxcnt`, caching the exact expected receive
>> length for each specific transaction during transfer preparation. Use
>> this cached length when saving concurrent responses.
>>
>> Consequently, ensure that `xfer->rxcnt` is explicitly zeroed in driver
>> helpers (e.g., `acpm_dvfs_set_xfer`) for fire-and-forget messages to
>> prevent uninitialized stack garbage from being interpreted as a massive
>> expected receive length.
>>
>> Cc: stable@vger.kernel.org
>> Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
>> Reported-by: Titouan Ameline <titouan.ameline@gmail.com>
> 
> As far as I can see, the name in this tag should be
> Titouan Ameline de Cadeville.

Ack, thanks!

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v5 0/7] perf libunwind multiple remote support
From: Ian Rogers @ 2026-05-14 16:51 UTC (permalink / raw)
  To: acme, adrian.hunter, dapeng1.mi, james.clark, namhyung,
	Florian Fainelli, Li Guan
  Cc: 9erthalion6, alex, alexander.shishkin, andrew.jones, aou,
	atrajeev, howardchu95, john.g.garry, jolsa, leo.yan,
	libunwind-devel, linux-arm-kernel, linux-kernel, linux-perf-users,
	linux-riscv, mingo, palmer, peterz, pjw, shimin.guo, tglozar,
	tmricht, will
In-Reply-To: <20260513233151.572332-1-irogers@google.com>

On Wed, May 13, 2026 at 4:32 PM Ian Rogers <irogers@google.com> wrote:
>
> Fix the libunwind build for when libdw and libunwind are feature
> detected, currently failing with a duplicate symbol.
>
> Refactor the libunwind support so that whenever a remote target is
> available, perf functions using the ELF machine can use that remote
> target regardless of what the host/local machine is. Migrate existing
> libunwind supported architectures like powerpc, arm64 and loongarch so
> that they can work in a cross-architecture way. Add support for
> RISC-V. Make the code more regular in function names, etc. and avoid
> including a C-file. This increases the lines of code. It is similar in
> style to the unwind-libdw implementation. It is hoped that the more
> uniform nature of the code will help with refactoring the perf
> registers for SIMD/APX support.
>
> Aside from local host testing these patches are under tested, in part
> as I'm failing to see how to build libunwind with support for multiple
> remote targets. Please could I get help in testing.

So the patches failed to apply in Sashiko:
https://sashiko.dev/#/patchset/20260513233151.572332-1-irogers%40google.com
The baseline logs show perf-tools-next was at commit 8c8f20936143
("perf build: Remove NO_GTK2 build test") which is 6 patches
out-of-date compared to the current tip these patches are against. I
ran Sashiko locally, so I don't expect a huge amount from the reviews.
Currently Sashiko is catching up with a backlog because its tokens
have a lower priority and there was high load earlier in the week.
Anyway, I could repost the patches for Sashiko review but given the
backlog I think that would just create noise at the moment. Hopefully
I can get human review so we can move forward with merging these
improvements.

Thanks,
Ian

> v5: Rebase dropping merged loong arch fix patch. Fixes to Sashiko
>     review feedback:
>     - Patch 1: Hooked unwind__configure() into perf_default_config().
>       Standardized unwinder return contracts (>0 success, 0 fallback,
>       <0 fatal).  Fixed UNWIND_STYLE_UNKNOWN fallback and added
>       memset() to clear config array on override.
>     - Patch 2: Dynamically populated FILES list in
>       tools/build/feature/Makefile using LIBUNWIND_ARCHS. Added
>       libunwind cases to FEATURE_TESTS_EXTRA in
>       tools/build/Makefile.feature for proper FEATURE-DUMP caching.
>     - Patch 3: Restored core -lunwind linkage to
>       FEATURE_CHECK_LDFLAGS.  Restored NO_LIBUNWIND fallback
>       validation, corrected EXTLIBS evaluation ordering for
>       BIONIC/Android compatibility, and restored static linking
>       multiple definition flags.
>     - Patch 4: Fixed out-of-bounds array read bugs (>= ARRAY_SIZE) in
>       libunwind-i386.c and libunwind-x86_64.c. Fixed constant typos
>       across LoongArch, PowerPC, and s390x.
>     - Patch 5: Added early EM_NONE and ops validation checks to
>       prevent warnings and NULL dereferences. Checked return value of
>       unwind__prepare_access() in maps__copy_from(). Corrected
>       architecture binding in thread__insert_map() by calculating
>       e_machine after map insertion.
>     - Patch 6: Aligned all remote architecture accessors to match
>       5-argument generic declarations (removing trailing
>       sizeof(unw_word_t)). Prevented frame discard on stack depth
>       limit by returning 0 instead of -1 in unwind_step(). Fixed
>       32-bit big-endian register corruption by replacing memcpy() with
>       conditional type-casted assignment. Fixed max_stack == 1
>       fallback trigger. Fixed .debug_frame layout union corruption by
>       changing di.u.rti to di.u.ti across all DWARF find wrappers.
>     - Patch 7: Applied the same corrections (5-argument accessors,
>       u.ti union accessors, 0 return on max_ips) to the newly
>       introduced libunwind-riscv.c.
>
> v4: Rebase, in particular the zalloc->calloc change conflicted.
> https://lore.kernel.org/linux-perf-users/20260413024805.1316480-1-irogers@google.com/
>
> v3: Minor whitespace clean up and warn when a dynamic choice of libdw
>     or libunwind is selected for unwinding and support is missing (Arnaldo).
> https://lore.kernel.org/lkml/20260404054032.1538095-1-irogers@google.com/
>
> v2: Move two fixes patches to position 1 and 2 in the series. Fix
>     struct naming inconsistency, Andrew Jones
>     <andrew.jones@oss.qualcomm.com>. Fix other inconsistencies and
>     potential non-x86 build issues.
> https://lore.kernel.org/lkml/20260305221927.3237145-1-irogers@google.com/
>
> v1: https://lore.kernel.org/lkml/20260224142938.26088-1-irogers@google.com/
>
> Ian Rogers (7):
>   perf unwind: Refactor get_entries to allow dynamic libdw/libunwind
>     selection
>   tools build: Deduplicate test-libunwind for different architectures
>   perf build: Be more programmatic when setting up libunwind variables
>   perf unwind-libunwind: Make libunwind register reading cross platform
>   perf unwind-libunwind: Move flush/finish access out of local
>   perf unwind-libunwind: Remove libunwind-local
>   perf unwind-libunwind: Add RISC-V libunwind support
>
>  tools/build/Makefile.feature                  |  12 +-
>  tools/build/feature/Makefile                  |  46 +-
>  tools/build/feature/test-libunwind-aarch64.c  |  27 -
>  tools/build/feature/test-libunwind-arm.c      |  28 -
>  .../test-libunwind-debug-frame-aarch64.c      |  17 -
>  .../feature/test-libunwind-debug-frame-arm.c  |  17 -
>  .../feature/test-libunwind-debug-frame.c      |   1 -
>  tools/build/feature/test-libunwind-x86.c      |  28 -
>  tools/build/feature/test-libunwind-x86_64.c   |  28 -
>  tools/build/feature/test-libunwind.c          |   1 -
>  tools/perf/Makefile.config                    | 226 +++--
>  tools/perf/arch/arm/util/Build                |   2 -
>  tools/perf/arch/arm/util/unwind-libunwind.c   |  50 --
>  tools/perf/arch/arm64/util/Build              |   1 -
>  tools/perf/arch/arm64/util/unwind-libunwind.c |  17 -
>  tools/perf/arch/loongarch/util/Build          |   2 -
>  .../arch/loongarch/util/unwind-libunwind.c    |  82 --
>  tools/perf/arch/mips/Build                    |   1 -
>  tools/perf/arch/mips/util/Build               |   1 -
>  tools/perf/arch/mips/util/unwind-libunwind.c  |  22 -
>  tools/perf/arch/powerpc/util/Build            |   1 -
>  .../perf/arch/powerpc/util/unwind-libunwind.c |  92 --
>  tools/perf/arch/x86/util/Build                |   3 -
>  tools/perf/arch/x86/util/unwind-libunwind.c   | 115 ---
>  tools/perf/builtin-inject.c                   |   4 +
>  tools/perf/builtin-report.c                   |   4 +
>  tools/perf/builtin-script.c                   |   4 +
>  tools/perf/util/Build                         |   5 +-
>  tools/perf/util/config.c                      |   4 +
>  tools/perf/util/libunwind-arch/Build          |  11 +
>  .../perf/util/libunwind-arch/libunwind-arch.c | 319 +++++++
>  .../perf/util/libunwind-arch/libunwind-arch.h | 296 +++++++
>  .../perf/util/libunwind-arch/libunwind-arm.c  | 290 ++++++
>  .../util/libunwind-arch/libunwind-arm64.c     | 289 ++++++
>  .../perf/util/libunwind-arch/libunwind-i386.c | 312 +++++++
>  .../util/libunwind-arch/libunwind-loongarch.c | 297 +++++++
>  .../perf/util/libunwind-arch/libunwind-mips.c | 299 +++++++
>  .../util/libunwind-arch/libunwind-ppc32.c     | 301 +++++++
>  .../util/libunwind-arch/libunwind-ppc64.c     | 303 +++++++
>  .../util/libunwind-arch/libunwind-riscv.c     | 297 +++++++
>  .../perf/util/libunwind-arch/libunwind-s390.c | 299 +++++++
>  .../util/libunwind-arch/libunwind-x86_64.c    | 320 +++++++
>  tools/perf/util/libunwind/arm64.c             |  40 -
>  tools/perf/util/libunwind/x86_32.c            |  41 -
>  tools/perf/util/maps.c                        |  34 +-
>  tools/perf/util/maps.h                        |   4 +-
>  tools/perf/util/symbol_conf.h                 |  10 +
>  tools/perf/util/thread.c                      |  32 +-
>  tools/perf/util/unwind-libdw.c                |  20 +-
>  tools/perf/util/unwind-libunwind-local.c      | 831 ------------------
>  tools/perf/util/unwind-libunwind.c            | 699 +++++++++++++--
>  tools/perf/util/unwind.c                      | 104 +++
>  tools/perf/util/unwind.h                      |  73 +-
>  53 files changed, 4623 insertions(+), 1739 deletions(-)
>  delete mode 100644 tools/build/feature/test-libunwind-aarch64.c
>  delete mode 100644 tools/build/feature/test-libunwind-arm.c
>  delete mode 100644 tools/build/feature/test-libunwind-debug-frame-aarch64.c
>  delete mode 100644 tools/build/feature/test-libunwind-debug-frame-arm.c
>  delete mode 100644 tools/build/feature/test-libunwind-x86.c
>  delete mode 100644 tools/build/feature/test-libunwind-x86_64.c
>  delete mode 100644 tools/perf/arch/arm/util/unwind-libunwind.c
>  delete mode 100644 tools/perf/arch/arm64/util/unwind-libunwind.c
>  delete mode 100644 tools/perf/arch/loongarch/util/unwind-libunwind.c
>  delete mode 100644 tools/perf/arch/mips/Build
>  delete mode 100644 tools/perf/arch/mips/util/Build
>  delete mode 100644 tools/perf/arch/mips/util/unwind-libunwind.c
>  delete mode 100644 tools/perf/arch/powerpc/util/unwind-libunwind.c
>  delete mode 100644 tools/perf/arch/x86/util/unwind-libunwind.c
>  create mode 100644 tools/perf/util/libunwind-arch/Build
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-arch.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-arch.h
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-arm.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-arm64.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-i386.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-loongarch.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-mips.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-ppc32.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-ppc64.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-riscv.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-s390.c
>  create mode 100644 tools/perf/util/libunwind-arch/libunwind-x86_64.c
>  delete mode 100644 tools/perf/util/libunwind/arm64.c
>  delete mode 100644 tools/perf/util/libunwind/x86_32.c
>  delete mode 100644 tools/perf/util/unwind-libunwind-local.c
>  create mode 100644 tools/perf/util/unwind.c
>
> --
> 2.54.0.563.g4f69b47b94-goog
>


^ permalink raw reply

* [PATCH v2 01/17] ACPI: GTDT: Account for GTDTv3 size when walking the platform timer descriptors
From: Marc Zyngier @ 2026-05-14 15:09 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, linux-kernel, devicetree
  Cc: Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla, Catalin Marinas,
	Will Deacon, Rafael J. Wysocki, Mark Rutland, Daniel Lezcano,
	Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Neil Armstrong,
	Kevin Hilman, Jerome Brunet, Martin Blumenstingl, Ge Gordon,
	BST Linux Kernel Upstream Group, Jesper Nilsson, Lars Persson,
	Alim Akhtar, Ivaylo Ivanov, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Dinh Nguyen,
	Matthias Brugger, AngeloGioacchino Del Regno, Thierry Reding,
	Jonathan Hunter, Bjorn Andersson, Konrad Dybcio,
	Andreas Färber, Heiko Stuebner, Shawn Lin, Orson Zhai,
	Baolin Wang, Michal Simek
In-Reply-To: <20260514150945.3917510-1-maz@kernel.org>

Since ARMv8.1, the architecture has grown an EL2-private virtual
timer. This has been described in ACPI since ACPI v6.3 and revision
3 of the GTDT table.

An aditional structure was added in ACPICA, though in a rather
bizarre way, and merged in v5.1 as 8f5a14d053100 ("ACPICA: ACPI 6.3:
add GTDT Revision 3 support").

Finally plug the table parsing in GTDT, and correct the parsing of
the platform timer subtables to account for the expanded size of
the base table.

Suggested-by: Sudeep Holla <sudeep.holla@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/acpi/arm64/gtdt.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index ffc867bac2d60..b9d9b8edf2df7 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -32,6 +32,12 @@ struct acpi_gtdt_descriptor {
 	struct acpi_table_gtdt *gtdt;
 	void *gtdt_end;
 	void *platform_timer;
+	bool v3;
+};
+
+struct gtdt_v3 {
+	struct acpi_table_gtdt	gtdt_v2;
+	struct acpi_gtdt_el2	el2_vtimer;
 };
 
 static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
@@ -39,8 +45,14 @@ static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
 static __init bool platform_timer_valid(void *platform_timer)
 {
 	struct acpi_gtdt_header *gh = platform_timer;
+	void *platform_timer_begin;
+
+	if (acpi_gtdt_desc.v3)
+		platform_timer_begin = container_of(acpi_gtdt_desc.gtdt, struct gtdt_v3, gtdt_v2) + 1;
+	else
+		platform_timer_begin = acpi_gtdt_desc.gtdt + 1;
 
-	return (platform_timer >= (void *)(acpi_gtdt_desc.gtdt + 1) &&
+	return (platform_timer >= platform_timer_begin &&
 		platform_timer < acpi_gtdt_desc.gtdt_end &&
 		gh->length != 0 &&
 		platform_timer + gh->length <= acpi_gtdt_desc.gtdt_end);
@@ -169,6 +181,7 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
 	acpi_gtdt_desc.gtdt = gtdt;
 	acpi_gtdt_desc.gtdt_end = (void *)table + table->length;
 	acpi_gtdt_desc.platform_timer = NULL;
+	acpi_gtdt_desc.v3 = gtdt->header.revision >= 3 && gtdt->header.length >= sizeof(struct gtdt_v3);
 	if (platform_timer_count)
 		*platform_timer_count = 0;
 
-- 
2.47.3



^ permalink raw reply related

* Re: [PATCH net-next 1/2] net: ti: icssg: Derive stats array lengths from ARRAY_SIZE
From: Jacob Keller @ 2026-05-14 16:38 UTC (permalink / raw)
  To: MD Danish Anwar, David CARLIER
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Jonathan Corbet, Shuah Khan, Roger Quadros,
	Andrew Lunn, Meghana Malladi, Kevin Hao, Vadim Fedorenko, netdev,
	linux-doc, linux-kernel, linux-arm-kernel, Vignesh Raghavendra
In-Reply-To: <e28d2931-004e-4935-a0b5-d554ece76fb2@ti.com>

On 5/13/2026 9:56 PM, MD Danish Anwar wrote:
> Hi Jacob,
> 
> On 14/05/26 1:30 am, Jacob Keller wrote:
>> The way we solved this in the Intel drivers is to use a single array
>> which contains both the stat name as well as the offset from the
>> structure where the stat resides.
>>
>> The stat string code just iterates over the stat list for the strings,
>> while the stat value code iterates the array and computes the stat
>> address from the offset and size and base structure pointer. Each object
>> that has stats has its own stat array structure.
>>
>> This is probably overkill, but the advantage is that the strings and
>> their values are stored together and adding a new stat is as simple as
>> adding a new entry to that list.
>>
>> I.e.
>>
>> struct ice_stats {
>>         char stat_string[ETH_GSTRING_LEN];
>>         int sizeof_stat;
>>         int stat_offset;
>> };
>>
>> #define ICE_STAT(_type, _name, _stat) { \
>>         .stat_string = _name, \
>>         .sizeof_stat = sizeof_field(_type, _stat), \
>>         .stat_offset = offsetof(_type, _stat) \
>> }
>>
>> #define ICE_VSI_STAT(_name, _stat) \
>>                 ICE_STAT(struct ice_vsi, _name, _stat)
>> #define ICE_PF_STAT(_name, _stat) \
>>                 ICE_STAT(struct ice_pf, _name, _stat)
>>
>>
>> Then the stats for the individial arrays are defined like this:
>>
>> static const struct ice_stats ice_gstrings_vsi_stats[] = {
>>         ICE_VSI_STAT(ICE_RX_UNICAST, eth_stats.rx_unicast),
>>         ICE_VSI_STAT(ICE_TX_UNICAST, eth_stats.tx_unicast),
>>         ICE_VSI_STAT(ICE_RX_MULTICAST, eth_stats.rx_multicast),
>>         ICE_VSI_STAT(ICE_TX_MULTICAST, eth_stats.tx_multicast),
>>         ICE_VSI_STAT(ICE_RX_BROADCAST, eth_stats.rx_broadcast),
>>         ICE_VSI_STAT(ICE_TX_BROADCAST, eth_stats.tx_broadcast),
>> 	...
>> };
>>
>> (Note, ICE_RX_UNICAST is a macro that defines the string value.. I don't
>> recall who changed this to macros or why vs just having the strings be
>> directly in the definition...)
>>
> 
> Thanks for sharing the ice driver pattern — that's a clean design.
> 
>> This is probably a lot bigger refactor to make work, and may not be
>> exactly suitable for your driver. I've considered "upgrading" these data
> 
> Yes, I need to see if refactoring is applicable to ICSSG or not. I will
> look into this and send a separate patch / series in future if
> applicable. For this series I will stick with what David Carlier suggested.
> 
Makes sense. No need to bloat this by more work immediately. I just
wanted to point it out.

I'd like to uplift this infrastructure into core helpers so that other
drivers can more easily benefit without duplicating the scaffolding, but
its always been a low priority task especially since the private driver
stats are somewhat of a legacy/deprecated interface. (Maintainers don't
generally like driver developers making up their own statistics...)


^ permalink raw reply

* Re: [PATCH 10/10] clk: amlogic: Add A9 AO clock controller driver
From: Jerome Brunet @ 2026-05-14 16:27 UTC (permalink / raw)
  To: Jian Hu via B4 Relay
  Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Neil Armstrong, Xianwei Zhao, Kevin Hilman,
	Martin Blumenstingl, jian.hu, linux-kernel, linux-clk, devicetree,
	linux-amlogic, linux-arm-kernel
In-Reply-To: <20260511-b4-a9_clk-v1-10-41cb4071b7c9@amlogic.com>

On lun. 11 mai 2026 at 20:47, Jian Hu via B4 Relay <devnull+jian.hu.amlogic.com@kernel.org> wrote:

> From: Jian Hu <jian.hu@amlogic.com>
>
> Add the Always-on clock controller driver for the Amlogic A9 SoC family.
>
> Signed-off-by: Jian Hu <jian.hu@amlogic.com>
> ---
>  drivers/clk/meson/Makefile   |   2 +-
>  drivers/clk/meson/a9-aoclk.c | 494 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 495 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
> index 2b5b67b14efc..91af609ce815 100644
> --- a/drivers/clk/meson/Makefile
> +++ b/drivers/clk/meson/Makefile
> @@ -20,7 +20,7 @@ obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
>  obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
>  obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
>  obj-$(CONFIG_COMMON_CLK_A9_PLL) += a9-pll.o
> -obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o
> +obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o a9-aoclk.o
>  obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
>  obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
>  obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
> diff --git a/drivers/clk/meson/a9-aoclk.c b/drivers/clk/meson/a9-aoclk.c
> new file mode 100644
> index 000000000000..3c42eaf585d2
> --- /dev/null
> +++ b/drivers/clk/meson/a9-aoclk.c
> @@ -0,0 +1,494 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2026 Amlogic, Inc. All rights reserved
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/platform_device.h>
> +#include <dt-bindings/clock/amlogic,a9-aoclkc.h>
> +#include "clk-regmap.h"
> +#include "clk-dualdiv.h"
> +#include "meson-clkc-utils.h"
> +
> +#define AO_OSCIN_CTRL			0x00
> +#define AO_SYS_CLK0			0x04
> +#define AO_PWM_CLK_A_CTRL		0x1c
> +#define AO_PWM_CLK_B_CTRL		0x20
> +#define AO_PWM_CLK_C_CTRL		0x24
> +#define AO_PWM_CLK_D_CTRL		0x28
> +#define AO_PWM_CLK_E_CTRL		0x2c
> +#define AO_PWM_CLK_F_CTRL		0x30
> +#define AO_PWM_CLK_G_CTRL		0x34
> +#define AO_CEC_CTRL0			0x38
> +#define AO_CEC_CTRL1			0x3c
> +#define AO_RTC_BY_OSCIN_CTRL0		0x50
> +#define AO_RTC_BY_OSCIN_CTRL1		0x54
> +
> +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \
> +	MESON_COMP_SEL(a9_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0)
                       a9_ao_ ?


> +
> +#define A9_COMP_DIV(_name, _reg, _shift, _width) \
> +	MESON_COMP_DIV(a9_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT)
> +
> +#define A9_COMP_GATE(_name, _reg, _bit) \
> +	MESON_COMP_GATE(a9_, _name, _reg, _bit, CLK_SET_RATE_PARENT)
> +
> +static struct clk_regmap a9_ao_xtal_in = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = AO_OSCIN_CTRL,
> +		.bit_idx = 3,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "ao_xtal_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "xtal",
> +		},
> +		.num_parents = 1,
> +		/*
> +		 * It may be ao_sys's parent clock, its child clocks mark
> +		 * CLK_IS_CRITICAL, So mark CLK_IS_CRITICAL for it.
> +		 */
> +		.flags = CLK_IS_CRITICAL,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_xtal = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = AO_OSCIN_CTRL,
> +		.mask = 0x1,
> +		.shift = 0,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ao_xtal",
> +		.ops = &clk_regmap_mux_ops,
> +		/* ext_32k is from external PAD, do not automatically reparent */
> +		.parent_data = (const struct clk_parent_data []) {
> +			{ .hw = &a9_ao_xtal_in.hw },
> +			{ .fw_name = "ext_32k", },
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_NO_REPARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_sys = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = AO_OSCIN_CTRL,
> +		.mask = 0x1,
> +		.shift = 1,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ao_sys",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = (const struct clk_parent_data []) {
> +			{ .hw = &a9_ao_xtal.hw },
> +			{ .fw_name = "sys", },
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_PARENT_GATE,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_ao_pclk_parents = { .hw = &a9_ao_sys.hw };
> +
> +#define A9_AO_PCLK(_name, _bit, _flags)		       \
> +	MESON_PCLK(a9_ao_sys_##_name, AO_SYS_CLK0, _bit, \
> +		   &a9_ao_pclk_parents, _flags)
> +
> +/*
> + * A9 integrates a low-power microprocessor (Always-on CPU: AOCPU). Some AO sys
> + * clocks control the AOCPU modules. Mark the AOCPU-related clocks with
> + * CLK_IS_CRITICAL to avoid them being disabled and impacting AOCPU functionality.
> + * AOCPU-related clocks list:
> + * - clktree
> + * - rst_ctrl
> + * - pad
> + * - irq
> + * - pwrctrl
> + * - aocpu
> + * - sram
> + */
> +static A9_AO_PCLK(i2c3,		0,	0);
> +static A9_AO_PCLK(rtc_reg,	1,	0);
> +static A9_AO_PCLK(clktree,	2,	CLK_IS_CRITICAL);
> +static A9_AO_PCLK(rst_ctrl,	3,	CLK_IS_CRITICAL);
> +static A9_AO_PCLK(pad,		4,	CLK_IS_CRITICAL);
> +static A9_AO_PCLK(rtc_dig,	5,	0);
> +static A9_AO_PCLK(irq,		6,	CLK_IS_CRITICAL);
> +static A9_AO_PCLK(pwrctrl,	7,	CLK_IS_CRITICAL);
> +static A9_AO_PCLK(pwm_a,	8,	0);
> +static A9_AO_PCLK(pwm_b,	9,	0);
> +static A9_AO_PCLK(pwm_c,	10,	0);
> +static A9_AO_PCLK(pwm_d,	11,	0);
> +static A9_AO_PCLK(pwm_e,	12,	0);
> +static A9_AO_PCLK(pwm_f,	13,	0);
> +static A9_AO_PCLK(pwm_g,	14,	0);
> +static A9_AO_PCLK(i2c_a,	15,	0);
> +static A9_AO_PCLK(i2c_b,	16,	0);
> +static A9_AO_PCLK(i2c_c,	17,	0);
> +static A9_AO_PCLK(i2c_d,	18,	0);
> +static A9_AO_PCLK(sed,		19,	0);
> +static A9_AO_PCLK(ir_ctrl,	20,	0);
> +static A9_AO_PCLK(uart_b,	21,	0);
> +static A9_AO_PCLK(uart_c,	22,	0);
> +static A9_AO_PCLK(uart_d,	23,	0);
> +static A9_AO_PCLK(uart_e,	24,	0);
> +static A9_AO_PCLK(spisg_0,	25,	0);
> +static A9_AO_PCLK(rtc_secure,	26,	0);
> +static A9_AO_PCLK(cec,		27,	0);
> +static A9_AO_PCLK(aocpu,	28,	CLK_IS_CRITICAL);
> +static A9_AO_PCLK(sram,		29,	CLK_IS_CRITICAL);
> +static A9_AO_PCLK(spisg_1,	30,	0);
> +static A9_AO_PCLK(spisg_2,	31,	0);
> +
> +static const struct clk_parent_data a9_ao_pwm_parents[] = {
> +	{ .hw = &a9_ao_xtal.hw },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", }
> +};
> +
> +static A9_COMP_SEL(ao_pwm_a, AO_PWM_CLK_A_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(ao_pwm_a, AO_PWM_CLK_A_CTRL, 0, 8);
> +static A9_COMP_GATE(ao_pwm_a, AO_PWM_CLK_A_CTRL, 8);
> +
> +static A9_COMP_SEL(ao_pwm_b, AO_PWM_CLK_B_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(ao_pwm_b, AO_PWM_CLK_B_CTRL, 0, 8);
> +static A9_COMP_GATE(ao_pwm_b, AO_PWM_CLK_A_CTRL, 8);
> +
> +static A9_COMP_SEL(ao_pwm_c, AO_PWM_CLK_C_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(ao_pwm_c, AO_PWM_CLK_C_CTRL, 0, 8);
> +static A9_COMP_GATE(ao_pwm_c, AO_PWM_CLK_C_CTRL, 8);
> +
> +static A9_COMP_SEL(ao_pwm_d, AO_PWM_CLK_D_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(ao_pwm_d, AO_PWM_CLK_D_CTRL, 0, 8);
> +static A9_COMP_GATE(ao_pwm_d, AO_PWM_CLK_D_CTRL, 8);
> +
> +static A9_COMP_SEL(ao_pwm_e, AO_PWM_CLK_E_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(ao_pwm_e, AO_PWM_CLK_E_CTRL, 0, 8);
> +static A9_COMP_GATE(ao_pwm_e, AO_PWM_CLK_E_CTRL, 8);
> +
> +static A9_COMP_SEL(ao_pwm_f, AO_PWM_CLK_F_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(ao_pwm_f, AO_PWM_CLK_F_CTRL, 0, 8);
> +static A9_COMP_GATE(ao_pwm_f, AO_PWM_CLK_F_CTRL, 8);
> +
> +static A9_COMP_SEL(ao_pwm_g, AO_PWM_CLK_G_CTRL, 9, 0x7, a9_ao_pwm_parents);
> +static A9_COMP_DIV(ao_pwm_g, AO_PWM_CLK_G_CTRL, 0, 8);
> +static A9_COMP_GATE(ao_pwm_g, AO_PWM_CLK_G_CTRL, 8);
> +
> +static struct clk_regmap a9_ao_rtc_dualdiv_in = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = AO_RTC_BY_OSCIN_CTRL0,
> +		.bit_idx = 31,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "ao_rtc_duandiv_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_xtal.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static const struct meson_clk_dualdiv_param a9_ao_dualdiv_table[] = {
> +	{ 733, 732, 8, 11, 1 },
> +	{ /* sentinel */ }
> +};
> +
> +static struct clk_regmap a9_ao_rtc_dualdiv_div = {
> +	.data = &(struct meson_clk_dualdiv_data){
> +		.n1 = {
> +			.reg_off = AO_RTC_BY_OSCIN_CTRL0,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.n2 = {
> +			.reg_off = AO_RTC_BY_OSCIN_CTRL0,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.m1 = {
> +			.reg_off = AO_RTC_BY_OSCIN_CTRL1,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.m2 = {
> +			.reg_off = AO_RTC_BY_OSCIN_CTRL1,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.dual = {
> +			.reg_off = AO_RTC_BY_OSCIN_CTRL0,
> +			.shift   = 28,
> +			.width   = 1,
> +		},
> +		.table = a9_ao_dualdiv_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "a9_ao_rtc_dualdiv_div",
> +		.ops = &meson_clk_dualdiv_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_rtc_dualdiv_in.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_rtc_dualdiv_sel = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = AO_RTC_BY_OSCIN_CTRL1,
> +		.mask = 0x1,
> +		.shift = 24,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ao_rtc_dualdiv_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_rtc_dualdiv_div.hw,
> +			&a9_ao_rtc_dualdiv_in.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_rtc_dualdiv = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = AO_RTC_BY_OSCIN_CTRL0,
> +		.bit_idx = 30,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "ao_rtc_dualdiv",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_rtc_dualdiv_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_rtc = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = AO_RTC_BY_OSCIN_CTRL1,
> +		.mask = 0x1,
> +		.shift = 30,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ao_rtc",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_xtal.hw,
> +			&a9_ao_rtc_dualdiv.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_cec_dualdiv_in = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = AO_CEC_CTRL0,
> +		.bit_idx = 31,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "ao_cec_dualdiv_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_xtal.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_cec_dualdiv_div = {
> +	.data = &(struct meson_clk_dualdiv_data){
> +		.n1 = {
> +			.reg_off = AO_CEC_CTRL0,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.n2 = {
> +			.reg_off = AO_CEC_CTRL0,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.m1 = {
> +			.reg_off = AO_CEC_CTRL1,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.m2 = {
> +			.reg_off = AO_CEC_CTRL1,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.dual = {
> +			.reg_off = AO_CEC_CTRL0,
> +			.shift   = 28,
> +			.width   = 1,
> +		},
> +		.table = a9_ao_dualdiv_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ao_cec_dualdiv_div",
> +		.ops = &meson_clk_dualdiv_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_cec_dualdiv_in.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_cec_dualdiv_sel = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = AO_CEC_CTRL1,
> +		.mask = 0x1,
> +		.shift = 24,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ao_cec_dualdiv_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_cec_dualdiv_div.hw,
> +			&a9_ao_cec_dualdiv_in.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_cec_dualdiv = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = AO_CEC_CTRL0,
> +		.bit_idx = 30,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ao_cec_dualdiv",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_cec_dualdiv_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_ao_cec = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = AO_CEC_CTRL1,
> +		.mask = 0x1,
> +		.shift = 30,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ao_cec",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ao_cec_dualdiv.hw,
> +			&a9_ao_rtc.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_hw *a9_ao_hw_clks[] = {
> +	[CLKID_AO_XTAL_IN]		= &a9_ao_xtal_in.hw,
> +	[CLKID_AO_XTAL]			= &a9_ao_xtal.hw,
> +	[CLKID_AO_SYS]			= &a9_ao_sys.hw,
> +	[CLKID_AO_SYS_I3C]		= &a9_ao_sys_i2c3.hw,
> +	[CLKID_AO_SYS_RTC_REG]		= &a9_ao_sys_rtc_reg.hw,
> +	[CLKID_AO_SYS_CLKTREE]		= &a9_ao_sys_clktree.hw,
> +	[CLKID_AO_SYS_RST_CTRL]		= &a9_ao_sys_rst_ctrl.hw,
> +	[CLKID_AO_SYS_PAD]		= &a9_ao_sys_pad.hw,
> +	[CLKID_AO_SYS_RTC_DIG]		= &a9_ao_sys_rtc_dig.hw,
> +	[CLKID_AO_SYS_IRQ]		= &a9_ao_sys_irq.hw,
> +	[CLKID_AO_SYS_PWRCTRL]		= &a9_ao_sys_pwrctrl.hw,
> +	[CLKID_AO_SYS_PWM_A]		= &a9_ao_sys_pwm_a.hw,
> +	[CLKID_AO_SYS_PWM_B]		= &a9_ao_sys_pwm_b.hw,
> +	[CLKID_AO_SYS_PWM_C]		= &a9_ao_sys_pwm_c.hw,
> +	[CLKID_AO_SYS_PWM_D]		= &a9_ao_sys_pwm_d.hw,
> +	[CLKID_AO_SYS_PWM_E]		= &a9_ao_sys_pwm_e.hw,
> +	[CLKID_AO_SYS_PWM_F]		= &a9_ao_sys_pwm_f.hw,
> +	[CLKID_AO_SYS_PWM_G]		= &a9_ao_sys_pwm_g.hw,
> +	[CLKID_AO_SYS_I2C_A]		= &a9_ao_sys_i2c_a.hw,
> +	[CLKID_AO_SYS_I2C_B]		= &a9_ao_sys_i2c_b.hw,
> +	[CLKID_AO_SYS_I2C_C]		= &a9_ao_sys_i2c_c.hw,
> +	[CLKID_AO_SYS_I2C_D]		= &a9_ao_sys_i2c_d.hw,
> +	[CLKID_AO_SYS_SED]		= &a9_ao_sys_sed.hw,
> +	[CLKID_AO_SYS_IR_CTRL]		= &a9_ao_sys_ir_ctrl.hw,
> +	[CLKID_AO_SYS_UART_B]		= &a9_ao_sys_uart_b.hw,
> +	[CLKID_AO_SYS_UART_C]		= &a9_ao_sys_uart_c.hw,
> +	[CLKID_AO_SYS_UART_D]		= &a9_ao_sys_uart_d.hw,
> +	[CLKID_AO_SYS_UART_E]		= &a9_ao_sys_uart_e.hw,
> +	[CLKID_AO_SYS_SPISG_0]		= &a9_ao_sys_spisg_0.hw,
> +	[CLKID_AO_SYS_RTC_SECURE]	= &a9_ao_sys_rtc_secure.hw,
> +	[CLKID_AO_SYS_CEC]		= &a9_ao_sys_cec.hw,
> +	[CLKID_AO_SYS_AOCPU]		= &a9_ao_sys_aocpu.hw,
> +	[CLKID_AO_SYS_SRAM]		= &a9_ao_sys_sram.hw,
> +	[CLKID_AO_SYS_SPISG_1]		= &a9_ao_sys_spisg_1.hw,
> +	[CLKID_AO_SYS_SPISG_2]		= &a9_ao_sys_spisg_2.hw,
> +	[CLKID_AO_PWM_A_SEL]		= &a9_ao_pwm_a_sel.hw,
> +	[CLKID_AO_PWM_A_DIV]		= &a9_ao_pwm_a_div.hw,
> +	[CLKID_AO_PWM_A]		= &a9_ao_pwm_a.hw,
> +	[CLKID_AO_PWM_B_SEL]		= &a9_ao_pwm_b_sel.hw,
> +	[CLKID_AO_PWM_B_DIV]		= &a9_ao_pwm_b_div.hw,
> +	[CLKID_AO_PWM_B]		= &a9_ao_pwm_b.hw,
> +	[CLKID_AO_PWM_C_SEL]		= &a9_ao_pwm_c_sel.hw,
> +	[CLKID_AO_PWM_C_DIV]		= &a9_ao_pwm_c_div.hw,
> +	[CLKID_AO_PWM_C]		= &a9_ao_pwm_c.hw,
> +	[CLKID_AO_PWM_D_SEL]		= &a9_ao_pwm_d_sel.hw,
> +	[CLKID_AO_PWM_D_DIV]		= &a9_ao_pwm_d_div.hw,
> +	[CLKID_AO_PWM_D]		= &a9_ao_pwm_d.hw,
> +	[CLKID_AO_PWM_E_SEL]		= &a9_ao_pwm_e_sel.hw,
> +	[CLKID_AO_PWM_E_DIV]		= &a9_ao_pwm_e_div.hw,
> +	[CLKID_AO_PWM_E]		= &a9_ao_pwm_e.hw,
> +	[CLKID_AO_PWM_F_SEL]		= &a9_ao_pwm_f_sel.hw,
> +	[CLKID_AO_PWM_F_DIV]		= &a9_ao_pwm_f_div.hw,
> +	[CLKID_AO_PWM_F]		= &a9_ao_pwm_f.hw,
> +	[CLKID_AO_PWM_G_SEL]		= &a9_ao_pwm_g_sel.hw,
> +	[CLKID_AO_PWM_G_DIV]		= &a9_ao_pwm_g_div.hw,
> +	[CLKID_AO_PWM_G]		= &a9_ao_pwm_g.hw,
> +	[CLKID_AO_RTC_DUALDIV_IN]	= &a9_ao_rtc_dualdiv_in.hw,
> +	[CLKID_AO_RTC_DUALDIV_DIV]	= &a9_ao_rtc_dualdiv_div.hw,
> +	[CLKID_AO_RTC_DUALDIV_SEL]	= &a9_ao_rtc_dualdiv_sel.hw,
> +	[CLKID_AO_RTC_DUALDIV]		= &a9_ao_rtc_dualdiv.hw,
> +	[CLKID_AO_RTC]			= &a9_ao_rtc.hw,
> +	[CLKID_AO_CEC_DUALDIV_IN]	= &a9_ao_cec_dualdiv_in.hw,
> +	[CLKID_AO_CEC_DUALDIV_DIV]	= &a9_ao_cec_dualdiv_div.hw,
> +	[CLKID_AO_CEC_DUALDIV_SEL]	= &a9_ao_cec_dualdiv_sel.hw,
> +	[CLKID_AO_CEC_DUALDIV]		= &a9_ao_cec_dualdiv.hw,
> +	[CLKID_AO_CEC]			= &a9_ao_cec.hw,
> +};
> +
> +static const struct meson_clkc_data a9_ao_clkc_data = {
> +	.hw_clks = {
> +		.hws = a9_ao_hw_clks,
> +		.num = ARRAY_SIZE(a9_ao_hw_clks),
> +	},
> +};
> +
> +static const struct of_device_id a9_ao_clkc_match_table[] = {
> +	{
> +		.compatible	= "amlogic,a9-aoclkc",
> +		.data		= &a9_ao_clkc_data,
> +	},
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, a9_ao_clkc_match_table);
> +
> +static struct platform_driver a9_ao_clkc_driver = {
> +	.probe		= meson_clkc_mmio_probe,
> +	.driver		= {
> +		.name	= "a9-aoclkc",
> +		.of_match_table = a9_ao_clkc_match_table,
> +	},
> +};
> +module_platform_driver(a9_ao_clkc_driver);
> +
> +MODULE_DESCRIPTION("Amlogic A9 Always-ON Clock Controller driver");
> +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("CLK_MESON");

-- 
Jerome


^ permalink raw reply

* [PATCH] KVM: arm64: Fix nVHE/pKVM hyp tracing error on invalid desc
From: Vincent Donnefort @ 2026-05-14 16:26 UTC (permalink / raw)
  To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will
  Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort

pKVM must validate the host-provided tracing buffer descriptor.
However, if an error is found, the hypervisor would just return 0 to the
host. Fix the return value on validation failure.

While at it, rename the function to hyp_trace_desc_is_valid() and skip
validation for the nVHE mode as we trust host-provided data in that
case.

Signed-off-by: Vincent Donnefort <vdonnefort@google.com>

diff --git a/arch/arm64/kvm/hyp/nvhe/trace.c b/arch/arm64/kvm/hyp/nvhe/trace.c
index a6ca27b18e15..e7e150ab265f 100644
--- a/arch/arm64/kvm/hyp/nvhe/trace.c
+++ b/arch/arm64/kvm/hyp/nvhe/trace.c
@@ -164,13 +164,16 @@ static int hyp_trace_buffer_load(struct hyp_trace_buffer *trace_buffer,
 	return ret;
 }
 
-static bool hyp_trace_desc_validate(struct hyp_trace_desc *desc, size_t desc_size)
+static bool hyp_trace_desc_is_valid(struct hyp_trace_desc *desc, size_t desc_size)
 {
 	struct ring_buffer_desc *rb_desc;
 	unsigned int cpu;
 	size_t nr_bpages;
 	void *desc_end;
 
+	if (!is_protected_kvm_enabled())
+		return true;
+
 	/*
 	 * Both desc_size and bpages_backing_size are untrusted host-provided
 	 * values. We rely on __pkvm_host_donate_hyp() to enforce their validity.
@@ -212,8 +215,10 @@ int __tracing_load(unsigned long desc_hva, size_t desc_size)
 	if (ret)
 		return ret;
 
-	if (!hyp_trace_desc_validate(desc, desc_size))
+	if (!hyp_trace_desc_is_valid(desc, desc_size)) {
+		ret = -EINVAL;
 		goto err_release_desc;
+	}
 
 	hyp_spin_lock(&trace_buffer.lock);
 

base-commit: 5d6919055dec134de3c40167a490f33c74c12581
-- 
2.54.0.563.g4f69b47b94-goog



^ permalink raw reply related

* [PATCH v2 5/5] remoteproc: switch drivers to optional resource-table helper
From: Ben Levinsky @ 2026-05-14 16:21 UTC (permalink / raw)
  To: andersson, mathieu.poirier, linux-remoteproc
  Cc: Frank.Li, s.hauer, kernel, festevam, geert+renesas, magnus.damm,
	patrice.chotard, mcoquelin.stm32, alexandre.torgue,
	arnaud.pouliquen, daniel.baluta, tanmay.shah, imx,
	linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32
In-Reply-To: <20260514162129.1504162-1-ben.levinsky@amd.com>

Use the shared optional resource-table helper in the remoteproc
drivers that already treat a missing resource table as non-fatal:
xlnx_r5_remoteproc, rcar_rproc, stm32_rproc, imx_rproc, and
imx_dsp_rproc.

Keep thin local parse_fw() wrappers in each driver so the helper only
centralizes the return-value handling. That lets each platform retain
control over whether the missing-table case is logged and at what
severity, while other parsing failures continue to propagate to the
caller.

Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
---
 drivers/remoteproc/imx_dsp_rproc.c      | 24 ++++++++++-----
 drivers/remoteproc/imx_rproc.c          | 25 ++++++++-------
 drivers/remoteproc/rcar_rproc.c         | 25 ++++++++-------
 drivers/remoteproc/stm32_rproc.c        | 23 +++++++++-----
 drivers/remoteproc/xlnx_r5_remoteproc.c | 41 +++++++++----------------
 5 files changed, 73 insertions(+), 65 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index 2d9f14fbef1d..2ff74f7938f6 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -954,14 +954,6 @@ static int imx_dsp_rproc_elf_load_segments(struct rproc *rproc, const struct fir
 	return ret;
 }
 
-static int imx_dsp_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
-{
-	if (rproc_elf_load_rsc_table(rproc, fw))
-		dev_warn(&rproc->dev, "no resource table found for this firmware\n");
-
-	return 0;
-}
-
 static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw)
 {
 	struct imx_dsp_rproc *priv = rproc->priv;
@@ -990,6 +982,22 @@ static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw)
 	return 0;
 }
 
+static int imx_dsp_rproc_parse_fw(struct rproc *rproc,
+				  const struct firmware *fw)
+{
+	int ret;
+
+	ret = rproc_elf_load_rsc_table_optional(rproc, fw);
+	if (ret)
+		return ret;
+
+	if (!rproc->table_ptr)
+		dev_warn(&rproc->dev,
+			 "no resource table found for this firmware\n");
+
+	return 0;
+}
+
 static const struct rproc_ops imx_dsp_rproc_ops = {
 	.prepare	= imx_dsp_rproc_prepare,
 	.unprepare	= imx_dsp_rproc_unprepare,
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 6249815b54d8..58c63f97ebf7 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -680,17 +680,6 @@ static int imx_rproc_prepare(struct rproc *rproc)
 	return 0;
 }
 
-static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
-{
-	int ret;
-
-	ret = rproc_elf_load_rsc_table(rproc, fw);
-	if (ret)
-		dev_info(&rproc->dev, "No resource table in elf\n");
-
-	return 0;
-}
-
 static void imx_rproc_kick(struct rproc *rproc, int vqid)
 {
 	struct imx_rproc *priv = rproc->priv;
@@ -768,6 +757,20 @@ imx_rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *
 	return rproc_elf_find_loaded_rsc_table(rproc, fw);
 }
 
+static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+	int ret;
+
+	ret = rproc_elf_load_rsc_table_optional(rproc, fw);
+	if (ret)
+		return ret;
+
+	if (!rproc->table_ptr)
+		dev_info(&rproc->dev, "No resource table in elf\n");
+
+	return 0;
+}
+
 static const struct rproc_ops imx_rproc_ops = {
 	.prepare	= imx_rproc_prepare,
 	.attach		= imx_rproc_attach,
diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c
index e3121fadd292..b7a39014b6bb 100644
--- a/drivers/remoteproc/rcar_rproc.c
+++ b/drivers/remoteproc/rcar_rproc.c
@@ -55,17 +55,6 @@ static int rcar_rproc_prepare(struct rproc *rproc)
 	}
 }
 
-static int rcar_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
-{
-	int ret;
-
-	ret = rproc_elf_load_rsc_table(rproc, fw);
-	if (ret)
-		dev_info(&rproc->dev, "No resource table in elf\n");
-
-	return 0;
-}
-
 static int rcar_rproc_start(struct rproc *rproc)
 {
 	struct rcar_rproc *priv = rproc->priv;
@@ -99,6 +88,20 @@ static int rcar_rproc_stop(struct rproc *rproc)
 	return err;
 }
 
+static int rcar_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+	int ret;
+
+	ret = rproc_elf_load_rsc_table_optional(rproc, fw);
+	if (ret)
+		return ret;
+
+	if (!rproc->table_ptr)
+		dev_info(&rproc->dev, "No resource table in elf\n");
+
+	return 0;
+}
+
 static struct rproc_ops rcar_rproc_ops = {
 	.prepare	= rcar_rproc_prepare,
 	.start		= rcar_rproc_start,
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
index 7ac8265b60ac..a4d42b755c74 100644
--- a/drivers/remoteproc/stm32_rproc.c
+++ b/drivers/remoteproc/stm32_rproc.c
@@ -232,14 +232,6 @@ static int stm32_rproc_prepare(struct rproc *rproc)
 	}
 }
 
-static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
-{
-	if (rproc_elf_load_rsc_table(rproc, fw))
-		dev_warn(&rproc->dev, "no resource table found for this firmware\n");
-
-	return 0;
-}
-
 static irqreturn_t stm32_rproc_wdg(int irq, void *data)
 {
 	struct platform_device *pdev = data;
@@ -623,6 +615,21 @@ stm32_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz)
 	return (__force struct resource_table *)ddata->rsc_va;
 }
 
+static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+	int ret;
+
+	ret = rproc_elf_load_rsc_table_optional(rproc, fw);
+	if (ret)
+		return ret;
+
+	if (!rproc->table_ptr)
+		dev_warn(&rproc->dev,
+			 "no resource table found for this firmware\n");
+
+	return 0;
+}
+
 static const struct rproc_ops st_rproc_ops = {
 	.prepare	= stm32_rproc_prepare,
 	.start		= stm32_rproc_start,
diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
index e5d1903c9636..9b9f07d152e6 100644
--- a/drivers/remoteproc/xlnx_r5_remoteproc.c
+++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
@@ -664,33 +664,6 @@ static int add_tcm_banks(struct rproc *rproc)
 	return ret;
 }
 
-/*
- * zynqmp_r5_parse_fw()
- * @rproc: single R5 core's corresponding rproc instance
- * @fw: ptr to firmware to be loaded onto r5 core
- *
- * get resource table if available
- *
- * return 0 on success, otherwise non-zero value on failure
- */
-static int zynqmp_r5_parse_fw(struct rproc *rproc, const struct firmware *fw)
-{
-	int ret;
-
-	ret = rproc_elf_load_rsc_table(rproc, fw);
-	if (ret == -EINVAL) {
-		/*
-		 * resource table only required for IPC.
-		 * if not present, this is not necessarily an error;
-		 * for example, loading r5 hello world application
-		 * so simply inform user and keep going.
-		 */
-		dev_info(&rproc->dev, "no resource table found.\n");
-		ret = 0;
-	}
-	return ret;
-}
-
 /**
  * zynqmp_r5_rproc_prepare() - prepare core to boot/attach
  * adds carveouts for TCM bank and reserved memory regions
@@ -843,6 +816,20 @@ static int zynqmp_r5_detach(struct rproc *rproc)
 	return 0;
 }
 
+static int zynqmp_r5_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+	int ret;
+
+	ret = rproc_elf_load_rsc_table_optional(rproc, fw);
+	if (ret)
+		return ret;
+
+	if (!rproc->table_ptr)
+		dev_info(&rproc->dev, "no resource table found.\n");
+
+	return 0;
+}
+
 static const struct rproc_ops zynqmp_r5_rproc_ops = {
 	.prepare	= zynqmp_r5_rproc_prepare,
 	.unprepare	= zynqmp_r5_rproc_unprepare,
-- 
2.34.1



^ permalink raw reply related

* [PATCH v2 3/5] remoteproc: mark wc-ioremap carveouts as iomem
From: Ben Levinsky @ 2026-05-14 16:21 UTC (permalink / raw)
  To: andersson, mathieu.poirier, linux-remoteproc
  Cc: Frank.Li, s.hauer, kernel, festevam, geert+renesas, magnus.damm,
	patrice.chotard, mcoquelin.stm32, alexandre.torgue,
	arnaud.pouliquen, daniel.baluta, tanmay.shah, imx,
	linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32
In-Reply-To: <20260514162129.1504162-1-ben.levinsky@amd.com>

Carveouts registered through the shared wc-ioremap helper are backed by
I/O memory, but rproc_da_to_va() only reports that to its callers when
mem->is_iomem is set on the carveout.

Without that flag, the remoteproc ELF loader and coredump paths can
fall back to normal memcpy()/memset() accessors instead of the I/O
helpers used for iomapped memory.

Mark shared wc-ioremap carveouts as iomem so the framework uses the
proper memcpy_toio(), memset_io(), and memcpy_fromio() accessors for
these regions.

Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
---
 drivers/remoteproc/remoteproc_internal.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index f5b34aabed5b..9955e512f073 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -136,6 +136,7 @@ static inline int rproc_mem_entry_ioremap_wc(struct rproc *rproc,
 	}
 
 	mem->va = (__force void *)va;
+	mem->is_iomem = true;
 
 	return 0;
 }
-- 
2.34.1



^ permalink raw reply related

* [PATCH v2 2/5] remoteproc: switch exact-match drivers to wc-ioremap callbacks
From: Ben Levinsky @ 2026-05-14 16:21 UTC (permalink / raw)
  To: andersson, mathieu.poirier, linux-remoteproc
  Cc: Frank.Li, s.hauer, kernel, festevam, geert+renesas, magnus.damm,
	patrice.chotard, mcoquelin.stm32, alexandre.torgue,
	arnaud.pouliquen, daniel.baluta, tanmay.shah, imx,
	linux-arm-kernel, linux-kernel, linux-renesas-soc, linux-stm32
In-Reply-To: <20260514162129.1504162-1-ben.levinsky@amd.com>

Replace the exact-match carveout map and unmap callbacks in the
existing remoteproc drivers with the common wc-ioremap helpers. This
covers xlnx_r5_remoteproc, rcar_rproc, st_remoteproc, stm32_rproc,
imx_rproc, and imx_dsp_rproc.

Leave the zynqmp R5 TCM callbacks alone because they also clear the
mapped memory and are therefore not exact matches for the shared
helpers.

Signed-off-by: Ben Levinsky <ben.levinsky@amd.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> # renesas
---
 drivers/remoteproc/imx_dsp_rproc.c      | 36 ++++---------------
 drivers/remoteproc/imx_rproc.c          | 32 ++---------------
 drivers/remoteproc/rcar_rproc.c         | 33 ++---------------
 drivers/remoteproc/st_remoteproc.c      | 31 ++--------------
 drivers/remoteproc/stm32_rproc.c        | 34 ++----------------
 drivers/remoteproc/xlnx_r5_remoteproc.c | 47 +++----------------------
 6 files changed, 18 insertions(+), 195 deletions(-)

diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index 008741af9f11..2d9f14fbef1d 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -644,32 +644,6 @@ static void imx_dsp_rproc_free_mbox(struct imx_dsp_rproc *priv)
 	mbox_free_channel(priv->rxdb_ch);
 }
 
-static int imx_dsp_rproc_mem_alloc(struct rproc *rproc,
-				   struct rproc_mem_entry *mem)
-{
-	struct device *dev = rproc->dev.parent;
-	void *va;
-
-	va = ioremap_wc(mem->dma, mem->len);
-	if (!va) {
-		dev_err(dev, "Unable to map memory region: %pa+%zx\n",
-			&mem->dma, mem->len);
-		return -ENOMEM;
-	}
-
-	mem->va = va;
-
-	return 0;
-}
-
-static int imx_dsp_rproc_mem_release(struct rproc *rproc,
-				     struct rproc_mem_entry *mem)
-{
-	iounmap(mem->va);
-
-	return 0;
-}
-
 /**
  * imx_dsp_rproc_add_carveout() - request mailbox channels
  * @priv: private data pointer
@@ -700,8 +674,10 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv)
 
 		/* Register memory region */
 		mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)att->sa,
-					   att->size, da, imx_dsp_rproc_mem_alloc,
-					   imx_dsp_rproc_mem_release, "dsp_mem");
+					   att->size, da,
+					   rproc_mem_entry_ioremap_wc,
+					   rproc_mem_entry_iounmap,
+					   "dsp_mem");
 
 		if (mem)
 			rproc_coredump_add_segment(rproc, da, att->size);
@@ -732,8 +708,8 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv)
 		/* Register memory region */
 		mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)res.start,
 					   resource_size(&res), da,
-					    imx_dsp_rproc_mem_alloc,
-					    imx_dsp_rproc_mem_release,
+					   rproc_mem_entry_ioremap_wc,
+					   rproc_mem_entry_iounmap,
 					   "%.*s", strchrnul(res.name, '@') - res.name, res.name);
 		if (!mem)
 			return -ENOMEM;
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 7f54322244ac..6249815b54d8 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -600,35 +600,6 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *i
 	return va;
 }
 
-static int imx_rproc_mem_alloc(struct rproc *rproc,
-			       struct rproc_mem_entry *mem)
-{
-	struct device *dev = rproc->dev.parent;
-	void *va;
-
-	dev_dbg(dev, "map memory: %p+%zx\n", &mem->dma, mem->len);
-	va = ioremap_wc(mem->dma, mem->len);
-	if (IS_ERR_OR_NULL(va)) {
-		dev_err(dev, "Unable to map memory region: %p+%zx\n",
-			&mem->dma, mem->len);
-		return -ENOMEM;
-	}
-
-	/* Update memory entry va */
-	mem->va = va;
-
-	return 0;
-}
-
-static int imx_rproc_mem_release(struct rproc *rproc,
-				 struct rproc_mem_entry *mem)
-{
-	dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma);
-	iounmap(mem->va);
-
-	return 0;
-}
-
 static int imx_rproc_sm_lmm_prepare(struct rproc *rproc)
 {
 	struct imx_rproc *priv = rproc->priv;
@@ -692,7 +663,8 @@ static int imx_rproc_prepare(struct rproc *rproc)
 		/* Register memory region */
 		mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)res.start,
 					   resource_size(&res), da,
-					   imx_rproc_mem_alloc, imx_rproc_mem_release,
+					   rproc_mem_entry_ioremap_wc,
+					   rproc_mem_entry_iounmap,
 					   "%.*s", strchrnul(res.name, '@') - res.name,
 					   res.name);
 		if (!mem)
diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c
index 3c25625f966d..e3121fadd292 100644
--- a/drivers/remoteproc/rcar_rproc.c
+++ b/drivers/remoteproc/rcar_rproc.c
@@ -19,35 +19,6 @@ struct rcar_rproc {
 	struct reset_control *rst;
 };
 
-static int rcar_rproc_mem_alloc(struct rproc *rproc,
-				 struct rproc_mem_entry *mem)
-{
-	struct device *dev = &rproc->dev;
-	void *va;
-
-	dev_dbg(dev, "map memory: %pa+%zx\n", &mem->dma, mem->len);
-	va = ioremap_wc(mem->dma, mem->len);
-	if (!va) {
-		dev_err(dev, "Unable to map memory region: %pa+%zx\n",
-			&mem->dma, mem->len);
-		return -ENOMEM;
-	}
-
-	/* Update memory entry va */
-	mem->va = va;
-
-	return 0;
-}
-
-static int rcar_rproc_mem_release(struct rproc *rproc,
-				   struct rproc_mem_entry *mem)
-{
-	dev_dbg(&rproc->dev, "unmap memory: %pa\n", &mem->dma);
-	iounmap(mem->va);
-
-	return 0;
-}
-
 static int rcar_rproc_prepare(struct rproc *rproc)
 {
 	struct device *dev = rproc->dev.parent;
@@ -73,8 +44,8 @@ static int rcar_rproc_prepare(struct rproc *rproc)
 		mem = rproc_mem_entry_init(dev, NULL,
 					   res.start,
 					   resource_size(&res), da,
-					   rcar_rproc_mem_alloc,
-					   rcar_rproc_mem_release,
+					   rproc_mem_entry_ioremap_wc,
+					   rproc_mem_entry_iounmap,
 					   res.name);
 
 		if (!mem)
diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
index a07edf7217d2..486180cdccb4 100644
--- a/drivers/remoteproc/st_remoteproc.c
+++ b/drivers/remoteproc/st_remoteproc.c
@@ -88,33 +88,6 @@ static void st_rproc_kick(struct rproc *rproc, int vqid)
 		dev_err(dev, "failed to send message via mbox: %d\n", ret);
 }
 
-static int st_rproc_mem_alloc(struct rproc *rproc,
-			      struct rproc_mem_entry *mem)
-{
-	struct device *dev = rproc->dev.parent;
-	void *va;
-
-	va = ioremap_wc(mem->dma, mem->len);
-	if (!va) {
-		dev_err(dev, "Unable to map memory region: %pa+%zx\n",
-			&mem->dma, mem->len);
-		return -ENOMEM;
-	}
-
-	/* Update memory entry va */
-	mem->va = va;
-
-	return 0;
-}
-
-static int st_rproc_mem_release(struct rproc *rproc,
-				struct rproc_mem_entry *mem)
-{
-	iounmap(mem->va);
-
-	return 0;
-}
-
 static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
 {
 	struct device *dev = rproc->dev.parent;
@@ -138,8 +111,8 @@ static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
 			mem = rproc_mem_entry_init(dev, NULL,
 						   (dma_addr_t)res.start,
 						   resource_size(&res), res.start,
-						   st_rproc_mem_alloc,
-						   st_rproc_mem_release,
+						   rproc_mem_entry_ioremap_wc,
+						   rproc_mem_entry_iounmap,
 						   "%.*s",
 						   strchrnul(res.name, '@') - res.name,
 						   res.name);
diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
index 632614013dc6..7ac8265b60ac 100644
--- a/drivers/remoteproc/stm32_rproc.c
+++ b/drivers/remoteproc/stm32_rproc.c
@@ -113,35 +113,6 @@ static int stm32_rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da)
 	return -EINVAL;
 }
 
-static int stm32_rproc_mem_alloc(struct rproc *rproc,
-				 struct rproc_mem_entry *mem)
-{
-	struct device *dev = rproc->dev.parent;
-	void *va;
-
-	dev_dbg(dev, "map memory: %pad+%zx\n", &mem->dma, mem->len);
-	va = (__force void *)ioremap_wc(mem->dma, mem->len);
-	if (IS_ERR_OR_NULL(va)) {
-		dev_err(dev, "Unable to map memory region: %pad+0x%zx\n",
-			&mem->dma, mem->len);
-		return -ENOMEM;
-	}
-
-	/* Update memory entry va */
-	mem->va = va;
-
-	return 0;
-}
-
-static int stm32_rproc_mem_release(struct rproc *rproc,
-				   struct rproc_mem_entry *mem)
-{
-	dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma);
-	iounmap((__force __iomem void *)mem->va);
-
-	return 0;
-}
-
 static int stm32_rproc_of_memory_translations(struct platform_device *pdev,
 					      struct stm32_rproc *ddata)
 {
@@ -237,8 +208,8 @@ static int stm32_rproc_prepare(struct rproc *rproc)
 			mem = rproc_mem_entry_init(dev, NULL,
 						   (dma_addr_t)res.start,
 						   resource_size(&res), da,
-						   stm32_rproc_mem_alloc,
-						   stm32_rproc_mem_release,
+						   rproc_mem_entry_ioremap_wc,
+						   rproc_mem_entry_iounmap,
 						   "%.*s", strchrnul(res.name, '@') - res.name,
 						   res.name);
 			if (mem)
@@ -957,4 +928,3 @@ MODULE_DESCRIPTION("STM32 Remote Processor Control Driver");
 MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
 MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
 MODULE_LICENSE("GPL v2");
-
diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
index 45a62cb98072..e5d1903c9636 100644
--- a/drivers/remoteproc/xlnx_r5_remoteproc.c
+++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
@@ -447,45 +447,6 @@ static int zynqmp_r5_rproc_stop(struct rproc *rproc)
 	return ret;
 }
 
-/*
- * zynqmp_r5_mem_region_map()
- * @rproc: single R5 core's corresponding rproc instance
- * @mem: mem descriptor to map reserved memory-regions
- *
- * Callback to map va for memory-region's carveout.
- *
- * return 0 on success, otherwise non-zero value on failure
- */
-static int zynqmp_r5_mem_region_map(struct rproc *rproc,
-				    struct rproc_mem_entry *mem)
-{
-	void __iomem *va;
-
-	va = ioremap_wc(mem->dma, mem->len);
-	if (IS_ERR_OR_NULL(va))
-		return -ENOMEM;
-
-	mem->va = (void *)va;
-
-	return 0;
-}
-
-/*
- * zynqmp_r5_rproc_mem_unmap
- * @rproc: single R5 core's corresponding rproc instance
- * @mem: mem entry to unmap
- *
- * Unmap memory-region carveout
- *
- * return: always returns 0
- */
-static int zynqmp_r5_mem_region_unmap(struct rproc *rproc,
-				      struct rproc_mem_entry *mem)
-{
-	iounmap((void __iomem *)mem->va);
-	return 0;
-}
-
 /*
  * add_mem_regions_carveout()
  * @rproc: single R5 core's corresponding rproc instance
@@ -522,8 +483,8 @@ static int add_mem_regions_carveout(struct rproc *rproc)
 			rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL,
 							 (dma_addr_t)res.start,
 							 resource_size(&res), res.start,
-							 zynqmp_r5_mem_region_map,
-							 zynqmp_r5_mem_region_unmap,
+							 rproc_mem_entry_ioremap_wc,
+							 rproc_mem_entry_iounmap,
 							 "%.*s",
 							 strchrnul(res.name, '@') - res.name,
 							 res.name);
@@ -560,8 +521,8 @@ static int add_sram_carveouts(struct rproc *rproc)
 		rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL,
 						 dma_addr,
 						 len, da,
-						 zynqmp_r5_mem_region_map,
-						 zynqmp_r5_mem_region_unmap,
+						 rproc_mem_entry_ioremap_wc,
+						 rproc_mem_entry_iounmap,
 						 sram->sram_res.name);
 		if (!rproc_mem) {
 			dev_err(&rproc->dev, "failed to add sram %s da=0x%x, size=0x%lx",
-- 
2.34.1



^ permalink raw reply related


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