* Re: [RESEND v2] soc: mediatek: mtk-mmsys: Restore MT8167 routing masks lost during merge
From: AngeloGioacchino Del Regno @ 2026-05-11 9:23 UTC (permalink / raw)
To: linux-mediatek, Luca Leonardo Scorcia
Cc: Matthias Brugger, Fabien Parent, linux-kernel, linux-arm-kernel
In-Reply-To: <20260505211345.318647-1-l.scorcia@gmail.com>
On Tue, 05 May 2026 22:13:16 +0100, Luca Leonardo Scorcia wrote:
> The original patch that was sent to the mailing lists included the values
> for the route masks, but they got lost during merge: add back the full
> register masks where missing.
>
>
Applied to v7.1-next/soc, thanks!
[1/1] soc: mediatek: mtk-mmsys: Restore MT8167 routing masks lost during merge
commit: 7d462de9f65b002b439b1b168bf3b5579b0de48b
Cheers,
Angelo
^ permalink raw reply
* Re: [PATCH] ASoC; dt-bindings: mediatek,mt8173-rt5650-rt5514: Fix mediatek,audio-codec constraints
From: Mark Brown @ 2026-05-11 0:28 UTC (permalink / raw)
To: Liam Girdwood, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno, Koro Chen,
Khushal Chitturi, Rob Herring (Arm)
Cc: Krzysztof Kozlowski, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <20260508182438.1757394-1-robh@kernel.org>
On Fri, 08 May 2026 13:24:37 -0500, Rob Herring (Arm) wrote:
> ASoC; dt-bindings: mediatek,mt8173-rt5650-rt5514: Fix mediatek,audio-codec constraints
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.1
Thanks!
[1/1] ASoC; dt-bindings: mediatek,mt8173-rt5650-rt5514: Fix mediatek,audio-codec constraints
https://git.kernel.org/broonie/sound/c/cb196d50a78d
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply
* [PATCH v12 04/28] coresight: Populate CPU ID into coresight_device
From: Leo Yan @ 2026-05-11 11:10 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Yeoreum Yun,
Mark Rutland, Will Deacon, Yabin Cui, Keita Morisaki, Jie Gan,
Yuanfang Zhang, Greg Kroah-Hartman, Alexander Shishkin,
Tamas Petz, Thomas Gleixner, Peter Zijlstra
Cc: coresight, linux-arm-kernel, Leo Yan
In-Reply-To: <20260511-arm_coresight_path_power_management_improvement-v12-0-1c9dcb1de8c9@arm.com>
Add a new flag CORESIGHT_DESC_CPU_BOUND to indicate components that
are CPU bound. Populate CPU ID into the coresight_device structure;
otherwise, set CPU ID to -1 for non CPU bound devices.
Use the {0} initializer to clear coresight_desc structures to avoid
uninitialized values.
Tested-by: Jie Gan <jie.gan@oss.qualcomm.com>
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Tested-by: James Clark <james.clark@linaro.org>
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
drivers/hwtracing/coresight/coresight-catu.c | 2 +-
drivers/hwtracing/coresight/coresight-core.c | 13 +++++++++++++
drivers/hwtracing/coresight/coresight-cti-core.c | 9 ++++++---
drivers/hwtracing/coresight/coresight-etm3x-core.c | 2 ++
drivers/hwtracing/coresight/coresight-etm4x-core.c | 2 ++
drivers/hwtracing/coresight/coresight-trbe.c | 2 ++
include/linux/coresight.h | 8 ++++++++
7 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index ce71dcddfca2558eddd625de58a709b151f2e07e..43abe13995cf3c96e70dcf97856872d70f71345a 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -514,7 +514,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
int ret = 0;
u32 dma_mask;
struct catu_drvdata *drvdata;
- struct coresight_desc catu_desc;
+ struct coresight_desc catu_desc = { 0 };
struct coresight_platform_data *pdata = NULL;
void __iomem *base;
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 48ea882bd10870a6be253ecf0b58860d7a4a0bb0..f8c0c2b05888403318372dc76278910c8a5c7e15 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1347,6 +1347,19 @@ coresight_init_device(struct coresight_desc *desc)
csdev->access = desc->access;
csdev->orphan = true;
+ if (desc->flags & CORESIGHT_DESC_CPU_BOUND) {
+ csdev->cpu = desc->cpu;
+ } else {
+ /* A per-CPU source or sink must set CPU_BOUND flag */
+ if (coresight_is_percpu_source(csdev) ||
+ coresight_is_percpu_sink(csdev)) {
+ kfree(csdev);
+ return ERR_PTR(-EINVAL);
+ }
+
+ csdev->cpu = -1;
+ }
+
csdev->dev.type = &coresight_dev_type[desc->type];
csdev->dev.groups = desc->groups;
csdev->dev.parent = desc->dev;
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 2f4c9362709a90b12a1aeb5016905b7d4474b912..b2c9a4db13b4e5554bca565c17ed299fdfdb30ff 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -659,7 +659,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
void __iomem *base;
struct device *dev = &adev->dev;
struct cti_drvdata *drvdata = NULL;
- struct coresight_desc cti_desc;
+ struct coresight_desc cti_desc = { 0 };
struct coresight_platform_data *pdata = NULL;
struct resource *res = &adev->res;
@@ -702,11 +702,14 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
* eCPU ID. System CTIs will have the name cti_sys<I> where I is an
* index allocated by order of discovery.
*/
- if (drvdata->ctidev.cpu >= 0)
+ if (drvdata->ctidev.cpu >= 0) {
+ cti_desc.cpu = drvdata->ctidev.cpu;
+ cti_desc.flags = CORESIGHT_DESC_CPU_BOUND;
cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d",
drvdata->ctidev.cpu);
- else
+ } else {
cti_desc.name = coresight_alloc_device_name("cti_sys", dev);
+ }
if (!cti_desc.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index a547a6d2e0bde84748f753e5529d316c4f5e82e2..eb665db1a37d9970f7f55395c0aa23b98a7f3118 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -891,6 +891,8 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
desc.pdata = pdata;
desc.dev = dev;
desc.groups = coresight_etm_groups;
+ desc.cpu = drvdata->cpu;
+ desc.flags = CORESIGHT_DESC_CPU_BOUND;
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index a251375db24b17c22490a71f97308119b89a5975..8f270bfc74723f1fc1cead2da1725ab6b50f910e 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -2291,6 +2291,8 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
desc.pdata = pdata;
desc.dev = dev;
desc.groups = coresight_etmv4_groups;
+ desc.cpu = drvdata->cpu;
+ desc.flags = CORESIGHT_DESC_CPU_BOUND;
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
index 1511f8eb95afb5b4610b8fbdacc8b174b6b08530..14e35b9660d76e47619cc6026b94929b3bb3e02b 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
+++ b/drivers/hwtracing/coresight/coresight-trbe.c
@@ -1289,6 +1289,8 @@ static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cp
desc.ops = &arm_trbe_cs_ops;
desc.groups = arm_trbe_groups;
desc.dev = dev;
+ desc.cpu = cpu;
+ desc.flags = CORESIGHT_DESC_CPU_BOUND;
trbe_csdev = coresight_register(&desc);
if (IS_ERR(trbe_csdev))
goto cpu_clear;
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 2131febebee93d609df1aea8534a10898b600be2..687190ca11ddeaa83193caa3903a480bac3060d1 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -141,6 +141,8 @@ struct csdev_access {
.base = (_addr), \
})
+#define CORESIGHT_DESC_CPU_BOUND BIT(0)
+
/**
* struct coresight_desc - description of a component required from drivers
* @type: as defined by @coresight_dev_type.
@@ -153,6 +155,8 @@ struct csdev_access {
* in the component's sysfs sub-directory.
* @name: name for the coresight device, also shown under sysfs.
* @access: Describe access to the device
+ * @flags: The descritpion flags.
+ * @cpu: The CPU this component is affined to.
*/
struct coresight_desc {
enum coresight_dev_type type;
@@ -163,6 +167,8 @@ struct coresight_desc {
const struct attribute_group **groups;
const char *name;
struct csdev_access access;
+ u32 flags;
+ int cpu;
};
/**
@@ -260,6 +266,7 @@ struct coresight_trace_id_map {
* device's spinlock when the coresight_mutex held and mode ==
* CS_MODE_SYSFS. Otherwise it must be accessed from inside the
* spinlock.
+ * @cpu: The CPU this component is affined to (-1 for not CPU bound).
* @orphan: true if the component has connections that haven't been linked.
* @sysfs_sink_activated: 'true' when a sink has been selected for use via sysfs
* by writing a 1 to the 'enable_sink' file. A sink can be
@@ -286,6 +293,7 @@ struct coresight_device {
struct device dev;
atomic_t mode;
int refcnt;
+ int cpu;
bool orphan;
/* sink specific fields */
bool sysfs_sink_activated;
--
2.34.1
^ permalink raw reply related
* Re: [PATCH] arm64: defconfig: Enable MT7921S support
From: AngeloGioacchino Del Regno @ 2026-05-11 12:01 UTC (permalink / raw)
To: Matthias Brugger, Gary Bisson
Cc: linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <20260310-mtkdefconfig-v1-1-717eb3e6eea7@gmail.com>
On Tue, 10 Mar 2026 16:52:12 +0100, Gary Bisson wrote:
> Enable MT7921S which is the SDIO variant of the MT7921, also called
> Filogic 320 [1].
> This driver is now used by Tungsten510/700 platforms which are now
> included upstream.
>
> [1] https://www.mediatek.com/products/broadband-wifi/mediatek-filogic-320
>
> [...]
Applied to v7.1-next/defconfig, thanks!
[1/1] arm64: defconfig: Enable MT7921S support
commit: f86e8870547299cb6ee5b8c29d7e35d942b4bc39
Cheers,
Angelo
^ permalink raw reply
* [PATCH v3 1/5] drm/exynos: fbdev: Remove offset into screen_buffer
From: Thomas Zimmermann @ 2026-05-11 11:54 UTC (permalink / raw)
To: inki.dae, sw0312.kim, kyungmin.park, m.szyprowski, wens, airlied,
simona
Cc: dri-devel, linux-samsung-soc, Thomas Zimmermann, linux-arm-kernel,
stable
In-Reply-To: <20260511115538.57884-1-tzimmermann@suse.de>
The screen_buffer field in struct fb_info contains the kernel address
of the first byte of framebuffer memory. Do not add the display offset.
This offset only describes scrolling during scanout.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 19c8b8343d9c ("drm/exynos: fixed overlay data updating.")
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-samsung-soc@vger.kernel.org
Cc: <stable@vger.kernel.org> # v3.2+
---
drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 637927818dfe..d283ded266d5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -61,17 +61,13 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
struct fb_info *fbi = helper->info;
struct drm_framebuffer *fb = helper->fb;
unsigned int size = fb->width * fb->height * fb->format->cpp[0];
- unsigned long offset;
fbi->fbops = &exynos_drm_fb_ops;
drm_fb_helper_fill_info(fbi, helper, sizes);
- offset = fbi->var.xoffset * fb->format->cpp[0];
- offset += fbi->var.yoffset * fb->pitches[0];
-
fbi->flags |= FBINFO_VIRTFB;
- fbi->screen_buffer = exynos_gem->kvaddr + offset;
+ fbi->screen_buffer = exynos_gem->kvaddr;
fbi->screen_size = size;
fbi->fix.smem_len = size;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH] drivers: altera_edac: Guard SDRAM irq2 retrieval for Arria10 only
From: Dinh Nguyen @ 2026-05-11 11:54 UTC (permalink / raw)
To: muhammad.nazim.amirul.nazle.asmade, bp, tony.luck
Cc: linux-edac, linux-arm-kernel, linux-kernel
In-Reply-To: <20260508075240.23638-1-muhammad.nazim.amirul.nazle.asmade@altera.com>
On 5/8/26 02:52, 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>
> Signed-off-by: Niravkumar L Rabara <nirav.rabara@altera.com>
> ---
> drivers/edac/altera_edac.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
> index 4edd2088c2db..b30302198cd4 100644
> --- a/drivers/edac/altera_edac.c
> +++ b/drivers/edac/altera_edac.c
> @@ -348,7 +348,8 @@ static int altr_sdram_probe(struct platform_device *pdev)
> }
>
> /* Arria10 has a 2nd IRQ */
> - irq2 = platform_get_irq(pdev, 1);
> + if (of_machine_is_compatible("altr,socfpga-arria10"))
> + irq2 = platform_get_irq(pdev, 1);
>
> layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
> layers[0].size = 1;
Why? We already switch on arria10 later in the same function.
Sorry, but NAK.
Dinh
^ permalink raw reply
* Re: [PATCH v6 05/25] iommu/arm-smmu-v3: Move IDR parsing to common functions
From: Mostafa Saleh @ 2026-05-11 11:53 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: linux-arm-kernel, linux-kernel, kvmarm, iommu, catalin.marinas,
will, maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
joro, jean-philippe, mark.rutland, qperret, tabba, vdonnefort,
sebastianene, keirf
In-Reply-To: <20260509233443.GK9285@ziepe.ca>
On Sun, May 10, 2026 at 12:34 AM Jason Gunthorpe <jgg@ziepe.ca> wrote:
>
> On Thu, May 07, 2026 at 10:13:13AM +0000, Mostafa Saleh wrote:
> > > I was thinking more like
> > >
> > > #define arm_smmu arm_pkvm_smmu
> > >
> > > Before the pkvm compile of the shared code.
> >
> > Oh, so we rely on arm_pkvm_smmu and arm_smmu having the same field
> > names and types?
>
> Just for the shared code, yes.
>
> For instance this patch would require the features field be present in
> both, and then all you do is directly copy all the smmu->features
> logic into the shared file and that's it.
>
> > I don’t think that’s better for maintainability, I can look into it
> > if Robin and Will are OK with that.
>
> I think maintainability here means pkvm minimizes how much it changes
> the code of the main driver.
>
> Copying a bunch of functions into a shared .c file exactly as it is,
> then compiling the shared file with some #ifdef'ery at is going to be
> long term better than trying to mangle the whole thing to avoid using
> any of the core types and not directly share the code, IMHO.
>
There isn't #ifdef'ery at the moment, that's what I was trying to
avoid by introducing shared code.
I believe that can be treated as a library as most of the shared code
is about HW description (commands, invalidation, IDR probing...)
> Like my tlbi point for instance, it is not a good idea to rip out a
> little bit of the invalidation logic then open code a pkvm
> version. Use the exact driver code. But to do this you need to pass an
> arm_smmu through to to the pkvm specific queue management functions.
>
What concerns me is how fragile that is, any change in the main struct
can easily break the hypervisor, unlike if we have a clear shared code
and defined API that is used by 2 entities.
I will think more about this before v7 and see how intrusive it is.
> > > How does pkvm compilation work anyhow? Is it all rolled into a unique
> > > link, or do you have to worry about symbol conflicts with the main
> > > kernel?
> >
> > All pkvm symbols are prefixed with __kvm_nvhe_ in the main kernel.
>
> So automatically with objcopy or something like that during the build?
>
Exactly: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/kvm/hyp/nvhe/Makefile#n96
Thanks,
Mostafa
> Jason
^ permalink raw reply
* Re: [RFC PATCH] KVM: arm64: vgic: Skip vCPU trylock for pre-init register access
From: David Woodhouse @ 2026-05-11 11:52 UTC (permalink / raw)
To: Yao Yuan
Cc: Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon, Sascha Bischoff,
Paolo Bonzini, Jonathan Cameron, Eric Auger,
Raghavendra Rao Ananta, Maxim Levitsky, linux-arm-kernel, kvmarm,
kvm
In-Reply-To: <3ijnoudux4iyddpd25yr53s2zqrslplixjqfod225ix43y4z4a@heoklijpq45f>
[-- Attachment #1: Type: text/plain, Size: 1454 bytes --]
On Mon, 2026-05-11 at 19:03 +0800, Yao Yuan wrote:
>
> > + /*
> > + * If the VGIC becomes initialized between the above check and taking
> > + * config_lock, drop config_lock to lock the VCPUS.
> > + */
> > + if (vgic_initialized(dev->kvm) && !vcpus_locked) {
> > + mutex_unlock(&dev->kvm->arch.config_lock);
> > + if (kvm_trylock_all_vcpus(dev->kvm)) {
> > + mutex_unlock(&dev->kvm->lock);
> > + return -EBUSY;
> > + }
> > + mutex_lock(&dev->kvm->arch.config_lock);
> > + vcpus_locked = true;
>
> Question: Why not do vgic_initialized(dev->kvm) and
> reg_allowed_pre_init(attr) checking after take config_lock,
> and depends on the checking result to decide trylocak all
> vcpus or not ?
Yeah... I didn't like that either.
If we attempt to take the vCPU locks while *holding* config_lock, that
gives us a classic ABBA deadlock with the code paths that hold the vCPU
locks first.
Well, maybe it doesn't because we'd only be doing a *trylock*... but
lockdep wouldn't know that and it's fugly as hell. So I settled on the
above.
The long term fix, as I noted, is to kill kvm_trylock_all_vcpus() with
fire in *all* cases, not just the !vgic_initialized() case. On x86 we'd
do this with something like KVM_REQ_MCLOCK_INPROGRESS to kick vCPUs out
of guest mode to prevent concurrent access. Which isn't my favourite
code *either* but at least it works without imposing the awfulness on
the userspace API.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply
* Re: [PATCH] arm64: defconfig: Enable MT7921S support
From: Gary Bisson @ 2026-05-11 11:51 UTC (permalink / raw)
To: Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <20260310-mtkdefconfig-v1-1-717eb3e6eea7@gmail.com>
Hi,
On Tue, Mar 10, 2026 at 04:52:12PM +0100, Gary Bisson wrote:
> Enable MT7921S which is the SDIO variant of the MT7921, also called
> Filogic 320 [1].
> This driver is now used by Tungsten510/700 platforms which are now
> included upstream.
>
> [1] https://www.mediatek.com/products/broadband-wifi/mediatek-filogic-320
>
> Signed-off-by: Gary Bisson <bisson.gary@gmail.com>
> ---
> arch/arm64/configs/defconfig | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index b67d5b1fc45b..d469ad15dc69 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -200,6 +200,7 @@ CONFIG_BT_HCIUART_QCA=y
> CONFIG_BT_HCIUART_MRVL=y
> CONFIG_BT_MRVL=m
> CONFIG_BT_MRVL_SDIO=m
> +CONFIG_BT_MTKSDIO=m
> CONFIG_BT_QCOMSMD=m
> CONFIG_BT_NXPUART=m
> CONFIG_CFG80211=m
> @@ -462,6 +463,7 @@ CONFIG_MWIFIEX_SDIO=m
> CONFIG_MWIFIEX_PCIE=m
> CONFIG_MWIFIEX_USB=m
> CONFIG_MT7921E=m
> +CONFIG_MT7921S=m
> CONFIG_RSI_91X=m
> CONFIG_WL18XX=m
> CONFIG_WLCORE_SDIO=m
>
> ---
> base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
> change-id: 20260310-mtkdefconfig-5d9626f242c7
>
> Best regards,
Gentle ping on this request. Let me know if anything is missing.
Regards,
Gary
^ permalink raw reply
* Re: [PATCH v6 1/2] media: dt-bindings: Add CSI Pixel Formatter DT bindings
From: Marco Felsch @ 2026-05-11 11:45 UTC (permalink / raw)
To: Guoniu Zhou
Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Laurent Pinchart, Frank Li, imx,
Krzysztof Kozlowski, devicetree, linux-kernel, Guoniu Zhou,
linux-arm-kernel, linux-media
In-Reply-To: <20260511-csi_formatter-v6-1-01028e312e2b@oss.nxp.com>
On 26-05-11, Guoniu Zhou wrote:
> From: Guoniu Zhou <guoniu.zhou@nxp.com>
>
> The i.MX9 CSI pixel formatting module uses packet info, pixel and
> non-pixel data from the CSI-2 host controller and reformat them to
> match Pixel Link(PL) definition.
Sorry for chiming in very late, but can you please provide on which
i.MX9 devices this formatting module is present? I've checked the i.MX93
reference manual and found no info instead I found a CAMERA_MUX register
which does something similiar but is not the same. Please provide a more
specific compatible if this IP is only be present on i.MX95 devices.
Regards,
Marco
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> Signed-off-by: Guoniu Zhou <guoniu.zhou@nxp.com>
> ---
> .../bindings/media/fsl,imx9-csi-formatter.yaml | 87 ++++++++++++++++++++++
> 1 file changed, 87 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/media/fsl,imx9-csi-formatter.yaml b/Documentation/devicetree/bindings/media/fsl,imx9-csi-formatter.yaml
> new file mode 100644
> index 000000000000..774d37d2b987
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/fsl,imx9-csi-formatter.yaml
> @@ -0,0 +1,87 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/fsl,imx9-csi-formatter.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: i.MX9 CSI Pixel Formatter
> +
> +maintainers:
> + - Guoniu Zhou <guoniu.zhou@nxp.com>
> +
> +description:
> + The CSI pixel formatting module uses packet info, pixel and non-pixel
> + data from the CSI-2 host controller and reformat them to match Pixel
> + Link(PL) definition.
> +
> +properties:
> + compatible:
> + const: fsl,imx9-csi-formatter
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> +
> + power-domains:
> + maxItems: 1
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> +
> + properties:
> + port@0:
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + unevaluatedProperties: false
> + description: MIPI CSI-2 RX IDI interface
> +
> + properties:
> + endpoint:
> + $ref: video-interfaces.yaml#
> + unevaluatedProperties: false
> +
> + port@1:
> + $ref: /schemas/graph.yaml#/properties/port
> + description: Pixel Link Interface
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - power-domains
> + - ports
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/nxp,imx95-clock.h>
> +
> + formatter@20 {
> + compatible = "fsl,imx9-csi-formatter";
> + reg = <0x20 0x100>;
> + clocks = <&cameramix_csr IMX95_CLK_CAMBLK_CSI2_FOR0>;
> + power-domains = <&scmi_devpd 3>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&mipi_csi_0_out>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&isi_in_2>;
> + };
> + };
> + };
> + };
>
> --
> 2.34.1
>
>
>
--
#gernperDu
#CallMeByMyFirstName
Pengutronix e.K. | |
Steuerwalder Str. 21 | https://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
^ permalink raw reply
* Re: [PATCH v6 04/25] iommu/arm-smmu-v3: Move TLB range invalidation into common code
From: Mostafa Saleh @ 2026-05-11 11:45 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: linux-arm-kernel, linux-kernel, kvmarm, iommu, catalin.marinas,
will, maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
joro, jean-philippe, mark.rutland, qperret, tabba, vdonnefort,
sebastianene, keirf
In-Reply-To: <20260509232931.GJ9285@ziepe.ca>
On Sat, May 09, 2026 at 08:29:31PM -0300, Jason Gunthorpe wrote:
> On Thu, May 07, 2026 at 09:40:00AM +0000, Mostafa Saleh wrote:
> > But that doesn’t solve the problem, which is: At some point, whether
> > eagerly from the page table code, through gather sync or a fancy
> > invalidation array, the driver will need to populate a range
> > invalidation command (tg, ttl, scale...) and this logic is better
> > shared with the main driver which is this patch does.
>
> My point is this patch doesn't share enough. If you do need to issue
> invalidations then share everything below the top level tlbi entry
> point and don't try to make a pkvm version of the entire logic just by
> ripping out the range logic.
>
> There is no reason for pkvm to need a different algorithm
> here. Especially when you get to supporting ATS and multiple devices
> and smmus you may as well just use the whole thing.
>
> Which is why I suggested to copy the entire call chain into a shared
> file
Agh, actually this seires doesn't deal with ATS, which I think is
wrong, propably we have to issue CMDQ_OP_ATC_INV for the whole
space on every S2 invalidation which has to be done per-SID and
as it can't be done by VMID :/ or just hide ATS support from host for
now, I will look into more for v7.
But anyway, we don’t have to share any logic, the kernel driver
is quite complicated as it is designed for a different use-case.
Doing that makes the hypervisor unnecessary complicated and
oversharing this logic makes the kernel driver less maintainable IMO.
The hypervisor only needs to share the architecture spec of
populating commands.
If that’s a problem. I am happy to re-write the RIL part in the
hypervisor. It's not that complicated, but I thought it makes sense
to share as it is a HW contract.
Otherwise, we can break this part into some macros that are called
by this function and the hypervisor but that's maybe over-engineered.
Thanks,
Mostafa
>
> Jason
^ permalink raw reply
* Re: [PATCH v2 3/3] arm64: dts: allwinner: A133: add support for Baijie Helper A133 board
From: Andre Przywara @ 2026-05-11 11:44 UTC (permalink / raw)
To: Alexander Sverdlin, linux-sunxi
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, devicetree, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260510201644.4143710-4-alexander.sverdlin@gmail.com>
Hi Alexander,
thanks for upstreaming the DTs!
On 5/10/26 22:16, Alexander Sverdlin wrote:
> Baijie Helper A133 board is a development board around Baijie A133 Core
> SBC. Features:
>
> - 1/2/4GiB LPDDR4 DRAM
> - 8/16/32GiB eMMC
> - AXP707 PMIC
> - 2 USB 2.0 ports
> - MicroSD slot and on-board eMMC module
> - Gigabit Ethernet
> - Bluetooth
> - WiFi
>
> Add initial support for both the Helper and Core boards, including UART,
> PMU, eMMC, USB, Ethernet.
>
> Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
> ---
>
> Changelog:
> v2:
> - introduced baijie,helper-a133-core compatible for the Core (SoM) board
>
> arch/arm64/boot/dts/allwinner/Makefile | 1 +
> .../dts/allwinner/sun50i-a133-baije-core.dtsi | 162 ++++++++++++++++++
> .../allwinner/sun50i-a133-baijie-helper.dts | 94 ++++++++++
> 3 files changed, 257 insertions(+)
> create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-baije-core.dtsi
> create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-baijie-helper.dts
>
> diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
> index d116864b6c2b..926dfa851100 100644
> --- a/arch/arm64/boot/dts/allwinner/Makefile
> +++ b/arch/arm64/boot/dts/allwinner/Makefile
> @@ -18,6 +18,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h64-remix-mini-pc.dtb
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a100-allwinner-perf1.dtb
> +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a133-baijie-helper.dtb
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a133-liontron-h-a133l.dtb
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus.dtb
> dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus-v1.2.dtb
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-baije-core.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a133-baije-core.dtsi
> new file mode 100644
> index 000000000000..65b094f30bf5
> --- /dev/null
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-baije-core.dtsi
> @@ -0,0 +1,162 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright (c) 2025 Arm Ltd.
Please put your own copyright here, even if that has been largely copied
from an existing file.
> + */
> +
> +/dts-v1/;
> +
> +#include "sun50i-a100.dtsi"
> +#include "sun50i-a100-cpu-opp.dtsi"
> +
> +/{
> + compatible = "baijie,helper-a133-core",
> + "allwinner,sun50i-a100";
> +
> + aliases {
> + serial1 = &uart1; /* BT module */
Do we really need an alias for the BT UART? And is the BT module
supported already? Then please add a child node to the UART node.
> + };
> +};
> +
> +&cpu0 {
> + cpu-supply = <®_dcdc2>;
> +};
> +
> +&pio {
The order of those referenced nodes is alphabetically by the label name.
So this one goes further down.
> + vcc-pb-supply = <®_dcdc1>;
> + vcc-pc-supply = <®_eldo1>;
> + vcc-pd-supply = <®_dcdc1>;
> + vcc-pe-supply = <®_dldo2>;
> + vcc-pf-supply = <®_dcdc1>;
> + vcc-pg-supply = <®_dldo1>;
> + vcc-ph-supply = <®_dcdc1>;
> +};
> +
Isn't the WiFi/BT module on the SoM? Then please mention and enable MMC1
here. Provide the child node for the WiFi chip, even if there is no
upstream support in the kernel for it yet.
> +&mmc2 {
> + vmmc-supply = <®_dcdc1>;
> + vqmmc-supply = <®_eldo1>;
> + cap-mmc-hw-reset;
> + non-removable;
> + bus-width = <8>;
> + mmc-ddr-1_8v;
> + mmc-hs200-1_8v;
> + status = "okay";
> +};
> +
> +&r_i2c0 {
> + status = "okay";
> +
> + axp803: pmic@34 {
> + compatible = "x-powers,axp803";
> + reg = <0x34>;
> + interrupt-parent = <&r_intc>;
> + interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
> + };
> +};
> +
> +#include "axp803.dtsi"
> +
> +&ac_power_supply {
> + status = "okay";
> +};
> +
> +®_aldo1 {
What is aldo1 used for, actually? I don't see this referenced anywhere.
I guess the kernel turns that off after booting?
If you have access to the schematic, please check that. If that's for
some peripheral not yet supported, please note the user anyway, ideally
by an explaining regulator-name, or by a comment. Also if it's used for
any of the required SoC VDD pins. See the Liontron .dts for comparison.
> + regulator-always-on;
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <3300000>;
Please don't provide ranges here (those are in the driver already), the
point of this entry is to set the voltage required by the board. (And
yes, the vendor DTBs alway get this wrong). Typically there are fixed
requirements, so use the same value for min and max.
Same for the others below.
> +};
> +
> +®_aldo2 {
> + regulator-always-on;
For always-on regulators we definitely need an explanation. Does the
board stop booting if you remove this line?
Maybe it's for DRAM? Can you say what voltage it is, either from the
reset default, or set by the bootloader?
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <3300000>;
> +};
> +
> +®_aldo3 {
> + regulator-always-on;
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-enable-ramp-delay = <1000>;
> +};
> +
> +®_dcdc1 {
> + regulator-always-on;
> + regulator-min-microvolt = <1600000>;
> + regulator-max-microvolt = <3400000>;
> + regulator-name = "vcc-3v3";
> +};
> +
> +®_dcdc2 {
> + regulator-always-on;
> + regulator-min-microvolt = <500000>;
> + regulator-max-microvolt = <1300000>;
This one is an exception, because the voltage is to be adjusted at
runtime. But the voltage range needs to be tighter, the A133 datasheet
puts the valid VDD_CPU range between 810mV and 1200mV.
Compare to the Liontron dts file here.
> + regulator-name = "vdd-cpu";
> +};
> +
> +®_dcdc3 {
> + regulator-always-on;
> + regulator-min-microvolt = <500000>;
> + regulator-max-microvolt = <1300000>;
> +};
> +
> +®_dcdc4 {
> + regulator-always-on;
> + regulator-min-microvolt = <500000>;
> + regulator-max-microvolt = <1300000>;
> + regulator-name = "vdd-sys";
> +};
> +
> +®_dcdc5 {
> + regulator-always-on;
> + regulator-min-microvolt = <800000>;
> + regulator-max-microvolt = <1840000>;
> + regulator-name = "vcc-dram";
> +};
> +
> +/* DCDC6 unused */
> +
> +®_dldo1 {
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-enable-ramp-delay = <1000>;
> +};
> +
> +®_dldo2 {
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <3400000>;
> + regulator-enable-ramp-delay = <1000>;
> +};
> +
> +®_dldo3 {
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-enable-ramp-delay = <1000>;
> + regulator-name = "avdd-csi";
> +};
> +
> +®_dldo4 {
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-enable-ramp-delay = <1000>;
> +};
> +
> +®_eldo1 {
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <1900000>;
> + regulator-enable-ramp-delay = <1000>;
> +};
> +
> +®_eldo2 {
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <1900000>;
> + regulator-enable-ramp-delay = <1000>;
> + regulator-name = "dvdd-csi";
> +};
> +
> +/* ELDO3 unused */
> +
> +®_fldo1 {
> + regulator-always-on;
> + regulator-min-microvolt = <700000>;
> + regulator-max-microvolt = <1450000>;
> + regulator-name = "vdd-cpus-usb";
> +};
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-baijie-helper.dts b/arch/arm64/boot/dts/allwinner/sun50i-a133-baijie-helper.dts
> new file mode 100644
> index 000000000000..ccbca5d0a40c
> --- /dev/null
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-baijie-helper.dts
> @@ -0,0 +1,94 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright (c) 2025 Arm Ltd.
Your own copyright, please.
> + */
> +
> +/dts-v1/;
> +
> +#include "sun50i-a133-baije-core.dtsi"
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/leds/common.h>
> +
> +/{
> + model = "HelperBoard A133";
> + compatible = "baijie,helper-a133",
> + "baijie,helper-a133-core",
> + "allwinner,sun50i-a100";
> +
> + aliases {
> + serial0 = &uart0;
> + };
> +
> + chosen {
> + stdout-path = "serial0:115200n8";
> + };
> +
> + leds {
> + compatible = "gpio-leds";
> +
> + led {
> + function = LED_FUNCTION_INDICATOR;
> + color = <LED_COLOR_ID_GREEN>;
> + gpios = <&pio 7 13 GPIO_ACTIVE_LOW>; /* PH13 */
> + };
> + };
I see quite some buttons on the board. I guess they are connected to
GPIOs? Can you please describe them then, using gpio-keys? Look at
sun50i-h5-orangepi-pc2.dts for an example.
And you should provide a top level 5V regulator here, to be the root of
the regulator tree. Look at reg_vcc5v in the Liontron .dts.
> +};
> +
> +&mmc0 {
> + vmmc-supply = <®_dcdc1>;
> + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
> + bus-width = <4>;
> + status = "okay";
> +};
> +
> +&uart0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart0_pb_pins>;
> + status = "okay";
> +};
> +
> +&rgmii0_pins {
> + drive-strength = <30>;
> +};
> +
> +&emac0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&rgmii0_pins>;
> + phy-handle = <ð_phy>;
> + phy-mode = "rgmii-id";
> + allwinner,rx-delay-ps = <200>;
> + allwinner,tx-delay-ps = <200>;
> + status = "okay";
> +};
> +
> +&mdio0 {
> + reset-gpios = <&pio 7 11 GPIO_ACTIVE_LOW>; /* PH11 */
> + reset-delay-us = <10000>;
> + reset-post-delay-us = <150000>;
> +
> + eth_phy: ethernet-phy@1 {
The typical label here would be rgmii_phy. The node name is correct, though.
> + compatible = "ethernet-phy-ieee802.3-c22";
> + reg = <1>;
> + };
> +};
> +
So from the pictures I found online it looks like there is an USB-C port
labelled "OTG", so can you please add an &usbotg reference here and
describe that port.
> +&usbphy {
Are the two USB ports always powered?
And anyway, I see a *dual* USB-A socket on the pictures online, in
addition to the USB-OTG port. So where does the third USB come from? The
A133 only supports one host USB port plus the one OTG port. So is there
an USB hub chip on the board?
> + status = "okay";
> +};
> +
> +&ehci0 {
(and again, please order those nodes alphabetically)
Cheers,
Andre.
> + status = "okay";
> +};
> +
> +&ohci0 {
> + status = "okay";
> +};
> +
> +&ehci1 {
> + status = "okay";
> +};
> +
> +&ohci1 {
> + status = "okay";
> +};
^ permalink raw reply
* [PATCH v12 12/28] coresight: etm4x: Hook CPU PM callbacks
From: Leo Yan @ 2026-05-11 11:10 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Yeoreum Yun,
Mark Rutland, Will Deacon, Yabin Cui, Keita Morisaki, Jie Gan,
Yuanfang Zhang, Greg Kroah-Hartman, Alexander Shishkin,
Tamas Petz, Thomas Gleixner, Peter Zijlstra
Cc: coresight, linux-arm-kernel, Leo Yan
In-Reply-To: <20260511-arm_coresight_path_power_management_improvement-v12-0-1c9dcb1de8c9@arm.com>
Add a helper etm4_pm_save_needed() to detect if need save context for
self-hosted PM mode and hook pm_save_disable() and pm_restore_enable()
callbacks through etm4_cs_pm_ops structure. With this, ETMv4 PM
save/restore is integrated into the core layer's CPU PM.
Organize etm4_cs_ops and etm4_cs_pm_ops together for more readable.
The CPU PM notifier in the ETMv4 driver is no longer needed, remove it
along with its registration and unregistration code.
Reviewed-by: James Clark <james.clark@linaro.org>
Tested-by: James Clark <james.clark@linaro.org>
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Tested-by: Jie Gan <jie.gan@oss.qualcomm.com>
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 73 +++++++---------------
1 file changed, 23 insertions(+), 50 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 7011a20d20042cfbeaac51797cd8592275bbf1ca..5cd70f0f3710a5ec6406a89c034d30230f782b13 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1195,11 +1195,6 @@ static const struct coresight_ops_source etm4_source_ops = {
.pause_perf = etm4_pause_perf,
};
-static const struct coresight_ops etm4_cs_ops = {
- .trace_id = coresight_etm_get_trace_id,
- .source_ops = &etm4_source_ops,
-};
-
static bool cpu_supports_sysreg_trace(void)
{
u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
@@ -1853,6 +1848,11 @@ static int etm4_dying_cpu(unsigned int cpu)
return 0;
}
+static inline bool etm4_pm_save_needed(struct etmv4_drvdata *drvdata)
+{
+ return !!drvdata->save_state;
+}
+
static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
{
int i, ret = 0;
@@ -1995,11 +1995,12 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
return ret;
}
-static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
+static int etm4_cpu_save(struct coresight_device *csdev)
{
+ struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
int ret = 0;
- if (!drvdata->save_state)
+ if (!etm4_pm_save_needed(drvdata))
return 0;
/*
@@ -2112,47 +2113,27 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
etm4_cs_lock(drvdata, csa);
}
-static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
+static void etm4_cpu_restore(struct coresight_device *csdev)
{
- if (!drvdata->save_state)
+ struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ if (!etm4_pm_save_needed(drvdata))
return;
if (coresight_get_mode(drvdata->csdev))
__etm4_cpu_restore(drvdata);
}
-static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
- void *v)
-{
- struct etmv4_drvdata *drvdata;
- unsigned int cpu = smp_processor_id();
-
- if (!etmdrvdata[cpu])
- return NOTIFY_OK;
-
- drvdata = etmdrvdata[cpu];
-
- if (WARN_ON_ONCE(drvdata->cpu != cpu))
- return NOTIFY_BAD;
-
- switch (cmd) {
- case CPU_PM_ENTER:
- if (etm4_cpu_save(drvdata))
- return NOTIFY_BAD;
- break;
- case CPU_PM_EXIT:
- case CPU_PM_ENTER_FAILED:
- etm4_cpu_restore(drvdata);
- break;
- default:
- return NOTIFY_DONE;
- }
-
- return NOTIFY_OK;
-}
+static const struct coresight_ops etm4_cs_ops = {
+ .trace_id = coresight_etm_get_trace_id,
+ .source_ops = &etm4_source_ops,
+};
-static struct notifier_block etm4_cpu_pm_nb = {
- .notifier_call = etm4_cpu_pm_notify,
+static const struct coresight_ops etm4_cs_pm_ops = {
+ .trace_id = coresight_etm_get_trace_id,
+ .source_ops = &etm4_source_ops,
+ .pm_save_disable = etm4_cpu_save,
+ .pm_restore_enable = etm4_cpu_restore,
};
/* Setup PM. Deals with error conditions and counts */
@@ -2160,16 +2141,12 @@ static int __init etm4_pm_setup(void)
{
int ret;
- ret = cpu_pm_register_notifier(&etm4_cpu_pm_nb);
- if (ret)
- return ret;
-
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
"arm/coresight4:starting",
etm4_starting_cpu, etm4_dying_cpu);
if (ret)
- goto unregister_notifier;
+ return ret;
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"arm/coresight4:online",
@@ -2183,15 +2160,11 @@ static int __init etm4_pm_setup(void)
/* failed dyn state - remove others */
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
-
-unregister_notifier:
- cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
return ret;
}
static void etm4_pm_clear(void)
{
- cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
if (hp_online) {
cpuhp_remove_state_nocalls(hp_online);
@@ -2270,7 +2243,7 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
desc.type = CORESIGHT_DEV_TYPE_SOURCE;
desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
- desc.ops = &etm4_cs_ops;
+ desc.ops = etm4_pm_save_needed(drvdata) ? &etm4_cs_pm_ops : &etm4_cs_ops;
desc.pdata = pdata;
desc.dev = dev;
desc.groups = coresight_etmv4_groups;
--
2.34.1
^ permalink raw reply related
* [PATCH v3 0/4] KVM: arm64: vgic: Fix IGROUPR writability and IIDR revision control
From: David Woodhouse @ 2026-05-11 11:30 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Jonathan Corbet, Shuah Khan, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Will Deacon, Jonathan Cameron, Sascha Bischoff, Eric Auger,
Raghavendra Rao Ananta, Maxim Levitsky, David Woodhouse,
Kees Cook, Timothy Hayes, Arnd Bergmann, kvm, linux-doc,
linux-kernel, linux-arm-kernel, kvmarm, linux-kselftest,
Peter Maydell, qemu-arm, qemu-devel
Maintaining precise guest compatibility across host kernel upgrades —
and even downgrades, since rollback is sometimes necessary — is not
optional. That *shouldn't* need saying, but maybe it does:
https://lore.kernel.org/all/6856b269d2af706eae397e0cf9c1231f89d9a932.camel@infradead.org/
This series fixes the GICv2/v3 IGROUPR writability model to be
consistently controlled by the GICD_IIDR implementation revision,
replacing the ad-hoc v2_groups_user_writable flag.
Before commit d53c2c29ae0d ("KVM: arm/arm64: vgic: Allow configuration
of interrupt groups"), IGROUPR was read-only on both GICv2 and GICv3.
That commit made it unconditionally guest-writable, but provided no
mechanism for userspace to restore the previous behaviour for guests
that were launched on older kernels (which which might need to be
migrated back to older kernels).
The v2_groups_user_writable flag (added by 32f8777ed92d) attempted to
gate GICv2 userspace IGROUPR writes until userspace wrote the IIDR,
but the guest write path was never gated, creating an inconsistency
where the guest could modify groups that userspace couldn't save or
restore. QEMU never writes GICD_IIDR, so its GICv2 IGROUPR
save/restore (QEMU commit eb8b9530b0c) appears to be silently broken.
This series:
- Allows userspace to set IIDR revision 1, to restore the original
read-only IGROUPR behaviour for both GICv2 and GICv3 (patch 1)
- Removes v2_groups_user_writable and makes both guest and userspace
writability follow the IIDR revision directly (patch 3)
- Adds selftests covering IIDR revision semantics and a QEMU-style
save/restore scenario (patches 2, 4)
Tested on EC2 c7g.metal (GICv3 native) and under QEMU-TCG (GICv2).
David Woodhouse (4):
KVM: arm64: vgic: Allow userspace to set IIDR revision 1
KVM: arm64: selftests: Add vgic IIDR revision test
KVM: arm64: vgic: Remove v2_groups_user_writable and use IIDR revision directly
KVM: arm64: selftests: Add GICv2 IGROUPR writability test
arch/arm64/kvm/vgic/vgic-mmio-v2.c | 15 +-
arch/arm64/kvm/vgic/vgic-mmio-v3.c | 4 +
arch/arm64/kvm/vgic/vgic-mmio.c | 4 +
include/kvm/arm_vgic.h | 4 +-
tools/testing/selftests/kvm/Makefile.kvm | 2 +
.../testing/selftests/kvm/arm64/vgic_group_iidr.c | 118 +++++++++++
tools/testing/selftests/kvm/arm64/vgic_group_v2.c | 226 +++++++++++++++++++++
7 files changed, 361 insertions(+), 12 deletions(-)
^ permalink raw reply
* [PATCH v3 3/4] KVM: arm64: vgic: Remove v2_groups_user_writable and use IIDR revision directly
From: David Woodhouse @ 2026-05-11 11:30 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Jonathan Corbet, Shuah Khan, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Will Deacon, Jonathan Cameron, Sascha Bischoff, Eric Auger,
Raghavendra Rao Ananta, Maxim Levitsky, David Woodhouse,
Kees Cook, Timothy Hayes, Arnd Bergmann, kvm, linux-doc,
linux-kernel, linux-arm-kernel, kvmarm, linux-kselftest,
Peter Maydell, qemu-arm, qemu-devel
In-Reply-To: <20260511113558.3325004-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
The v2_groups_user_writable flag was introduced to gate GICv2 userspace
IGROUPR writes until userspace explicitly wrote the IIDR, signalling
awareness of the group semantics. However, the guest write path through
vgic_mmio_write_group() was never gated by this flag, allowing a GICv2
guest to modify interrupt groups regardless of whether userspace had
opted in.
Rather than adding the same flag check to the guest path, remove the
flag entirely and make both guest and userspace IGROUPR writability
follow the IIDR implementation revision directly. Groups are writable
when the revision is >= 2, which is the case when userspace explicitly
sets the IIDR to revision 2 or 3. When userspace does not write the
IIDR, vgic_init() defaults to KVM_VGIC_IMP_REV_LATEST (currently 3),
so the behaviour is unchanged for userspace that doesn't set the IIDR.
This also fixes the inconsistency where GICv2 userspace could not write
IGROUPR at the default revision, even though the guest could.
As far as I can tell, QEMU commit eb8b9530b0c ("hw/intc/arm_gic_kvm.c:
Save and restore GICD_IGROUPRn state") made QEMU attempt to save/restore
the GICD_IGROUPR registers (which, again, are guest-writable but not
userspace-writable by default) without ever actually setting GICD_IIDR.
Fixes: 32f8777ed92d ("KVM: arm/arm64: vgic: Let userspace opt-in to writable v2 IGROUPR")
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/arm64/kvm/vgic/vgic-mmio-v2.c | 16 +++++-----------
include/kvm/arm_vgic.h | 3 ---
2 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
index e5714f7fd2ec..e5fc673a1ea9 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
@@ -84,21 +84,15 @@ static int vgic_mmio_uaccess_write_v2_misc(struct kvm_vcpu *vcpu,
return -EINVAL;
/*
- * If we observe a write to GICD_IIDR we know that userspace
- * has been updated and has had a chance to cope with older
- * kernels (VGICv2 IIDR.Revision == 0) incorrectly reporting
- * interrupts as group 1, and therefore we now allow groups to
- * be user writable. Doing this by default would break
- * migration from old kernels to new kernels with legacy
- * userspace.
+ * Allow userspace to select the GICv2 IIDR revision.
+ * Group writability follows the revision directly:
+ * groups are guest/user writable for revision >= 2.
*/
reg = FIELD_GET(GICD_IIDR_REVISION_MASK, val);
switch (reg) {
+ case KVM_VGIC_IMP_REV_1:
case KVM_VGIC_IMP_REV_2:
case KVM_VGIC_IMP_REV_3:
- vcpu->kvm->arch.vgic.v2_groups_user_writable = true;
- fallthrough;
- case KVM_VGIC_IMP_REV_1:
dist->implementation_rev = reg;
return 0;
default:
@@ -114,7 +108,7 @@ static int vgic_mmio_uaccess_write_v2_group(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val)
{
- if (vcpu->kvm->arch.vgic.v2_groups_user_writable)
+ if (vgic_get_implementation_rev(vcpu) >= KVM_VGIC_IMP_REV_2)
vgic_mmio_write_group(vcpu, addr, len, val);
return 0;
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 16811ec03d54..a9490e43d98d 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -377,9 +377,6 @@ struct vgic_dist {
#define KVM_VGIC_IMP_REV_3 3 /* GICv3 GICR_CTLR.{IW,CES,RWP} */
#define KVM_VGIC_IMP_REV_LATEST KVM_VGIC_IMP_REV_3
- /* Userspace can write to GICv2 IGROUPR */
- bool v2_groups_user_writable;
-
/* Do injected MSIs require an additional device ID? */
bool msis_require_devid;
--
2.51.0
^ permalink raw reply related
* [PATCH v3 4/4] KVM: arm64: selftests: Add GICv2 IGROUPR writability test
From: David Woodhouse @ 2026-05-11 11:30 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Jonathan Corbet, Shuah Khan, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Will Deacon, Jonathan Cameron, Sascha Bischoff, Eric Auger,
Raghavendra Rao Ananta, Maxim Levitsky, David Woodhouse,
Kees Cook, Timothy Hayes, Arnd Bergmann, kvm, linux-doc,
linux-kernel, linux-arm-kernel, kvmarm, linux-kselftest,
Peter Maydell, qemu-arm, qemu-devel
In-Reply-To: <20260511113558.3325004-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
Test that GICv2 IGROUPR writability is consistently gated by the IIDR
implementation revision for both guest and userspace paths:
Default (no IIDR write): implementation_rev defaults to 3, groups
writable from both guest and userspace.
Rev 1: IGROUPR reads as zero (group 0), writes ignored from both
guest and userspace.
Rev 2: IGROUPR is writable from both guest and userspace.
This test requires GICv2 emulation support (GICv3 with GICv2 compat
CPU interface) and will be skipped on hardware without it.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
tools/testing/selftests/kvm/Makefile.kvm | 1 +
.../selftests/kvm/arm64/vgic_group_v2.c | 226 ++++++++++++++++++
2 files changed, 227 insertions(+)
create mode 100644 tools/testing/selftests/kvm/arm64/vgic_group_v2.c
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 8cadfed4d79a..6bc295d0b776 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -178,6 +178,7 @@ TEST_GEN_PROGS_arm64 += arm64/set_id_regs
TEST_GEN_PROGS_arm64 += arm64/smccc_filter
TEST_GEN_PROGS_arm64 += arm64/vcpu_width_config
TEST_GEN_PROGS_arm64 += arm64/vgic_group_iidr
+TEST_GEN_PROGS_arm64 += arm64/vgic_group_v2
TEST_GEN_PROGS_arm64 += arm64/vgic_init
TEST_GEN_PROGS_arm64 += arm64/vgic_irq
TEST_GEN_PROGS_arm64 += arm64/vgic_lpi_stress
diff --git a/tools/testing/selftests/kvm/arm64/vgic_group_v2.c b/tools/testing/selftests/kvm/arm64/vgic_group_v2.c
new file mode 100644
index 000000000000..f2b384a816ba
--- /dev/null
+++ b/tools/testing/selftests/kvm/arm64/vgic_group_v2.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * vgic_group_v2.c - Test GICv2 IGROUPR behaviour across IIDR revisions
+ *
+ * Validate that the GICD_IIDR implementation revision controls GICv2
+ * IGROUPR writability for both guest and userspace:
+ * Default (no IIDR write): groups writable (implementation_rev defaults to 3)
+ * Rev 1: IGROUPR reads as zero (group 0), writes ignored
+ * Rev 2: IGROUPR is guest and userspace configurable
+ */
+#include <linux/sizes.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "processor.h"
+#include "gic.h"
+#include "gic_v3.h"
+#include "vgic.h"
+
+#define NR_IRQS 64
+
+#define V2_DIST_BASE 0x8000000ULL
+#define V2_CPU_BASE 0x8010000ULL
+#define V2_DIST_GVA ((volatile void *)V2_DIST_BASE)
+
+#define SPI_IGROUPR (GICD_IGROUPR + (32 / 32) * 4)
+
+static uint64_t shared_rev;
+static uint64_t guest_result;
+
+static void guest_code(void)
+{
+ uint32_t before, after;
+
+ before = readl(V2_DIST_GVA + SPI_IGROUPR);
+ writel(0x5a5a5a5a, V2_DIST_GVA + SPI_IGROUPR);
+ after = readl(V2_DIST_GVA + SPI_IGROUPR);
+
+ guest_result = ((uint64_t)before << 32) | after;
+ GUEST_DONE();
+}
+
+static int create_v2_gic(struct kvm_vm *vm)
+{
+ uint32_t nr_irqs = NR_IRQS;
+ uint64_t addr;
+ int gic_fd;
+
+ gic_fd = __kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V2);
+ if (gic_fd < 0)
+ return gic_fd;
+
+ addr = V2_DIST_BASE;
+ kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_V2_ADDR_TYPE_DIST, &addr);
+ addr = V2_CPU_BASE;
+ kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_V2_ADDR_TYPE_CPU, &addr);
+
+ virt_map(vm, V2_DIST_BASE, V2_DIST_BASE,
+ vm_calc_num_guest_pages(vm->mode, SZ_64K));
+ virt_map(vm, V2_CPU_BASE, V2_CPU_BASE,
+ vm_calc_num_guest_pages(vm->mode, SZ_64K));
+
+ kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
+ 0, &nr_irqs);
+ return gic_fd;
+}
+
+static void run_test(int set_iidr_rev)
+{
+ struct kvm_vcpu *vcpus[1];
+ struct kvm_vm *vm;
+ struct ucall uc;
+ uint32_t before, after, igroupr, iidr;
+ int gic_fd;
+ bool expect_writable;
+
+ if (set_iidr_rev >= 0)
+ pr_info("Testing GICv2 IIDR revision %d\n", set_iidr_rev);
+ else
+ pr_info("Testing GICv2 IIDR default (no write)\n");
+
+ test_disable_default_vgic();
+ vm = vm_create_with_vcpus(1, guest_code, vcpus);
+
+ gic_fd = create_v2_gic(vm);
+ TEST_REQUIRE(gic_fd >= 0);
+
+ if (set_iidr_rev >= 0) {
+ kvm_device_attr_get(gic_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ GICD_IIDR, &iidr);
+ iidr &= ~GICD_IIDR_REVISION_MASK;
+ iidr |= set_iidr_rev << GICD_IIDR_REVISION_SHIFT;
+ kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ GICD_IIDR, &iidr);
+ }
+
+ kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
+
+ /*
+ * Default (no IIDR write) gets implementation_rev=3 from vgic_init(),
+ * so groups should be writable. Rev 1 = not writable. Rev 2+ = writable.
+ */
+ expect_writable = (set_iidr_rev != 1);
+
+ /* Test userspace IGROUPR write */
+ igroupr = 0xa5a5a5a5;
+ kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ SPI_IGROUPR, &igroupr);
+ igroupr = 0;
+ kvm_device_attr_get(gic_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ SPI_IGROUPR, &igroupr);
+
+ if (expect_writable)
+ TEST_ASSERT(igroupr == 0xa5a5a5a5,
+ "Userspace write should succeed: got 0x%08x", igroupr);
+ else
+ TEST_ASSERT(igroupr == 0x00000000,
+ "Userspace write should be ignored: got 0x%08x", igroupr);
+
+ /* Reset IGROUPR to 0 via userspace for rev 2+ before guest test */
+ if (expect_writable) {
+ igroupr = 0;
+ kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ SPI_IGROUPR, &igroupr);
+ }
+
+ /* Test guest IGROUPR write */
+ sync_global_to_guest(vm, guest_result);
+ vcpu_run(vcpus[0]);
+
+ switch (get_ucall(vcpus[0], &uc)) {
+ case UCALL_ABORT:
+ REPORT_GUEST_ASSERT(uc);
+ break;
+ case UCALL_DONE:
+ break;
+ default:
+ TEST_FAIL("Unexpected ucall %lu", uc.cmd);
+ }
+
+ sync_global_from_guest(vm, guest_result);
+ before = guest_result >> 32;
+ after = guest_result & 0xffffffff;
+
+ TEST_ASSERT(before == 0x00000000,
+ "Initial IGROUPR should be 0 (group 0): got 0x%08x", before);
+
+ if (expect_writable)
+ TEST_ASSERT(after == 0x5a5a5a5a,
+ "Guest write should succeed: got 0x%08x", after);
+ else
+ TEST_ASSERT(after == 0x00000000,
+ "Guest write should be ignored: got 0x%08x", after);
+
+ close(gic_fd);
+ kvm_vm_free(vm);
+}
+
+/*
+ * Test QEMU-style save/restore: the guest writes IGROUPR, then userspace
+ * reads it back (save) and writes it again (restore) — all without ever
+ * writing GICD_IIDR. This exercises the bug where v2_groups_user_writable
+ * gated userspace writes but not guest writes, so userspace could observe
+ * guest-modified groups but couldn't restore them.
+ */
+static void run_save_restore_test(void)
+{
+ struct kvm_vcpu *vcpus[1];
+ struct kvm_vm *vm;
+ struct ucall uc;
+ uint32_t igroupr;
+ int gic_fd;
+
+ pr_info("Testing GICv2 IGROUPR save/restore (no IIDR write)\n");
+
+ test_disable_default_vgic();
+ vm = vm_create_with_vcpus(1, guest_code, vcpus);
+
+ gic_fd = create_v2_gic(vm);
+ TEST_REQUIRE(gic_fd >= 0);
+
+ /* Do NOT write GICD_IIDR — mimicking QEMU */
+
+ kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
+
+ /* Let the guest write 0x5a5a5a5a to IGROUPR */
+ sync_global_to_guest(vm, guest_result);
+ vcpu_run(vcpus[0]);
+ TEST_ASSERT(get_ucall(vcpus[0], &uc) == UCALL_DONE,
+ "Guest failed");
+
+ /* Save: userspace reads IGROUPR — should see guest's write */
+ igroupr = 0;
+ kvm_device_attr_get(gic_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ SPI_IGROUPR, &igroupr);
+ TEST_ASSERT(igroupr == 0x5a5a5a5a,
+ "Save: expected 0x5a5a5a5a, got 0x%08x", igroupr);
+
+ /* Restore: userspace writes a different value — should succeed */
+ igroupr = 0x12345678;
+ kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ SPI_IGROUPR, &igroupr);
+
+ /* Verify: read back should reflect the restore */
+ igroupr = 0;
+ kvm_device_attr_get(gic_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ SPI_IGROUPR, &igroupr);
+ TEST_ASSERT(igroupr == 0x12345678,
+ "Restore: expected 0x12345678, got 0x%08x", igroupr);
+
+ close(gic_fd);
+ kvm_vm_free(vm);
+}
+
+int main(int argc, char *argv[])
+{
+ run_test(-1); /* default */
+ run_test(1); /* rev 1 */
+ run_test(2); /* rev 2 */
+ run_save_restore_test();
+ return 0;
+}
--
2.51.0
^ permalink raw reply related
* [PATCH v3 1/4] KVM: arm64: vgic: Allow userspace to set IIDR revision 1
From: David Woodhouse @ 2026-05-11 11:30 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Jonathan Corbet, Shuah Khan, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Will Deacon, Jonathan Cameron, Sascha Bischoff, Eric Auger,
Raghavendra Rao Ananta, Maxim Levitsky, David Woodhouse,
Kees Cook, Timothy Hayes, Arnd Bergmann, kvm, linux-doc,
linux-kernel, linux-arm-kernel, kvmarm, linux-kselftest,
Peter Maydell, qemu-arm, qemu-devel
In-Reply-To: <20260511113558.3325004-1-dwmw2@infradead.org>
From: David Woodhouse <dwmw@amazon.co.uk>
In order to preserve guest compatibility across kernel upgrades, allow
userspace to select GICD_IIDR revision 1. This allows compatibility with
the original behaviour from before commit d53c2c29ae0d ("KVM: arm/arm64:
vgic: Allow configuration of interrupt groups") where interrupt groups
are not guest-configurable.
When revision 1 is selected:
- GICv2: IGROUPR reads as zero (group 0), writes are ignored
- GICv3: IGROUPR reads as all-ones (group 1), writes are ignored
- v2_groups_user_writable is not set
This is implemented by checking the implementation revision in
vgic_mmio_write_group() and suppressing writes when the revision is
below 2. The read side needs no change since the per-IRQ group reset
values already match the expected behaviour.
For GICv2, commit 32f8777ed92d7 ("KVM: arm/arm64: vgic: Let userspace
opt-in to writable v2 IGROUPR") introduced a confusing model where
IGROUPR registers were not writable from userspace by default until the
IIDR was written — even if it was written to the *same* as its default
value (which, in fact, was the only thing that userspace *could* set it
to before commit a0e6ae45af17 fixed the IIDR write path). Furthermore,
even when the v2_groups_user_writable flag wasn't set, the *guest*
could still actually write to the registers... but userspace couldn't
save/restore them. That default behaviour for GICv2 remains unchanged;
it can be fixed in a future commit.
Fixes: d53c2c29ae0d ("KVM: arm/arm64: vgic: Allow configuration of interrupt groups")
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/arm64/kvm/vgic/vgic-mmio-v2.c | 3 +++
arch/arm64/kvm/vgic/vgic-mmio-v3.c | 4 ++++
arch/arm64/kvm/vgic/vgic-mmio.c | 4 ++++
include/kvm/arm_vgic.h | 1 +
4 files changed, 12 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
index 0643e333db35..e5714f7fd2ec 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
@@ -20,6 +20,7 @@
* Revision 1: Report GICv2 interrupts as group 0 instead of group 1
* Revision 2: Interrupt groups are guest-configurable and signaled using
* their configured groups.
+ * Revision 3: GICv2 behaviour is unchanged from revision 2.
*/
static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
@@ -96,6 +97,8 @@ static int vgic_mmio_uaccess_write_v2_misc(struct kvm_vcpu *vcpu,
case KVM_VGIC_IMP_REV_2:
case KVM_VGIC_IMP_REV_3:
vcpu->kvm->arch.vgic.v2_groups_user_writable = true;
+ fallthrough;
+ case KVM_VGIC_IMP_REV_1:
dist->implementation_rev = reg;
return 0;
default:
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index 5913a20d8301..0130db71cfc9 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -74,8 +74,11 @@ bool vgic_supports_direct_sgis(struct kvm *kvm)
/*
* The Revision field in the IIDR have the following meanings:
*
+ * Revision 1: Interrupt groups are not guest-configurable.
+ * IGROUPR reads as all-ones (group 1), writes ignored.
* Revision 2: Interrupt groups are guest-configurable and signaled using
* their configured groups.
+ * Revision 3: GICR_CTLR.{IR,CES} are advertised.
*/
static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
@@ -196,6 +199,7 @@ static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
reg = FIELD_GET(GICD_IIDR_REVISION_MASK, val);
switch (reg) {
+ case KVM_VGIC_IMP_REV_1:
case KVM_VGIC_IMP_REV_2:
case KVM_VGIC_IMP_REV_3:
dist->implementation_rev = reg;
diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c
index 74d76dec9730..1b662744ec5b 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio.c
@@ -73,6 +73,10 @@ void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
int i;
unsigned long flags;
+ /* Revision 1 and below: groups are not guest-configurable. */
+ if (vgic_get_implementation_rev(vcpu) < KVM_VGIC_IMP_REV_2)
+ return;
+
for (i = 0; i < len * 8; i++) {
struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 1388dc6028a9..16811ec03d54 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -372,6 +372,7 @@ struct vgic_dist {
/* Implementation revision as reported in the GICD_IIDR */
u32 implementation_rev;
+#define KVM_VGIC_IMP_REV_1 1 /* GICv2 interrupts as group 0 */
#define KVM_VGIC_IMP_REV_2 2 /* GICv2 restorable groups */
#define KVM_VGIC_IMP_REV_3 3 /* GICv3 GICR_CTLR.{IW,CES,RWP} */
#define KVM_VGIC_IMP_REV_LATEST KVM_VGIC_IMP_REV_3
--
2.51.0
^ permalink raw reply related
* [PATCH v12 5/5] mfd: Add support for MediaTek SPMI PMICs and MT6363/73
From: AngeloGioacchino Del Regno @ 2026-05-11 10:13 UTC (permalink / raw)
To: linux-mediatek
Cc: lee, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, lgirdwood, broonie, devicetree,
linux-kernel, linux-arm-kernel, kernel, wenst,
Nícolas F. R. A. Prado
In-Reply-To: <20260511101355.122478-1-angelogioacchino.delregno@collabora.com>
This driver adds support for the MediaTek SPMI PMICs and their
interrupt controller (which is present in 95% of the cases).
Other than probing all of the sub-devices of a SPMI PMIC, this
sets up a regmap from the relevant SPMI bus and initializes an
interrupt controller with its irq domain and irqchip to handle
chained interrupts, with the SPMI bus itself being its parent
irq controller, and the PMIC being the outmost device.
This driver hence holds all of the information about a specific
PMIC's interrupts and will properly handle them, calling the
ISR for any subdevice that requested an interrupt.
As for the interrupt spec, this driver wants either three or
two interrupt cells, but in the case 3 were given it ignores
the first one: this is because of how this first revision of
of the MediaTek SPMI 2.0 Controller works, which doesn't hold
hold irq number information in its register, but delegates
that to the SPMI device - it's possible that this will change
in the future with a newer revision of the controller IP, and
this is the main reason for that.
To make use of this implementation, this driver also adds the
required bits to support MediaTek MT6363 and MT6373 SPMI PMICs.
Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/mfd/Kconfig | 16 +
drivers/mfd/Makefile | 1 +
drivers/mfd/mtk-spmi-pmic.c | 427 ++++++++++++++++++++++
include/linux/mfd/mt63x3_spmi/registers.h | 34 ++
4 files changed, 478 insertions(+)
create mode 100644 drivers/mfd/mtk-spmi-pmic.c
create mode 100644 include/linux/mfd/mt63x3_spmi/registers.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 7192c9d1d268..3e9acdf648b7 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1148,6 +1148,22 @@ config MFD_MT6397
accessing the device; additional drivers must be enabled in order
to use the functionality of the device.
+config MFD_MTK_SPMI_PMIC
+ tristate "MediaTek SPMI PMICs"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on OF
+ depends on SPMI
+ select REGMAP_SPMI
+ help
+ Say yes here to enable support for MediaTek's SPMI PMICs.
+ These PMICs made their first appearance in board designs using the
+ MediaTek Dimensity 9400 series of SoCs.
+ Note that this will only be useful when paired with descriptions
+ of the independent functions as child nodes in the device tree.
+
+ Say M here if you want to include support for the MediaTek SPMI
+ PMICs as a module. The module will be called "mtk-spmi-pmic".
+
config MFD_MENF21BMC
tristate "MEN 14F021P00 Board Management Controller Support"
depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index e75e8045c28a..e00d283450c6 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -190,6 +190,7 @@ obj-$(CONFIG_MFD_MT6360) += mt6360-core.o
obj-$(CONFIG_MFD_MT6370) += mt6370.o
mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o
obj-$(CONFIG_MFD_MT6397) += mt6397.o
+obj-$(CONFIG_MFD_MTK_SPMI_PMIC) += mtk-spmi-pmic.o
obj-$(CONFIG_RZ_MTU3) += rz-mtu3.o
obj-$(CONFIG_ABX500_CORE) += abx500-core.o
diff --git a/drivers/mfd/mtk-spmi-pmic.c b/drivers/mfd/mtk-spmi-pmic.c
new file mode 100644
index 000000000000..d1fc8156e696
--- /dev/null
+++ b/drivers/mfd/mtk-spmi-pmic.c
@@ -0,0 +1,427 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * MediaTek SPMI PMICs Driver
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Copyright (c) 2025 Collabora Ltd
+ *
+ * Authors:
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/mfd/mt63x3_spmi/registers.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/spmi.h>
+#include <linux/types.h>
+
+#define MTK_SPMI_PMIC_VAL_BITS 8
+#define MTK_SPMI_PMIC_REG_CHIP_ID 0xb
+#define MTK_SPMI_PMIC_RCS_IRQ_DONE 0x41b
+
+/**
+ * struct mtk_spmi_pmic_irq_group - Group of interrupts in SPMI PMIC
+ * @num_int_regs: Number of registers for this group of interrupts
+ * @con_reg: PMIC Interrupt Group Control 0 register
+ * @sta_reg: PMIC Interrupt Group Status 0 register
+ * @group_num: PMIC Interrupt Group number - also corresponds to the
+ * status bit in the global IRQ Control register
+ */
+struct mtk_spmi_pmic_irq_grp {
+ u8 hwirq_base;
+ u8 num_int_regs;
+ u16 con_reg;
+ u16 sta_reg;
+ u8 group_num;
+};
+
+/**
+ * struct mtk_spmi_pmic_variant - SPMI PMIC variant-specific data
+ * @pmic_irq: Group of interrupts in SPMI PMIC
+ * @num_groups: Number of groups of interrupts
+ * @con_reg_len: Length in bytes of Control registers, depends on
+ * existence of SET and CLR registers in the layout
+ * @irq_grp_reg: Global interrupt status register, explains which
+ * group needs attention because of a group IRQ;
+ * if this is zero, it means that there is only one
+ * group and the device has no irqgroup register
+ * @chip_id_reg: Chip ID Register
+ */
+struct mtk_spmi_pmic_variant {
+ const struct mtk_spmi_pmic_irq_grp *pmic_irq;
+ u8 num_groups;
+ u8 con_reg_len;
+ u8 irq_grp_reg;
+ u8 chip_id_reg;
+};
+
+/**
+ * struct mtk_spmi_pmic - Main driver structure
+ * @variant: SPMI PMIC variant-specific data
+ * @dev: Handle to SPMI Device
+ * @dom: IRQ Domain of the PMIC's interrupt controller
+ * @regmap: Handle to PMIC regmap
+ * @irq: PMIC chained interrupt
+ */
+struct mtk_spmi_pmic {
+ const struct mtk_spmi_pmic_variant *variant;
+ struct device *dev;
+ struct irq_domain *dom;
+ struct regmap *regmap;
+ int irq;
+};
+
+static void mtk_spmi_pmic_irq_set_unmasking(struct irq_data *d, bool unmask)
+{
+ struct mtk_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
+ const struct mtk_spmi_pmic_variant *variant = pmic->variant;
+ struct regmap *regmap = pmic->regmap;
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ unsigned short i;
+
+ for (i = 0; i < variant->num_groups; i++) {
+ const struct mtk_spmi_pmic_irq_grp *irq_grp = &variant->pmic_irq[i];
+ u32 con_reg;
+ u8 irq_en_bit;
+
+ if (hwirq < irq_grp->hwirq_base)
+ continue;
+
+ con_reg = irq_grp->con_reg + (variant->con_reg_len * i);
+ irq_en_bit = hwirq - irq_grp->hwirq_base;
+ regmap_assign_bits(regmap, con_reg, BIT(irq_en_bit), unmask);
+
+ break;
+ }
+}
+
+static void mtk_spmi_pmic_irq_mask(struct irq_data *d)
+{
+ mtk_spmi_pmic_irq_set_unmasking(d, false);
+}
+
+static void mtk_spmi_pmic_irq_unmask(struct irq_data *d)
+{
+ mtk_spmi_pmic_irq_set_unmasking(d, true);
+}
+
+static struct irq_chip mtk_spmi_pmic_irq_chip = {
+ .name = "mtk-spmi-pmic",
+ .irq_mask = mtk_spmi_pmic_irq_mask,
+ .irq_unmask = mtk_spmi_pmic_irq_unmask,
+ .flags = IRQCHIP_SKIP_SET_WAKE,
+};
+
+static struct lock_class_key mtk_spmi_pmic_irq_lock_class, mtk_spmi_pmic_irq_request_class;
+
+static int mtk_spmi_pmic_irq_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
+ unsigned long *out_hwirq, unsigned int *out_type)
+{
+ struct mtk_spmi_pmic *pmic = d->host_data;
+ u32 intsize = fwspec->param_count;
+ u32 *intspec = fwspec->param;
+ unsigned int irq_type_index;
+ unsigned int irq_num_index;
+
+ /*
+ * Interrupt cell index - For interrupt size 3:
+ * [0] - SID Interrupt number
+ * [1] - SPMI PMIC (Sub-)Device Interrupt number
+ * [2] - Interrupt Type mask
+ *
+ * When only two cells are specified the SID Interrupt is not present.
+ */
+ if (intsize != 2 && intsize != 3) {
+ dev_err(pmic->dev, "Expected IRQ specifier of size 2 or 3, got %u\n", intsize);
+ return -EINVAL;
+ }
+
+ /* irq_num_index refers to the SPMI (Sub-)Device Interrupt number */
+ irq_num_index = intsize - 2;
+ irq_type_index = irq_num_index + 1;
+
+ /*
+ * For 3 cells, the IRQ number in intspec[0] is ignored on purpose here!
+ *
+ * This is because of how at least the first revision of the SPMI 2.0
+ * controller works in MediaTek SoCs: the controller will raise an
+ * interrupt for each SID (but doesn't know the details), and the
+ * specific IRQ number that got raised must be read from the PMIC or
+ * its sub-device driver.
+ * It's possible that this will change in the future with a newer
+ * revision of the SPMI controller, and this is why the device tree
+ * holds the full interrupt specifier.
+ *
+ * out_hwirq: SPMI PMIC (Sub-)Device Interrupt number
+ * out_type: Interrupt type sense mask
+ */
+ *out_hwirq = intspec[irq_num_index];
+ *out_type = intspec[irq_type_index] & IRQ_TYPE_SENSE_MASK;
+
+ return 0;
+}
+
+static int mtk_spmi_pmic_irq_alloc(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs, void *data)
+{
+ struct mtk_spmi_pmic *pmic = d->host_data;
+ struct irq_fwspec *fwspec = data;
+ irq_hw_number_t hwirq;
+ unsigned int irqtype;
+ int i, ret;
+
+ ret = mtk_spmi_pmic_irq_translate(d, fwspec, &hwirq, &irqtype);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < nr_irqs; i++) {
+ irq_set_lockdep_class(virq, &mtk_spmi_pmic_irq_lock_class,
+ &mtk_spmi_pmic_irq_request_class);
+ irq_domain_set_info(d, virq, hwirq, &mtk_spmi_pmic_irq_chip,
+ pmic, handle_level_irq, NULL, NULL);
+ }
+
+ return 0;
+}
+
+
+static const struct irq_domain_ops mtk_spmi_pmic_irq_domain_ops = {
+ .alloc = mtk_spmi_pmic_irq_alloc,
+ .free = irq_domain_free_irqs_common,
+ .translate = mtk_spmi_pmic_irq_translate,
+};
+
+static int mtk_spmi_pmic_handle_group_irq(struct mtk_spmi_pmic *pmic, int group)
+{
+ const struct mtk_spmi_pmic_irq_grp *irq_grp = &pmic->variant->pmic_irq[group];
+ struct regmap *regmap = pmic->regmap;
+ struct device *dev = pmic->dev;
+ int i, ret;
+
+ for (i = 0; i < irq_grp->num_int_regs; i++) {
+ u32 status, saved_status;
+
+ ret = regmap_read(regmap, irq_grp->sta_reg + i, &status);
+ if (ret) {
+ dev_err(dev, "Could not read IRQ status register: %d", ret);
+ return ret;
+ }
+
+ if (status == 0)
+ continue;
+
+ saved_status = status;
+ do {
+ irq_hw_number_t hwirq;
+ u8 bit = __ffs(status);
+
+ /* Each register has 8 bits: this is the first IRQ of this group */
+ hwirq = MTK_SPMI_PMIC_VAL_BITS * i;
+
+ /* Offset by this group's start interrupt */
+ hwirq += irq_grp->hwirq_base;
+
+ /* Finally, offset by the fired IRQ's bit number */
+ hwirq += bit;
+
+ status &= ~BIT(bit);
+
+ generic_handle_domain_irq_safe(pmic->dom, hwirq);
+ } while (status);
+
+ /* Clear the interrupts by writing the previous status */
+ regmap_write(regmap, irq_grp->sta_reg + i, saved_status);
+ }
+
+ return 0;
+}
+
+static void mtk_spmi_pmic_handle_chained_irq(struct irq_desc *desc)
+{
+ struct mtk_spmi_pmic *pmic = irq_desc_get_handler_data(desc);
+ const struct mtk_spmi_pmic_variant *variant = pmic->variant;
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct regmap *regmap = pmic->regmap;
+ bool irq_handled = false;
+ int i, ret;
+ u32 val;
+
+ chained_irq_enter(chip, desc);
+
+ /* If irq_grp_reg is present there are multiple IRQ groups */
+ if (variant->irq_grp_reg > 0) {
+ ret = regmap_read(regmap, variant->irq_grp_reg, &val);
+ if (ret)
+ handle_bad_irq(desc);
+
+ /* This is very unlikely to happen */
+ if (val == 0) {
+ chained_irq_exit(chip, desc);
+ return;
+ }
+ } else {
+ val = BIT(0);
+ }
+
+ for (i = 0; i < variant->num_groups; i++) {
+ const struct mtk_spmi_pmic_irq_grp *irq_grp = &variant->pmic_irq[i];
+ u8 group_bit = BIT(irq_grp[i].group_num);
+
+ if (val & group_bit) {
+ ret = mtk_spmi_pmic_handle_group_irq(pmic, i);
+ if (ret == 0)
+ irq_handled = true;
+ }
+ }
+
+ /* The RCS flag has to be cleared even if the IRQ was not handled. */
+ ret = regmap_write(regmap, MTK_SPMI_PMIC_RCS_IRQ_DONE, 1);
+ if (ret)
+ dev_warn(pmic->dev, "Could not clear RCS flag!\n");
+
+ if (!irq_handled)
+ handle_bad_irq(desc);
+
+ chained_irq_exit(chip, desc);
+}
+
+static void mtk_spmi_pmic_irq_remove(void *data)
+{
+ struct mtk_spmi_pmic *pmic = (struct mtk_spmi_pmic *)data;
+
+ irq_set_chained_handler_and_data(pmic->irq, NULL, NULL);
+ irq_domain_remove(pmic->dom);
+}
+
+static int mtk_spmi_pmic_irq_init(struct device *dev, struct regmap *regmap,
+ const struct mtk_spmi_pmic_variant *variant)
+{
+ struct fwnode_handle *fwnode = of_fwnode_handle(dev->of_node);
+ struct mtk_spmi_pmic *pmic;
+ int ret;
+
+ pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic)
+ return -ENOMEM;
+
+ pmic->irq = of_irq_get(dev->of_node, 0);
+ if (pmic->irq < 0)
+ return dev_err_probe(dev, pmic->irq, "Cannot get IRQ\n");
+
+ pmic->dev = dev;
+ pmic->regmap = regmap;
+ pmic->variant = variant;
+
+ pmic->dom = irq_domain_create_tree(fwnode, &mtk_spmi_pmic_irq_domain_ops, pmic);
+ if (!pmic->dom)
+ return dev_err_probe(dev, -ENOMEM, "Cannot create IRQ domain\n");
+
+ ret = devm_add_action_or_reset(dev, mtk_spmi_pmic_irq_remove, pmic);
+ if (ret) {
+ irq_domain_remove(pmic->dom);
+ return ret;
+ }
+
+ irq_set_chained_handler_and_data(pmic->irq, mtk_spmi_pmic_handle_chained_irq, pmic);
+
+ return 0;
+}
+
+#define MTK_SPMI_PMIC_IRQ_GROUP(pmic, group_name, group_index, first_irq, last_irq) \
+{ \
+ .hwirq_base = first_irq, \
+ .num_int_regs = ((last_irq - first_irq) / MTK_SPMI_PMIC_VAL_BITS) + 1, \
+ .con_reg = pmic##_REG_##group_name##_TOP_INT_CON0, \
+ .sta_reg = pmic##_REG_##group_name##_TOP_INT_STATUS0, \
+ .group_num = group_index, \
+}
+
+static const struct mtk_spmi_pmic_irq_grp mt6363_irq_groups[] = {
+ MTK_SPMI_PMIC_IRQ_GROUP(MT6363, BUCK, 0, 0, 9),
+ MTK_SPMI_PMIC_IRQ_GROUP(MT6363, LDO, 1, 16, 40),
+ MTK_SPMI_PMIC_IRQ_GROUP(MT6363, PSC, 2, 48, 57),
+ MTK_SPMI_PMIC_IRQ_GROUP(MT6363, MISC, 3, 64, 79),
+ MTK_SPMI_PMIC_IRQ_GROUP(MT6363, HK, 4, 80, 87),
+ MTK_SPMI_PMIC_IRQ_GROUP(MT6363, BM, 6, 88, 107)
+};
+
+static const struct mtk_spmi_pmic_irq_grp mt6373_irq_groups[] = {
+ MTK_SPMI_PMIC_IRQ_GROUP(MT6373, BUCK, 0, 0, 9),
+ MTK_SPMI_PMIC_IRQ_GROUP(MT6373, LDO, 1, 16, 39),
+ MTK_SPMI_PMIC_IRQ_GROUP(MT6373, MISC, 3, 56, 71),
+};
+
+static const struct mtk_spmi_pmic_variant mt6363_variant = {
+ .pmic_irq = mt6363_irq_groups,
+ .num_groups = ARRAY_SIZE(mt6363_irq_groups),
+ .con_reg_len = 3,
+ .irq_grp_reg = MT6363_REG_TOP_INT_STATUS1,
+ .chip_id_reg = MTK_SPMI_PMIC_REG_CHIP_ID,
+};
+
+static const struct mtk_spmi_pmic_variant mt6373_variant = {
+ .pmic_irq = mt6373_irq_groups,
+ .num_groups = ARRAY_SIZE(mt6373_irq_groups),
+ .con_reg_len = 3,
+ .irq_grp_reg = MT6373_REG_TOP_INT_STATUS1,
+ .chip_id_reg = MTK_SPMI_PMIC_REG_CHIP_ID,
+};
+
+static const struct regmap_config mtk_spmi_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = MTK_SPMI_PMIC_VAL_BITS,
+ .max_register = 0xffff,
+ .fast_io = true,
+};
+
+static int mtk_spmi_pmic_probe(struct spmi_device *sdev)
+{
+ const struct mtk_spmi_pmic_variant *variant;
+ struct device *dev = &sdev->dev;
+ struct regmap *regmap;
+ int ret;
+
+ regmap = devm_regmap_init_spmi_ext(sdev, &mtk_spmi_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ variant = (const struct mtk_spmi_pmic_variant *)device_get_match_data(dev);
+ if (variant && variant->num_groups) {
+ ret = mtk_spmi_pmic_irq_init(dev, regmap, variant);
+ if (ret)
+ return ret;
+ }
+
+ return devm_of_platform_populate(dev);
+}
+
+static const struct of_device_id mtk_pmic_spmi_id_table[] = {
+ { .compatible = "mediatek,mt6363", .data = &mt6363_variant },
+ { .compatible = "mediatek,mt6373", .data = &mt6373_variant },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mtk_pmic_spmi_id_table);
+
+static struct spmi_driver mtk_spmi_pmic_driver = {
+ .probe = mtk_spmi_pmic_probe,
+ .driver = {
+ .name = "mtk-spmi-pmic",
+ .of_match_table = mtk_pmic_spmi_id_table,
+ },
+};
+module_spmi_driver(mtk_spmi_pmic_driver);
+
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
+MODULE_DESCRIPTION("MediaTek SPMI PMIC driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/mt63x3_spmi/registers.h b/include/linux/mfd/mt63x3_spmi/registers.h
new file mode 100644
index 000000000000..808927280b40
--- /dev/null
+++ b/include/linux/mfd/mt63x3_spmi/registers.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ * Copyright (c) 2025 Collabora Ltd
+ */
+
+#ifndef __MFD_MT63X3_SPMI_REGISTERS_H__
+#define __MFD_MT63X3_SPMI_REGISTERS_H__
+
+/* MT6363 PMIC Registers */
+#define MT6363_REG_MISC_TOP_INT_CON0 0x37
+#define MT6363_REG_MISC_TOP_INT_STATUS0 0x43
+#define MT6363_REG_TOP_INT_STATUS1 0x4e
+#define MT6363_REG_PSC_TOP_INT_CON0 0x90f
+#define MT6363_REG_PSC_TOP_INT_STATUS0 0x91b
+#define MT6363_REG_BM_TOP_INT_CON0 0xc24
+#define MT6363_REG_BM_TOP_INT_STATUS0 0xc36
+#define MT6363_REG_HK_TOP_INT_CON0 0xf92
+#define MT6363_REG_HK_TOP_INT_STATUS0 0xf9e
+#define MT6363_REG_BUCK_TOP_INT_CON0 0x1411
+#define MT6363_REG_BUCK_TOP_INT_STATUS0 0x141d
+#define MT6363_REG_LDO_TOP_INT_CON0 0x1b11
+#define MT6363_REG_LDO_TOP_INT_STATUS0 0x1b29
+
+/* MT6373 PMIC Registers */
+#define MT6373_REG_MISC_TOP_INT_CON0 0x3c
+#define MT6373_REG_MISC_TOP_INT_STATUS0 0x48
+#define MT6373_REG_TOP_INT_STATUS1 0x53
+#define MT6373_REG_BUCK_TOP_INT_CON0 0x1411
+#define MT6373_REG_BUCK_TOP_INT_STATUS0 0x141d
+#define MT6373_REG_LDO_TOP_INT_CON0 0x1b10
+#define MT6373_REG_LDO_TOP_INT_STATUS0 0x1b22
+
+#endif /* __MFD_MT63X3_SPMI_REGISTERS_H__ */
--
2.53.0
^ permalink raw reply related
* Re: [PATCH 2/3] [v5 net-next] p54spi: convert to devicetree
From: Bartosz Golaszewski @ 2026-05-11 11:30 UTC (permalink / raw)
To: Arnd Bergmann
Cc: netdev, Arnd Bergmann, Aaro Koskinen, Andreas Kemnade,
Bartosz Golaszewski, Benoît Cousson, David S. Miller,
Dmitry Torokhov, Eric Dumazet, Felipe Balbi, Jakub Kicinski,
Johannes Berg, Kevin Hilman, Krzysztof Kozlowski, Linus Walleij,
Paolo Abeni, Rob Herring, Roger Quadros, Tony Lindgren,
linux-wireless, devicetree, linux-kernel, linux-arm-kernel,
linux-gpio, linux-omap, Christian Lamparter
In-Reply-To: <20260507212451.3333185-3-arnd@kernel.org>
On Thu, 7 May 2026 23:24:50 +0200, Arnd Bergmann <arnd@kernel.org> said:
> From: Arnd Bergmann <arnd@arndb.de>
>
> The Prism54 SPI driver hardcodes GPIO numbers and expects users to
> pass them as module parameters, apparently a relic from its life as a
> staging driver. This works because there is only one user, the Nokia
> N8x0 tablet.
>
> Convert this to the gpio descriptor interface and DT based probing
> to improve this and simplify the code at the same time.
>
> Acked-by: Christian Lamparter <chunkeey@gmail.com>
> Reviewed-by: Linus Walleij <linusw@kernel.org>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v4 2/2] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Vladimir Oltean @ 2026-05-11 11:24 UTC (permalink / raw)
To: Josua Mayer
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Yazan Shhady, Mikhail Anikin,
Alexander Dahl, devicetree, linux-kernel, imx, linux-arm-kernel,
Conor Dooley, Krzysztof Kozlowski, netdev
In-Reply-To: <20260511-imx8dxl-sr-som-v4-2-64381b3bf80d@solid-run.com>
On Mon, May 11, 2026 at 12:11:31PM +0200, Josua Mayer wrote:
> +&eqos {
> + /* delays are added by connected ethernet-switch cpu port */
> + phy-mode = "rgmii";
Documentation/devicetree/bindings/net/ethernet-controller.yaml says:
# Informative
# ===========
#
# 'phy-modes' & 'phy-connection-type' properties 'rgmii', 'rgmii-id',
# 'rgmii-rxid', and 'rgmii-txid' are frequently used wrongly by
# developers. This informative section clarifies their usage.
#
# The RGMII specification requires a 2ns delay between the data and
# clock signals on the RGMII bus. How this delay is implemented is not
# specified.
#
# One option is to make the clock traces on the PCB longer than the
# data traces. A sufficient difference in length can provide the 2ns
# delay. If both the RX and TX delays are implemented in this manner,
# 'rgmii' should be used, so indicating the PCB adds the delays.
#
# If the PCB does not add these delays via extra long traces,
# 'rgmii-id' should be used. Here, 'id' refers to 'internal delay',
# where either the MAC or PHY adds the delay.
#
# If only one of the two delays are implemented via extra long clock
# lines, either 'rgmii-rxid' or 'rgmii-txid' should be used,
# indicating the MAC or PHY should implement one of the delays
# internally, while the PCB implements the other delay.
#
# Device Tree describes hardware, and in this case, it describes the
# PCB between the MAC and the PHY, if the PCB implements delays or
# not.
#
# In practice, very few PCBs make use of extra long clock lines. Hence
# any RGMII phy mode other than 'rgmii-id' is probably wrong, and is
# unlikely to be accepted during review without details provided in
# the commit description and comments in the .dts file.
My understanding from the above is that when the RGMII delays are
provided by the switch, the eqos should have phy-mode = "rgmii-id".
> + pinctrl-0 = <&eqos_pins>;
> + pinctrl-names = "default";
> + status = "okay";
> +
> + fixed-link {
> + full-duplex;
> + speed = <1000>;
> + };
> +};
> +
> +&lpspi0 {
> + cs-gpios = <&lsio_gpio1 8 GPIO_ACTIVE_LOW>, <&lsio_gpio1 7 GPIO_ACTIVE_LOW>;
> + pinctrl-0 = <&lpspi0_pins>, <&switch_pins>;
> + pinctrl-names = "default";
> + status = "okay";
> +
> + ethernet-switch@0 {
> + compatible = "nxp,sja1110a";
> + reg = <0>;
> + reset-gpios = <&lsio_gpio4 3 GPIO_ACTIVE_LOW>;
> + spi-max-frequency = <4000000>;
> +
> + ethernet-ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + /* 100Base-TX on connector J26 */
> + port@1 {
Some people might prefer seeing ethernet-port@N instead of port@N, to
fully avoid confusion with dtschema/schemas/graph.yaml (although, the
container node being ethernet-ports now, the confusion should be
avoidable).
Also, if you ever perform device tree fixups from the bootloader (like
for setting status = "disabled" to status = "okay" for the ports that go
to addon boards), please never hardcode fixup paths, but always use eth
aliases to get to them. This is in case the port node names ever change,
to avoid bootloader regressions.
> + reg = <0x1>;
> + phy-handle = <&switch_port1_base_tx_phy>;
> + phy-mode = "internal";
> + };
^ permalink raw reply
* Re: [PATCH v6 08/25] KVM: arm64: iommu: Shadow host stage-2 page table
From: Mostafa Saleh @ 2026-05-11 11:24 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: linux-arm-kernel, linux-kernel, kvmarm, iommu, catalin.marinas,
will, maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
joro, jean-philippe, mark.rutland, qperret, tabba, vdonnefort,
sebastianene, keirf
In-Reply-To: <20260509232714.GI9285@ziepe.ca>
On Sat, May 09, 2026 at 08:27:14PM -0300, Jason Gunthorpe wrote:
> On Mon, May 04, 2026 at 12:28:55PM +0000, Mostafa Saleh wrote:
> > So far this is the list of requirements/changes needed share the
> > stage-2 page table (besides the obvious: same page table format,
> > granularity, endianness...)
> >
> > 1) HW BBM is not supported in the hypervisor page table, that’s
> > because it can generate TLB conflict aborts, which the hypervisor
> > can not handle because of the limited syndrome information.
> > We can rely on FEAT_BBML3 which was newly introduced to work
> > around that, it’s quite niche and not supported in KVM yet or
> > have an allow list similar to the kernel
> > (as in cpu_supports_bbml2_noabort()) which also limits the number
> > of CPUs that can run this.
>
> Do you think pkvm will need BBM? Hitless replace of a PTE is already a
> pretty advanced feature and the SMMU has its own support matrix there
> too. Is it for shared/private conversion?
Yes, we can break block on memory donation which is transfer of
ownership to the hypervisor or a guest.
>
> > 2) Handling page faults, devices must be able to stall and let the
> > hypervisor handle the page fault (which has to proxy through the
> > kernel as the hypervisor doesn’t handle interrupts), this includes
> > also IO page faults which are hard to get right from the HW which
> > and may lead to system stability issues or lockups.
>
> No.. once you turn on IO like this you don't have page faults
> anymore. Everything must be permantently mapped into the SMMU view, it
> can never be made non-present and you must run without page
> faults. That's what you have in the io-pgtable constructed table,
> right?
Exactly, but the CPU page table doesn’t guarantee that, so we either
have to handle page faults in the IOMMU, or completely change how KVM
deals with stage-2 if we want to share the page table with the CPU.
>
> > Alternatively, we can pin the stage-2 pages, that would require some
> > hypercalls, hacks to the driver/IOMMU API and possibly new semantics
> > in the DMA-API for IDENTITY devices as they will still need to pin
> > the pages as they are actually in stage-2 translation and not bypass.
>
> ?? Then how does this series work?
This series works fine as it shadows the page table and doesn't share it
with the CPU, so it fully populates the address space.
>
> > 3) SMMUv3 must be coherent.
>
> Yes for sure.
>
> > 4) Support BTM/DVM for TLB invalidation, otherwise some hooks are
> > still required (although not io-pgtable-arm)
>
> SW needs to forward invalidations, BTM is rare..
>
> > IMO, 1, 2 are the most tricky parts. It's more work and runs on very
> > limited systems, However, it can be implemented as an optimization)
> > which is my plan.
>
> I think unless you can do it without these HW features (excluding 3)
> don't bother.
I am looking into this now, but as I mentioned that will be a separate
RFC following this one as an optimization for advanced HW.
Thanks,
Mostafa
>
> > I am not sure how CCA deals with that, I’d expect they have a lot of
> > constraints on CPUs/SMMUs and DMA capable devices on those systems.
>
> 3 is not supported. The entire S2 is permanently mapped and doesn't
> really change alot at runtime. No page faults, not sure if the RMM
> private/shard conversion would require BMM..
>
> Jason
^ permalink raw reply
* Re: [PATCH v3 2/4] arm_mpam: Check whether the config array is allocated before destroying it
From: Ben Horgan @ 2026-05-11 11:23 UTC (permalink / raw)
To: James Morse, linux-kernel, linux-arm-kernel, zengheng4
Cc: wangkefeng.wang, xry111, catalin.marinas, yang, reinette.chatre,
will, thuth, mrigendra.chaubey, fenghuay, ahmed.genidi
In-Reply-To: <20260508162341.3762549-3-james.morse@arm.com>
Hi James,
On 5/8/26 17:23, James Morse wrote:
> __destroy_component_cfg() is called to free the configuration array.
> It uses the embedded 'garbage' structure, which means the array has
> to be allocated.
>
> If __destroy_component_cfg() is called from mpam_disable() before the
> configuration was ever allocated, then a NULL pointer is dereferenced.
>
> Check for this case and return early if the configuration is not
> allocated.
>
> __destroy_component_cfg() also frees the mbwu_state as this is allocated
> by __allocate_component_cfg(). As the mbwu_state is allocated after
> comp->cfg is set, and is also under mpam_list_lock, only the first
> pointer needs checking.
>
> Fixes: 3bd04fe7d807bb ("arm_mpam: Extend reset logic to allow devices to be reset any time")
> Signed-off-by: James Morse <james.morse@arm.com>
I checked on the FVP and with this and the previous patch and an early mpam_disable
due to an unsupported MSC version doesn't cause any problems. Additionally, the kunit
tests still run and pass.
Reviewed-by: Ben Horgan <ben.horgan@arm.com>
Thanks,
Ben
^ permalink raw reply
* Re: [PATCH v3 1/4] arm_mpam: Fix false positive assert failure during mpam_disable()
From: Ben Horgan @ 2026-05-11 11:19 UTC (permalink / raw)
To: James Morse, linux-kernel, linux-arm-kernel, zengheng4
Cc: wangkefeng.wang, xry111, catalin.marinas, yang, reinette.chatre,
will, thuth, mrigendra.chaubey, fenghuay, ahmed.genidi
In-Reply-To: <20260508162341.3762549-2-james.morse@arm.com>
Hi James,
On 5/8/26 17:23, James Morse wrote:
> mpam_assert_partid_sizes_fixed() is used to document that the caller
> doesn't expect the discovered PARTID size to change while it is walking
> a list sized by PARTID. Typically the MSC state is not written to until
> all the MSC have been discovered and this value is set.
>
> However, if discovering the MSC fails and schedules mpam_disable(),
> then the MSC state is written to reset it. In this case the
> discovered PARTID size may be become smaller - but only PARTID 0
> will be used once resctrl_exit() has been called.
>
> Skip the WARN_ON_ONCE() if mpam_disable_reason has been set.
>
> Fixes: 3bd04fe7d807bb ("arm_mpam: Extend reset logic to allow devices to be reset at any time")
> Signed-off-by: James Morse <james.morse@arm.com>
> ---
> drivers/resctrl/mpam_devices.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
> index 41b14344b16f..bef5e9e9e844 100644
> --- a/drivers/resctrl/mpam_devices.c
> +++ b/drivers/resctrl/mpam_devices.c
> @@ -164,11 +164,17 @@ static void mpam_free_garbage(void)
> /*
> * Once mpam is enabled, new requestors cannot further reduce the available
> * partid. Assert that the size is fixed, and new requestors will be turned
> - * away.
> + * away. This is needed when walking over structures sized by PARTID.
> + *
> + * During mpam_disable() these structures are not fixed, but the MSC state
> + * is still reset using whatever sizes have been discovered so far. As only
> + * PARTID 0 will be used after mpam_disable(), any race would be benign.
> + * Skip the check if a mpam_disable_reason has been set.
> */
> static void mpam_assert_partid_sizes_fixed(void)
> {
> - WARN_ON_ONCE(!partid_max_published);
> + if (!mpam_disable_reason)
> + WARN_ON_ONCE(!partid_max_published);
A little bit nasty to use mpam_disable_reason this way but a simple better way eludes me.
Reviewed-by: Ben Horgan <ben.horgan@arm.com>
Thanks,
Ben
> }
>
> static u32 __mpam_read_reg(struct mpam_msc *msc, u16 reg)
^ permalink raw reply
* Re: [PATCH v6 06/25] iommu/io-pgtable-arm: Rework to use the iommu-pages API
From: Mostafa Saleh @ 2026-05-11 11:16 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: linux-arm-kernel, linux-kernel, kvmarm, iommu, catalin.marinas,
will, maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
joro, jean-philippe, mark.rutland, qperret, tabba, vdonnefort,
sebastianene, keirf
In-Reply-To: <20260509232155.GH9285@ziepe.ca>
On Sat, May 09, 2026 at 08:21:55PM -0300, Jason Gunthorpe wrote:
> On Mon, May 04, 2026 at 12:19:37PM +0000, Mostafa Saleh wrote:
> > > So.. I suggest you update it to use the iommu_pages API, #ifdef out
> > > the allocator so the pkvm pkvm doesn't need to deal with it. Then
> > > compile a special iommu-pages for the pkvm side presenting the same
> > > API.
> >
> > I see, we still need to leave the DMA-API calls for the custom config,
> > as I am not sure if it can use pages not backed by the vmemmap, I
> > pushed that into a separate function so it’s easily compiled out.
>
> Yeah..
>
> > Without this patch, now it looks like:
>
> Seems reasonable, and then i'd probably just put something like
> #define dma_map(...)
> #define dma_umap(...)
>
> To effectively take it out of the pkvm build
>
> Then have a pkvm compile of iommu-pages to provide the functions in a
> pkvm compatible way. I guess you can't actually fully do this, but
> can do enough to support this file at least.
>
> > > You should have a pkvm shim header that provides
> > > kmalloc/kfree/virt_to_phys in the normal way and just #include that in
> > > io-pgtable when doing a pkvm build instead of hacking up all the code.
> >
> > Ok, I can do that in another change, but I believe it's better to
> > change the usage in this file to arm_lpae_*(virt_to_phys...) so it's
> > clear which parts are intended for that.
>
> IDK, why? virt_to_phys() is part of the iommu-pages API, I'd just
> leave it.. If you want to narrow it then #define it for pkvm when
> compiling this file..
It is not going to be part of the iommu-pages API, I meant in
io-pgtable-arm, we will use something arm_lpae_virt_to_phys()...
which is then implemented differently for pkvm.
Thanks,
Mostafa
>
> Jason
^ permalink raw reply
* [PATCH v12 22/28] coresight: sysfs: Use source's path pointer for path control
From: Leo Yan @ 2026-05-11 11:11 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Yeoreum Yun,
Mark Rutland, Will Deacon, Yabin Cui, Keita Morisaki, Jie Gan,
Yuanfang Zhang, Greg Kroah-Hartman, Alexander Shishkin,
Tamas Petz, Thomas Gleixner, Peter Zijlstra
Cc: coresight, linux-arm-kernel, Leo Yan
In-Reply-To: <20260511-arm_coresight_path_power_management_improvement-v12-0-1c9dcb1de8c9@arm.com>
Since the path pointer is stored in the source's structure, retrieve it
directly when disabling the path.
As a result, the global variables used for caching path pointers are no
longer needed. Remove them to simplify the code.
Tested-by: James Clark <james.clark@linaro.org>
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Tested-by: Jie Gan <jie.gan@oss.qualcomm.com>
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
drivers/hwtracing/coresight/coresight-sysfs.c | 82 +++------------------------
1 file changed, 9 insertions(+), 73 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
index 7ef3f13ebac55b920458b6cd202bdb533796ba2d..0aebafcb8d0e8e699652244af5202e7c4dc4e9b1 100644
--- a/drivers/hwtracing/coresight/coresight-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-sysfs.c
@@ -5,26 +5,12 @@
*/
#include <linux/device.h>
-#include <linux/idr.h>
#include <linux/kernel.h>
#include <linux/property.h>
#include "coresight-priv.h"
#include "coresight-trace-id.h"
-/*
- * Use IDR to map the hash of the source's device name
- * to the pointer of path for the source. The idr is for
- * the sources which aren't associated with CPU.
- */
-static DEFINE_IDR(path_idr);
-
-/*
- * When operating Coresight drivers from the sysFS interface, only a single
- * path can exist from a tracer (associated to a CPU) to a sink.
- */
-static DEFINE_PER_CPU(struct coresight_path *, tracer_path);
-
ssize_t coresight_simple_show_pair(struct device *_dev,
struct device_attribute *attr, char *buf)
{
@@ -167,11 +153,10 @@ static int coresight_validate_source_sysfs(struct coresight_device *csdev,
int coresight_enable_sysfs(struct coresight_device *csdev)
{
- int cpu, ret = 0;
+ int ret = 0;
struct coresight_device *sink;
struct coresight_path *path;
enum coresight_dev_subtype_source subtype;
- u32 hash;
subtype = csdev->subtype.source_subtype;
@@ -223,37 +208,6 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
if (ret)
goto err_source;
- switch (subtype) {
- case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
- /*
- * When working from sysFS it is important to keep track
- * of the paths that were created so that they can be
- * undone in 'coresight_disable()'. Since there can only
- * be a single session per tracer (when working from sysFS)
- * a per-cpu variable will do just fine.
- */
- cpu = csdev->cpu;
- per_cpu(tracer_path, cpu) = path;
- break;
- case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
- case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM:
- case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS:
- /*
- * Use the hash of source's device name as ID
- * and map the ID to the pointer of the path.
- */
- hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev)));
- ret = idr_alloc_u32(&path_idr, path, &hash, hash, GFP_KERNEL);
- if (ret) {
- coresight_disable_source_sysfs(csdev, NULL);
- goto err_source;
- }
- break;
- default:
- /* We can't be here */
- break;
- }
-
out:
mutex_unlock(&coresight_mutex);
return ret;
@@ -269,9 +223,8 @@ EXPORT_SYMBOL_GPL(coresight_enable_sysfs);
void coresight_disable_sysfs(struct coresight_device *csdev)
{
- int cpu, ret;
- struct coresight_path *path = NULL;
- u32 hash;
+ struct coresight_path *path;
+ int ret;
mutex_lock(&coresight_mutex);
@@ -279,32 +232,15 @@ void coresight_disable_sysfs(struct coresight_device *csdev)
if (ret)
goto out;
+ /*
+ * coresight_disable_source_sysfs() clears the 'csdev->path' pointer
+ * when disabling the source. Retrieve the path pointer here.
+ */
+ path = csdev->path;
+
if (!coresight_disable_source_sysfs(csdev, NULL))
goto out;
- switch (csdev->subtype.source_subtype) {
- case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
- cpu = csdev->cpu;
- path = per_cpu(tracer_path, cpu);
- per_cpu(tracer_path, cpu) = NULL;
- break;
- case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
- case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM:
- case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS:
- hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev)));
- /* Find the path by the hash. */
- path = idr_find(&path_idr, hash);
- if (path == NULL) {
- pr_err("Path is not found for %s\n", dev_name(&csdev->dev));
- goto out;
- }
- idr_remove(&path_idr, hash);
- break;
- default:
- /* We can't be here */
- break;
- }
-
coresight_disable_path(path);
coresight_release_path(path);
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox