Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] pinctrl: meson: amlogic-a4: fix deadlock issue
From: Xianwei Zhao via B4 Relay @ 2026-04-22 11:44 UTC (permalink / raw)
  To: Linus Walleij, Neil Armstrong, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl
  Cc: linux-amlogic, linux-gpio, linux-arm-kernel, linux-kernel,
	Xianwei Zhao

From: Xianwei Zhao <xianwei.zhao@amlogic.com>

Accessing the pinconf-pins sysfs node may deadlock.

pinconf_pins_show() holds pctldev->mutex, and the platform driver
calls pinctrl_find_gpio_range_from_pin(), which tries to acquire
the same mutex again, leading to a deadlock.

Use pinctrl_find_gpio_range_from_pin_nolock() to fix this issue.

Fixes: 6e9be3abb78c ("pinctrl: Add driver support for Amlogic SoCs")
Signed-off-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
---
Fix deadlock issue.
---
 drivers/pinctrl/meson/pinctrl-amlogic-a4.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
index e2293a872dcb..35d27626a336 100644
--- a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
+++ b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
@@ -292,7 +292,7 @@ static int aml_calc_reg_and_bit(struct pinctrl_gpio_range *range,
 static int aml_pinconf_get_pull(struct aml_pinctrl *info, unsigned int pin)
 {
 	struct pinctrl_gpio_range *range =
-			 pinctrl_find_gpio_range_from_pin(info->pctl, pin);
+			 pinctrl_find_gpio_range_from_pin_nolock(info->pctl, pin);
 	struct aml_gpio_bank *bank = gpio_chip_to_bank(range->gc);
 	unsigned int reg, bit, val;
 	int ret, conf;
@@ -326,7 +326,7 @@ static int aml_pinconf_get_drive_strength(struct aml_pinctrl *info,
 					  u16 *drive_strength_ua)
 {
 	struct pinctrl_gpio_range *range =
-			 pinctrl_find_gpio_range_from_pin(info->pctl, pin);
+			 pinctrl_find_gpio_range_from_pin_nolock(info->pctl, pin);
 	struct aml_gpio_bank *bank = gpio_chip_to_bank(range->gc);
 	unsigned int reg, bit;
 	unsigned int val;
@@ -365,7 +365,7 @@ static int aml_pinconf_get_gpio_bit(struct aml_pinctrl *info,
 				    unsigned int reg_type)
 {
 	struct pinctrl_gpio_range *range =
-			 pinctrl_find_gpio_range_from_pin(info->pctl, pin);
+			 pinctrl_find_gpio_range_from_pin_nolock(info->pctl, pin);
 	struct aml_gpio_bank *bank = gpio_chip_to_bank(range->gc);
 	unsigned int reg, bit, val;
 	int ret;

---
base-commit: bd7fd288490c64835a74c05e631c102ce056d5e1
change-id: 20260422-fix-pinconf-42be1cc2f5af

Best regards,
-- 
Xianwei Zhao <xianwei.zhao@amlogic.com>




^ permalink raw reply related

* Re: [PATCH v4 2/2] arm64: dts: amlogic: add support for Amediatech X98Q
From: Christian Hewitt @ 2026-04-22 11:43 UTC (permalink / raw)
  To: christian.koever-draxl
  Cc: robh, krzk+dt, conor+dt, neil.armstrong, khilman, jbrunet,
	martin.blumenstingl, devicetree, linux-amlogic, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260422095840.26139-3-christian.koever-draxl@student.uibk.ac.at>

> On 22 Apr 2026, at 1:58 pm, christian.koever-draxl@student.uibk.ac.at wrote:
> 
> From: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
> 
> Add dts enabling core hardware for the Amediatech X98Q TV box.
> 
> The board features:
> - Amlogic S905W2 (Meson S4) SoC
> - 1 GiB RAM (2 GiB variants exist)
> - eMMC and microSD card slot
> - SDIO-based WiFi module (unsupported)
> - RMII Ethernet with internal PHY
> - IR receiver and UART console
> - Status LED
> 
> Enabled peripherals:
> - eMMC (HS200)
> - SD card interface
> - SDIO bus (WiFi, no driver yet)
> - Ethernet (RMII)
> - UART_B
> - IR receiver
> - PWM-controlled CPU regulator
> - PWM and Fixed regulators for core and IO rails
> 
> Known limitations:
> - No support for the onboard WiFi module
> - Missing multimedia (HDMI/audio)
> 
> Signed-off-by: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
> ---
> arch/arm64/boot/dts/amlogic/Makefile          |   1 +
> .../boot/dts/amlogic/meson-s4-s905w2-x98q.dts | 249 ++++++++++++++++++
> 2 files changed, 250 insertions(+)
> create mode 100644 arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
> 
> diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
> index 15f9c817e502..c7752684dea6 100644
> --- a/arch/arm64/boot/dts/amlogic/Makefile
> +++ b/arch/arm64/boot/dts/amlogic/Makefile
> @@ -85,6 +85,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-ugoos-am3.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-gxm-wetek-core2.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-s4-s805x2-aq222.dtb
> +dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905w2-x98q.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905y4-khadas-vim1s.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air-gbit.dtb
> dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air.dtb
> diff --git a/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
> index 000000000000..3eecbc858522
> --- /dev/null
> +++ b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
> @@ -0,0 +1,249 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright (c) 2026 Christian Stefan Köver-Draxl
> + * Based on meson-s4-s905y4-khadas-vim1s.dts:
> + *  - Copyright (c) 2026 Khadas Technology Co., Ltd.
> + */
> +
> +/dts-v1/;
> +
> +#include "meson-s4.dtsi"
> +
> +/ {
> + model = "Shenzhen Amediatech Technology Co., Ltd X98Q";
> + compatible = "amediatech,x98q", "amlogic,s905w2", "amlogic,s4";
> + interrupt-parent = <&gic>;
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + aliases {
> + mmc0 = &emmc; /* eMMC */
> + mmc1 = &sd; /* SD card */
> + mmc2 = &sdio; /* SDIO */
> + serial0 = &uart_b;
> + };
> +
> + memory@0 {
> + device_type = "memory";
> + reg = <0x0 0x0 0x0 0x40000000>;
> + };
> +
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + /* 52 MiB reserved for ARM Trusted Firmware */
> + secmon_reserved: secmon@5000000 {
> + reg = <0x0 0x05000000 0x0 0x3400000>;
> + no-map;
> + };
> + };
> +
> + emmc_pwrseq: emmc-pwrseq {
> + compatible = "mmc-pwrseq-emmc";
> + reset-gpios = <&gpio GPIOB_9 GPIO_ACTIVE_LOW>;
> + };
> +
> + sdio_32k: sdio-32k {
> + compatible = "pwm-clock";
> + #clock-cells = <0>;
> + clock-frequency = <32768>;
> + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
> + };
> +
> + sdio_pwrseq: sdio-pwrseq {
> + compatible = "mmc-pwrseq-simple";
> + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
> + clocks = <&sdio_32k>;
> + clock-names = "ext_clock";
> + };
> +
> + main_5v: regulator-main-5v {
> + compatible = "regulator-fixed";
> + regulator-name = "5V";
> + regulator-min-microvolt = <5000000>;
> + regulator-max-microvolt = <5000000>;
> + regulator-always-on;
> + };
> +
> + sd_3v3: regulator-sd-3v3 {
> + compatible = "regulator-fixed";
> + regulator-name = "SD_3V3";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + gpio = <&gpio GPIOD_4 GPIO_ACTIVE_LOW>;
> + regulator-always-on;
> + };
> +
> + vddio_sd: regulator-vddio-sd {
> + compatible = "regulator-gpio";
> + regulator-name = "VDDIO_SD";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <3300000>;
> + gpios = <&gpio GPIOD_9 GPIO_ACTIVE_HIGH>;
> + gpios-states = <1>;
> + states = <1800000 1 3300000 0>;
> + };
> +
> + vddao_3v3: regulator-vddao-3v3 {
> + compatible = "regulator-fixed";
> + regulator-name = "VDDAO_3V3";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + vin-supply = <&main_5v>;
> + regulator-always-on;
> + };
> +
> + vddio_ao1v8: regulator-vddio-ao1v8 {
> + compatible = "regulator-fixed";
> + regulator-name = "VDDIO_AO1V8";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + vin-supply = <&vddao_3v3>;
> + regulator-always-on;
> + };
> +
> + /* SY8120B1ABC DC/DC Regulator. */
> + vddcpu: regulator-vddcpu {
> + compatible = "pwm-regulator";
> +
> + regulator-name = "VDDCPU";
> + regulator-min-microvolt = <689000>;
> + regulator-max-microvolt = <1049000>;
> +
> + vin-supply = <&main_5v>;
> +
> + pwms = <&pwm_ij 1 1500 0>;
> + pwm-dutycycle-range = <100 0>;
> +
> + regulator-boot-on;
> + regulator-always-on;
> + /* Voltage Duty-Cycle */
> + voltage-table = <1049000 0>,
> + <1039000 3>,
> + <1029000 6>,
> + <1019000 9>,
> + <1009000 12>,
> + <999000 14>,
> + <989000 17>,
> + <979000 20>,
> + <969000 23>,
> + <959000 26>,
> + <949000 29>,
> + <939000 31>,
> + <929000 34>,
> + <919000 37>,
> + <909000 40>,
> + <899000 43>,
> + <889000 45>,
> + <879000 48>,
> + <869000 51>,
> + <859000 54>,
> + <849000 56>,
> + <839000 59>,
> + <829000 62>,
> + <819000 65>,
> + <809000 68>,
> + <799000 70>,
> + <789000 73>,
> + <779000 76>,
> + <769000 79>,
> + <759000 81>,
> + <749000 84>,
> + <739000 87>,
> + <729000 89>,
> + <719000 92>,
> + <709000 95>,
> + <699000 98>,
> + <689000 100>;
> + };
> +};
> +
> +&emmc {
> + status = "okay";
> + pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
> + pinctrl-1 = <&emmc_clk_gate_pins>;
> + pinctrl-names = "default", "clk-gate";
> +
> + bus-width = <8>;
> + cap-mmc-highspeed;
> + mmc-ddr-1_8v;
> + mmc-hs200-1_8v;
> + max-frequency = <200000000>;
> + non-removable;
> + disable-wp;
> +
> + mmc-pwrseq = <&emmc_pwrseq>;
> + vmmc-supply = <&vddao_3v3>;
> + vqmmc-supply = <&vddio_ao1v8>;
> +};
> +
> +&ethmac {
> + status = "okay";
> + phy-handle = <&internal_ephy>;
> + phy-mode = "rmii";
> +};
> +
> +&ir {
> + status = "okay";
> + pinctrl-0 = <&remote_pins>;
> + pinctrl-names = "default";
> +};
> +
> +&pwm_ef {
> + status = "okay";
> + pinctrl-0 = <&pwm_e_pins1>;
> + pinctrl-names = "default";
> +};
> +
> +&pwm_ij {
> + status = "okay";
> +};
> +
> +&sd {
> + status = "okay";
> + pinctrl-0 = <&sdcard_pins>;
> + pinctrl-1 = <&sdcard_clk_gate_pins>;
> + pinctrl-names = "default", "clk-gate";
> + bus-width = <4>;
> + cap-sd-highspeed;
> + max-frequency = <50000000>;
> + disable-wp;
> +
> + cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
> +
> + vmmc-supply = <&vddao_3v3>;
> + vqmmc-supply = <&vddao_3v3>;
> +};
> +
> +     /*
> +      * Wireless SDIO Module (Amlogic W150S1)
> +      * Note: There is no driver for this at the moment.
> +      */

^ drop this comment

> +
> +&sdio {
> + status = "okay";
> + pinctrl-0 = <&sdio_pins>;
> + pinctrl-1 = <&sdio_clk_gate_pins>;
> + pinctrl-names = "default", "clk-gate";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + bus-width = <4>;
> + cap-sd-highspeed;
> + sd-uhs-sdr50;
> + sd-uhs-sdr104;
> + max-frequency = <200000000>;
> + non-removable;
> + disable-wp;
> +
> + no-sd;
> + no-mmc;
> + mmc-pwrseq = <&sdio_pwrseq>;
> + vmmc-supply = <&vddao_3v3>;
> + vqmmc-supply = <&vddio_ao1v8>;

	sdio: wifi@1 {
		/* Amlogic W150S1 */
		reg = <1>;
  	};

^ add this to generically describe the hardware without
the need for a specific compatible (as done in several of
the Amlogic reference designs where we cannot guarantee
which chipset is used). The reg value should be enough to
result in the downstream driver probing should a distro
choose to package it; thus avoiding the need for distros
to forever carry a device-tree patch to add support (as
Amlogic have no plans to upstream the driver). Should that
ever change the comment can be replaced with a compatible.

Christian

> +};
> +
> +&uart_b {
> + status = "okay";
> +};
> -- 
> 2.53.0
> 
> 
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic



^ permalink raw reply

* Re: [PATCH v2 2/2] arm64: dts: add tqma9596la-mba95xxca
From: Francesco Dolcini @ 2026-04-22 11:42 UTC (permalink / raw)
  To: Alexander Stein, Daniel Baluta
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Geert Uytterhoeven, Magnus Damm, Shawn Guo, linux-arm-kernel,
	Markus Niebel, devicetree, linux-kernel, imx, linux,
	linux-renesas-soc
In-Reply-To: <5988897.DvuYhMxLoT@steina-w>

On Wed, Apr 22, 2026 at 07:58:11AM +0200, Alexander Stein wrote:
> Am Dienstag, 21. April 2026, 16:48:25 CEST schrieb Daniel Baluta:
> > [..]
> > 
> > > +
> > > +	reserved-memory {
> > > +		#address-cells = <2>;
> > > +		#size-cells = <2>;
> > > +		ranges;
> > > +
> > > +		linux_cma: linux,cma {
> > > +			compatible = "shared-dma-pool";
> > > +			reusable;
> > > +			size = <0 0x28000000>;
> > > +			alloc-ranges = <0 0x80000000 0 0x80000000>;
> > > +			linux,cma-default;
> > > +		};
> > > +
> > > +		vpu_boot: vpu_boot@a0000000 {
> > 
> > Should this be memory@a0000000 ?
> 
> According to schema in dt-schema repository [1] the node name should
> describe the purpose, so I would keep that.

See this question on the topic, and the related answer from Rob,
https://lore.kernel.org/all/88456d17c91737cfc09af46673b49bb9a9d36dc0.camel@gmail.com/

Francesco



^ permalink raw reply

* Re: [PATCH v5 0/6] Add Rockchip RK3576 PWM Support Through MFPWM
From: Nicolas Frattaroli @ 2026-04-22 11:31 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Lee Jones, William Breathitt Gray,
	Damon Ding, kernel, Jonas Karlman, Alexey Charkov, linux-rockchip,
	linux-pwm, devicetree, linux-arm-kernel, linux-kernel, linux-iio,
	Conor Dooley
In-Reply-To: <20260421165656.168fe262@jic23-huawei>

On Tuesday, 21 April 2026 17:56:56 Central European Summer Time Jonathan Cameron wrote:
> On Mon, 20 Apr 2026 15:52:37 +0200
> Nicolas Frattaroli <nicolas.frattaroli@collabora.com> wrote:
> 
> > This series introduces support for some of the functions of the new PWM
> > silicon found on Rockchip's RK3576 SoC. Due to the wide range of
> > functionalities offered by it, including many parts which this series'
> > first iteration does not attempt to implement for now. The drivers are
> > modelled as an MFD, with no leakage of the MFD-ness into the binding, as
> > it's a Linux implementation detail.
> 
> Just thought I'd point out that as this includes the linux-iio
> list sashiko took a look at it.  Quite a few things and at least
> the first one I looked at was valid (a dereference before a validity
> check)
> 
> https://sashiko.dev/#/patchset/20260420-rk3576-pwm-v5-0-ae7cfbbe5427%40collabora.com
> 
> Whilst this tool does generate some false positives, it also finds
> quite a few things it seems us humans fail to spot.
> 
> Jonathan
> 

While I'm not entirely opposed to this, I do think reviews should happen
on-list when possible. Sashiko is a Google service, so it has about a 50%
chance of still being around in 2 years time. One of the benefits of the
kernel development workflow is that discussion going back decades is still
accessible.

The reason why these aren't posted to list goes into the other thing
that I currently am not stoked about, which is that I'd have to act as
a filter for a Bring-Your-Own-Brain noise generator to pick out the
parts that aren't convincing lies.




^ permalink raw reply

* Re: [PATCH v2 2/9] driver core: Add dev_set_drv_queue_sync_state()
From: Danilo Krummrich @ 2026-04-22 11:30 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Saravana Kannan, Rafael J . Wysocki, Greg Kroah-Hartman, linux-pm,
	Sudeep Holla, Cristian Marussi, Kevin Hilman, Stephen Boyd,
	Marek Szyprowski, Bjorn Andersson, Abel Vesa, Peng Fan,
	Tomi Valkeinen, Maulik Shah, Konrad Dybcio, Thierry Reding,
	Jonathan Hunter, Geert Uytterhoeven, Dmitry Baryshkov,
	linux-arm-kernel, linux-kernel, Geert Uytterhoeven, driver-core
In-Reply-To: <CAPDyKFpeSv+fg=YKJE_qc=Q5BfiJFn0tR7Ar8SncqrD0UW1P1g@mail.gmail.com>

On Wed Apr 22, 2026 at 12:25 PM CEST, Ulf Hansson wrote:
> Most of the static inline functions in device.h lacks documentation.
> Are you suggesting that we should move towards documenting all of
> them?

I'd prefer that, yes. After all, if they are defined in device.h, they are
public APIs, so they should ideally have documentation.

(If a function is only used throughout the driver core, it should be in
drivers/base/base.h instead.)


^ permalink raw reply

* Re: [PATCH v3 4/4] docs: driver-api: add mod_name argument to __platform_register_drivers()
From: Greg Kroah-Hartman @ 2026-04-22 11:27 UTC (permalink / raw)
  To: Shashank Balaji
  Cc: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
	Maxime Coquelin, Alexandre Torgue, Rafael J. Wysocki,
	Danilo Krummrich, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Richard Cochran, Jonathan Corbet, Shuah Khan,
	Rahul Bukte, linux-kernel, coresight, linux-arm-kernel,
	driver-core, rust-for-linux, linux-doc, Daniel Palmer, Tim Bird
In-Reply-To: <20260422-acpi_mod_name-v3-4-a184eff9ff6f@sony.com>

On Wed, Apr 22, 2026 at 06:49:06PM +0900, Shashank Balaji wrote:
> Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
> Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
> Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
> ---
>  Documentation/driver-api/driver-model/platform.rst | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

For obvious reasons we can't take patches without any changelog text at
all (and neither should you want us to...)

thanks,

greg k-h


^ permalink raw reply

* Re: [PATCH 0/5] firmware/irqchip: Add FF-A DT interrupt support for donated NS SGIs
From: Marc Zyngier @ 2026-04-22 11:01 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree,
	linux-kernel, linux-arm-kernel
In-Reply-To: <20260412-b4-ffa_ns_sgi_gicv3-v1-0-af61243eb405@kernel.org>

On Sun, 12 Apr 2026 18:04:36 +0100,
Sudeep Holla <sudeep.holla@kernel.org> wrote:
> 
> Hi all,
> 
> This series wires FF-A notification interrupts up through DT using the
> standard interrupts property on the arm,ffa node and adds the
> required GICv3 and binding support for secure-donated non-secure SGIs.
> 
> This has been long pending after the discussions here[1][2]. I have been
> waiting for some ACPI story to shape up for almost an year now, but no
> progress there. So posting this for now to start discussion on the approach
> taken here instead of waiting for another year to sort out ACPI 😉.
> 
> It:
> 
> - documents secure-donated NS SGIs in the GIC DT binding
> - teaches the GICv3 driver to accept and map those SGIs
> - adds a DT binding for the arm,ffa firmware node
> - updates the FF-A driver to use the arm,ffa node interrupt instead of
>   synthesizing its own GIC mapping
> - adds an FVP DT node using SGI 8 as the FF-A notification interrupt
>
> The FF-A DT lookup expects a single interrupt entry, verifies that it is
> a per-CPU interrupt via the reported affinity mask, and cross-checks the
> resolved Linux IRQ hwirq against the interrupt ID returned by
> FFA_FEATURES.

I haven't looked at this in any detail, but these are the additional
issues someone needs to address:

- The GIC(v3) is dead, long live the GIC(v5)! SGIs don't exist in the
  brave new world, so FFA needs to find new ways to signal interrupts.

- FFA doesn't necessarily live in secure world, and could be
  implemented by a hypervisor. In the context of a single security
  domain machine (that's what a VM is), the guest *owns* all SGIs. So
  there is absolutely nothing to donate, and this doesn't work. FFA
  also needs fixing here.

- All of the above should work with the other firmware description
  (Avoid Critical Periodic Interrupts). But maybe FFA is not a thing
  on these machines? If not, it should be made explicit.

Overall, it only indicates that FFA should behave as a device, and
use interrupts that are valid for a device.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


^ permalink raw reply

* Re: [PATCH v2 1/9] driver core: Enable suppliers to implement fine grained sync_state support
From: Danilo Krummrich @ 2026-04-22 10:59 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Saravana Kannan, Rafael J . Wysocki, Greg Kroah-Hartman, linux-pm,
	Sudeep Holla, Cristian Marussi, Kevin Hilman, Stephen Boyd,
	Marek Szyprowski, Bjorn Andersson, Abel Vesa, Peng Fan,
	Tomi Valkeinen, Maulik Shah, Konrad Dybcio, Thierry Reding,
	Jonathan Hunter, Geert Uytterhoeven, Dmitry Baryshkov,
	linux-arm-kernel, linux-kernel, Geert Uytterhoeven, driver-core
In-Reply-To: <CAPDyKFqMDPiqvqJrq5Qs6Tw4Sc7szG4G-=y0NFkNSPoNd9kdVA@mail.gmail.com>

On Wed Apr 22, 2026 at 12:07 PM CEST, Ulf Hansson wrote:
> On Sat, 18 Apr 2026 at 13:23, Danilo Krummrich <dakr@kernel.org> wrote:
>> On Fri Apr 10, 2026 at 12:40 PM CEST, Ulf Hansson wrote:
>> > @@ -1126,6 +1128,9 @@ static void __device_links_queue_sync_state(struct device *dev,
>> >       if (dev->state_synced)
>> >               return;
>> >
>> > +     if (dev->driver && dev->driver->queue_sync_state)
>> > +             dev->driver->queue_sync_state(dev);
>>
>> This seems to be called without the device lock being held, which seems to allow
>> the queue_sync_state() callback to execute concurrently with remove(). This
>> opens the door for all kinds of UAF conditions in drivers.
>
> If that were the case, this whole function would be unsafe even before
> this change. I assume this isn't because of how the function is being
> called, but I may be wrong.

This function does not issue any driver callbacks intentionally; the existing
sync_state() callback is deferred to device_links_flush_sync_list(), which is
called without the device_links_write_lock() held, but takes the device_lock()
to protect against other concurrent driver callbacks, such as remove().

I.e. we can't take the device_lock() when the device_links_write_lock() is held,
as it would be prone to lock inversion.

The documentation of __device_links_queue_sync_state() actually slightly hints
at this, but focuses more on the other reason for the deferred semantics -- the
sync_state() callback may want to call device link APIs.

> Anyway, let me add a get/put_device() here somewhere, to ensure we
> prevent this from happening. I assume that is what you are proposing?

No, an additional device reference count won't protect against other concurrent
driver callbacks, such as remove().


^ permalink raw reply

* Re: [PATCH v6 1/2] dma: arm-dma350: enable ANYCH interrupt for shared IRQ wiring
From: Jun Guo @ 2026-04-22 10:33 UTC (permalink / raw)
  To: Frank Li
  Cc: peter.chen, fugang.duan, robh, krzk+dt, conor+dt, vkoul, ychuang3,
	schung, robin.murphy, Frank.Li, dmaengine, devicetree,
	linux-kernel, cix-kernel-upstream, linux-arm-kernel
In-Reply-To: <aeia3uoz4g8tlBaV@lizhi-Precision-Tower-5810>



On 4/22/2026 5:54 PM, Frank Li wrote:
> [Some people who received this message don't often get email from frank.li@nxp.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> 
> EXTERNAL EMAIL
> 
> On Tue, Apr 21, 2026 at 03:24:11PM +0800, Jun Guo wrote:
>> Hi Robin,
>>
>> Just pinging. I’d like to ask if you have any comments on the latest patch?
>>
>> On 3/25/2026 7:21 PM, Jun Guo wrote:
>>> Enable DMANSECCTRL.INTREN_ANYCHINTR during probe so channel
>>> interrupts are propagated when integrators wire DMA-350 channels
>>> onto a shared IRQ line.
> 
> Your tag is wrong
> 
> dmaegine: arm-dma350: enable ANYCH ...	
Okay, I'll fix this in the next version.

> 
>>>
>>> Signed-off-by: Jun Guo <jun.guo@cixtech.com>
>>> ---
>>>    drivers/dma/arm-dma350.c | 9 +++++++++
>>>    1 file changed, 9 insertions(+)
>>>
>>> diff --git a/drivers/dma/arm-dma350.c b/drivers/dma/arm-dma350.c
>>> index 84220fa83029..09403aca8bb0 100644
>>> --- a/drivers/dma/arm-dma350.c
>>> +++ b/drivers/dma/arm-dma350.c
>>> @@ -13,6 +13,11 @@
>>>    #include "dmaengine.h"
>>>    #include "virt-dma.h"
> 
> extra empty line between header file and macro
The space actually exists in the code, but it is hidden in the review 
records.

> 
> 
>>> +#define DMANSECCTRL                0x200
>>> +
>>> +#define NSEC_CTRL          0x0c
> 
> why need two layer regiser define, your use DMANSECCTRL + NSEC_CTRL,
> 
> why not use one macro for 0x20c
> 
DMANSECCTRL is the base address for a set of control registers. 
Currently, only the NSEC_CTRL register within that set is being used. 
All other registers in the same group share this same base address, and 
a similar arrangement applies to DMAINFO.
> 
>>> +#define INTREN_ANYCHINTR_EN        BIT(0)
>>> +
>>>    #define DMAINFO                   0x0f00
>>>    #define DMA_BUILDCFG0             0xb0
>>> @@ -582,6 +587,10 @@ static int d350_probe(struct platform_device *pdev)
>>>      dmac->dma.device_issue_pending = d350_issue_pending;
>>>      INIT_LIST_HEAD(&dmac->dma.channels);
>>> +   reg = readl_relaxed(base + DMANSECCTRL + NSEC_CTRL);
>>> +   writel_relaxed(reg | INTREN_ANYCHINTR_EN,
>>> +                  base + DMANSECCTRL + NSEC_CTRL);
>>> +
>>>      /* Would be nice to have per-channel caps for this... */
>>>      memset = true;
>>>      for (int i = 0; i < nchan; i++) {
>>



^ permalink raw reply

* Re: [PATCH v2] perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA Olympus
From: James Clark @ 2026-04-22 10:32 UTC (permalink / raw)
  To: Besar Wicaksono, will, mark.rutland
  Cc: linux-arm-kernel, linux-kernel, linux-tegra, treding, jonathanh,
	vsethi, rwiley, sdonthineni, mochs, nirmoyd, skelley
In-Reply-To: <20260421203856.3539186-1-bwicaksono@nvidia.com>



On 21/04/2026 21:38, Besar Wicaksono wrote:
> The PMCCNTR_EL0 in NVIDIA Olympus CPU may increment while
> in WFI/WFE, which does not align with counting CPU_CYCLES
> on a programmable counter. Add a MIDR range entry and
> refuse PMCCNTR_EL0 for cycle events on affected parts so
> perf does not mix the two behaviors.
> 
> Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
> ---
> 
> Changes from v1:
>    * add CONFIG_ARM64 check to fix build error found by kernel test robot
>    * add explicit include of <asm/cputype.h>
> v1: https://lore.kernel.org/linux-arm-kernel/20260406232034.2566133-1-bwicaksono@nvidia.com/
> 
> ---
>   drivers/perf/arm_pmuv3.c | 44 ++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 44 insertions(+)
> 
> diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
> index 8014ff766cff..7c39d0804b9f 100644
> --- a/drivers/perf/arm_pmuv3.c
> +++ b/drivers/perf/arm_pmuv3.c
> @@ -8,6 +8,7 @@
>    * This code is based heavily on the ARMv7 perf event code.
>    */
>   
> +#include <asm/cputype.h>
>   #include <asm/irq_regs.h>
>   #include <asm/perf_event.h>
>   #include <asm/virt.h>
> @@ -978,6 +979,41 @@ static int armv8pmu_get_chain_idx(struct pmu_hw_events *cpuc,
>   	return -EAGAIN;
>   }
>   
> +#ifdef CONFIG_ARM64
> +/*
> + * List of CPUs that should avoid using PMCCNTR_EL0.
> + */
> +static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
> +	/*
> +	 * The PMCCNTR_EL0 in Olympus CPU may still increment while in WFI/WFE state.
> +	 * This is an implementation specific behavior and not an erratum.
> +	 *
> +	 * From ARM DDI0487 D14.4:
> +	 *   It is IMPLEMENTATION SPECIFIC whether CPU_CYCLES and PMCCNTR count
> +	 *   when the PE is in WFI or WFE state, even if the clocks are not stopped.
> +	 *
> +	 * From ARM DDI0487 D24.5.2:
> +	 *   All counters are subject to any changes in clock frequency, including
> +	 *   clock stopping caused by the WFI and WFE instructions.
> +	 *   This means that it is CONSTRAINED UNPREDICTABLE whether or not
> +	 *   PMCCNTR_EL0 continues to increment when clocks are stopped by WFI and
> +	 *   WFE instructions.
> +	 */
> +	MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
> +	{}
> +};
> +
> +static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
> +{
> +	return is_midr_in_range_list(armv8pmu_avoid_pmccntr_cpus);
> +}
> +#else
> +static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
> +{
> +	return false;
> +}
> +#endif
> +
>   static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
>   				     struct perf_event *event)
>   {
> @@ -1011,6 +1047,14 @@ static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
>   	if (cpu_pmu->has_smt)
>   		return false;
>   
> +	/*
> +	 * On some CPUs, PMCCNTR_EL0 does not match the behavior of CPU_CYCLES
> +	 * programmable counter, so avoid routing cycles through PMCCNTR_EL0 to
> +	 * prevent inconsistency in the results.
> +	 */
> +	if (armv8pmu_is_in_avoid_pmccntr_cpus())
> +		return false;
> +

Hi Besar,

This is called from armpmu_event_init() before the event is scheduled on 
the CPU so I don't think reading the MIDR at this point is safe.

When the PMU is probed you probably need to do an SMP call to get the 
MIDR of CPUs in that PMU's mask and then cache the "avoid pmccntr" 
result like has_smt. Or even rename has_smt to avoid_pmccntr and combine 
the two results there.

I don't know what will happen if none of those CPUs are online when the 
PMU is probed though...

James



>   	return true;
>   }
>   



^ permalink raw reply

* Re: [PATCH v2] mm/page_alloc: fix initialization of tags of the huge zero folio with init_on_free
From: Catalin Marinas @ 2026-04-22 10:32 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: linux-arm-kernel, Will Deacon, Andrew Morton, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Brendan Jackman,
	Johannes Weiner, Zi Yan, Lance Yang, Ryan Roberts, Mark Brown,
	Dev Jain, linux-kernel, linux-mm, stable
In-Reply-To: <20260421-zerotags-v2-1-05cb1035482e@kernel.org>

On Tue, Apr 21, 2026 at 05:39:07PM +0200, David Hildenbrand wrote:
> __GFP_ZEROTAGS semantics are currently a bit weird, but effectively this
> flag is only ever set alongside __GFP_ZERO and __GFP_SKIP_KASAN.
> 
> If we run with init_on_free, we will zero out pages during
> __free_pages_prepare(), to skip zeroing on the allocation path.
> 
> However, when allocating with __GFP_ZEROTAG set, post_alloc_hook() will
> consequently not only skip clearing page content, but also skip
> clearing tag memory.
> 
> Not clearing tags through __GFP_ZEROTAGS is irrelevant for most pages that
> will get mapped to user space through set_pte_at() later: set_pte_at() and
> friends will detect that the tags have not been initialized yet
> (PG_mte_tagged not set), and initialize them.
> 
> However, for the huge zero folio, which will be mapped through a PMD
> marked as special, this initialization will not be performed, ending up
> exposing whatever tags were still set for the pages.
> 
> The docs (Documentation/arch/arm64/memory-tagging-extension.rst) state
> that allocation tags are set to 0 when a page is first mapped to user
> space. That no longer holds with the huge zero folio when init_on_free
> is enabled.
> 
> Fix it by decoupling __GFP_ZEROTAGS from __GFP_ZERO, passing to
> tag_clear_highpages() whether we want to also clear page content.
> 
> Invert the meaning of the tag_clear_highpages() return value to have
> clearer semantics.
> 
> Reproduced with the huge zero folio by modifying the check_buffer_fill
> arm64/mte selftest to use a 2 MiB area, after making sure that pages have
> a non-0 tag set when freeing (note that, during boot, we will not
> actually initialize tags, but only set KASAN_TAG_KERNEL in the page
> flags).
> 
> 	$ ./check_buffer_fill
> 	1..20
> 	...
> 	not ok 17 Check initial tags with private mapping, sync error mode and mmap memory
> 	not ok 18 Check initial tags with private mapping, sync error mode and mmap/mprotect memory
> 	...
> 
> This code needs more cleanups; we'll tackle that next, like
> decoupling __GFP_ZEROTAGS from __GFP_SKIP_KASAN.
> 
> Fixes: adfb6609c680 ("mm/huge_memory: initialise the tags of the huge zero folio")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>

The logic looks fine to me. Thanks!

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>


^ permalink raw reply

* [PATCH] KVM: arm64: Validate the FF-A memory access descriptor placement
From: Sebastian Ene @ 2026-04-22 10:25 UTC (permalink / raw)
  To: maz, oupton, will
  Cc: ayrton, catalin.marinas, joey.gouly, korneld, kvmarm,
	linux-arm-kernel, linux-kernel, android-kvm, mrigendra.chaubey,
	perlarsen, sebastianene, suzuki.poulose, yuzenghui, stable

Prevent the pKVM hypervisor from making assumptions that the
endpoint memory access descriptor (EMAD) comes right after the
FF-A memory region header and enforce a strict placement for it
when validating an FF-A memory lend/share transaction.

Prior to FF-A version 1.1 the header of the memory region
didn't contain an offset to the endpoint memory access descriptor.
The layout of a memory transaction looks like this:

  Field name				| Offset
					 -- 0
[ Header (ffa_mem_region)               |__ ep_mem_offset
  EMAD 1 (ffa_mem_region_attributes)	|
]

Reject the host from specifying a memory access descriptor offset
that is different than the size of the memory region header.

Cc: stable@vger.kernel.org
Fixes: 42fb33dde42b ("KVM: arm64: Use FF-A 1.1 with pKVM")
Signed-off-by: Sebastian Ene <sebastianene@google.com>
---
 arch/arm64/kvm/hyp/nvhe/ffa.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 94161ea1cd60..0703c0ad8dff 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -508,6 +508,12 @@ static void __do_ffa_mem_xfer(const u64 func_id,
 	buf = hyp_buffers.tx;
 	memcpy(buf, host_buffers.tx, fraglen);
 
+	if (FFA_MEM_REGION_HAS_EP_MEM_OFFSET(hyp_ffa_version) &&
+	    buf->ep_mem_offset != sizeof(struct ffa_mem_region)) {
+		ret = FFA_RET_INVALID_PARAMETERS;
+		goto out_unlock;
+	}
+
 	ep_mem_access = (void *)buf +
 			ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
 	offset = ep_mem_access->composite_off;
-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply related

* Re: [PATCH v2 2/9] driver core: Add dev_set_drv_queue_sync_state()
From: Ulf Hansson @ 2026-04-22 10:25 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: Saravana Kannan, Rafael J . Wysocki, Greg Kroah-Hartman, linux-pm,
	Sudeep Holla, Cristian Marussi, Kevin Hilman, Stephen Boyd,
	Marek Szyprowski, Bjorn Andersson, Abel Vesa, Peng Fan,
	Tomi Valkeinen, Maulik Shah, Konrad Dybcio, Thierry Reding,
	Jonathan Hunter, Geert Uytterhoeven, Dmitry Baryshkov,
	linux-arm-kernel, linux-kernel, Geert Uytterhoeven, driver-core
In-Reply-To: <DHW8QV8K3CM1.307C6PW2BM5RN@kernel.org>

On Sat, 18 Apr 2026 at 13:24, Danilo Krummrich <dakr@kernel.org> wrote:
>
> On Fri Apr 10, 2026 at 12:40 PM CEST, Ulf Hansson wrote:
> > diff --git a/include/linux/device.h b/include/linux/device.h
> > index e65d564f01cd..f812e70bdf22 100644
> > --- a/include/linux/device.h
> > +++ b/include/linux/device.h
> > @@ -994,6 +994,18 @@ static inline int dev_set_drv_sync_state(struct device *dev,
> >       return 0;
> >  }
> >
> > +static inline int dev_set_drv_queue_sync_state(struct device *dev,
> > +                                            void (*fn)(struct device *dev))
>
> As this is a public function, please add some documentation.

Most of the static inline functions in device.h lacks documentation.
Are you suggesting that we should move towards documenting all of
them?

In this case, dev_set_drv_sync_state() also lacks documentation and to
me, it doesn't make sense to add documentation only for
dev_set_drv_queue_sync_state(). Do you want me to add it for both?

[...]

Kind regards
Uffe


^ permalink raw reply

* Re: [PATCH v4 2/2] arm64: dts: amlogic: add support for Amediatech X98Q
From: Ferass El Hafidi @ 2026-04-22 10:02 UTC (permalink / raw)
  To: linux-amlogic, christian.koever-draxl, robh, krzk+dt, conor+dt,
	neil.armstrong, khilman
  Cc: jbrunet, martin.blumenstingl, devicetree, linux-amlogic,
	linux-arm-kernel, linux-kernel,
	Christian Stefan Kövér-Draxl
In-Reply-To: <20260422095840.26139-3-christian.koever-draxl@student.uibk.ac.at>

On Wed, 22 Apr 2026 09:58, christian.koever-draxl@student.uibk.ac.at wrote:
>From: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
>
>Add dts enabling core hardware for the Amediatech X98Q TV box.
>
>The board features:
>- Amlogic S905W2 (Meson S4) SoC
>- 1 GiB RAM (2 GiB variants exist)
>- eMMC and microSD card slot
>- SDIO-based WiFi module (unsupported)
>- RMII Ethernet with internal PHY
>- IR receiver and UART console
>- Status LED
>
>Enabled peripherals:
>- eMMC (HS200)
>- SD card interface
>- SDIO bus (WiFi, no driver yet)
>- Ethernet (RMII)
>- UART_B
>- IR receiver
>- PWM-controlled CPU regulator
>- PWM and Fixed regulators for core and IO rails
>
>Known limitations:
>- No support for the onboard WiFi module
>- Missing multimedia (HDMI/audio)
>
>Signed-off-by: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
>---
> arch/arm64/boot/dts/amlogic/Makefile          |   1 +
> .../boot/dts/amlogic/meson-s4-s905w2-x98q.dts | 249 ++++++++++++++++++
> 2 files changed, 250 insertions(+)
> create mode 100644 arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
><...>
>+&sd {
>+	status = "okay";
>+	pinctrl-0 = <&sdcard_pins>;
>+	pinctrl-1 = <&sdcard_clk_gate_pins>;
>+	pinctrl-names = "default", "clk-gate";
>+	bus-width = <4>;
>+	cap-sd-highspeed;
>+	max-frequency = <50000000>;
>+	disable-wp;
>+
>+	cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
>+
>+	vmmc-supply = <&vddao_3v3>;
>+	vqmmc-supply = <&vddao_3v3>;
>+};
>+
>+     /*
>+      * Wireless SDIO Module (Amlogic W150S1)
>+      * Note: There is no driver for this at the moment.
>+      */
>+

I didn't mean to indent, just to align the '*'.
Sorry it wasn't clear.

>+&sdio {
>+	status = "okay";
>+	pinctrl-0 = <&sdio_pins>;
>+	pinctrl-1 = <&sdio_clk_gate_pins>;
>+	pinctrl-names = "default", "clk-gate";
>+	#address-cells = <1>;
>+	#size-cells = <0>;
>+	bus-width = <4>;
>+	cap-sd-highspeed;
>+	sd-uhs-sdr50;
>+	sd-uhs-sdr104;
>+	max-frequency = <200000000>;
>+	non-removable;
>+	disable-wp;
>+
>+	no-sd;
>+	no-mmc;
>+	mmc-pwrseq = <&sdio_pwrseq>;
>+	vmmc-supply = <&vddao_3v3>;
>+	vqmmc-supply = <&vddio_ao1v8>;
>+};
>+
>+&uart_b {
>+	status = "okay";
>+};
>-- 
>2.53.0

--
Best regards,
Ferass


^ permalink raw reply

* Re: [PATCH v2 1/9] driver core: Enable suppliers to implement fine grained sync_state support
From: Ulf Hansson @ 2026-04-22 10:07 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: Saravana Kannan, Rafael J . Wysocki, Greg Kroah-Hartman, linux-pm,
	Sudeep Holla, Cristian Marussi, Kevin Hilman, Stephen Boyd,
	Marek Szyprowski, Bjorn Andersson, Abel Vesa, Peng Fan,
	Tomi Valkeinen, Maulik Shah, Konrad Dybcio, Thierry Reding,
	Jonathan Hunter, Geert Uytterhoeven, Dmitry Baryshkov,
	linux-arm-kernel, linux-kernel, Geert Uytterhoeven, driver-core
In-Reply-To: <DHW8QPU1VU1F.3P6PH69HLFBYC@kernel.org>

On Sat, 18 Apr 2026 at 13:23, Danilo Krummrich <dakr@kernel.org> wrote:
>
> On Fri Apr 10, 2026 at 12:40 PM CEST, Ulf Hansson wrote:
> > The common sync_state support isn't fine grained enough for some types of
> > suppliers, like power domains for example. Especially when a supplier
> > provides multiple independent power domains, each with their own set of
> > consumers. In these cases we need to wait for all consumers for all the
> > provided power domains before invoking the supplier's ->sync_state().
> >
> > To allow a more fine grained sync_state support to be implemented on per
> > supplier's driver basis, let's add a new optional callback. As soon as
> > there is an update worth to consider in regards to managing sync_state for
> > a supplier device, __device_links_queue_sync_state() invokes the callback.
> >
> > Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >  drivers/base/core.c           | 7 ++++++-
> >  include/linux/device/driver.h | 7 +++++++
> >  2 files changed, 13 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/base/core.c b/drivers/base/core.c
> > index 09b98f02f559..4085a011d8ca 100644
> > --- a/drivers/base/core.c
> > +++ b/drivers/base/core.c
> > @@ -1106,7 +1106,9 @@ int device_links_check_suppliers(struct device *dev)
> >   * Queues a device for a sync_state() callback when the device links write lock
> >   * isn't held. This allows the sync_state() execution flow to use device links
> >   * APIs.  The caller must ensure this function is called with
> > - * device_links_write_lock() held.
> > + * device_links_write_lock() held.  Note, if the optional queue_sync_state()
> > + * callback has been assigned too, it gets called for every update to allowing a
>
> s/allowing/allow/
>
> > + * more fine grained support to be implemented on per supplier basis.
> >   *
> >   * This function does a get_device() to make sure the device is not freed while
> >   * on this list.
> > @@ -1126,6 +1128,9 @@ static void __device_links_queue_sync_state(struct device *dev,
> >       if (dev->state_synced)
> >               return;
> >
> > +     if (dev->driver && dev->driver->queue_sync_state)
> > +             dev->driver->queue_sync_state(dev);
>
> This seems to be called without the device lock being held, which seems to allow
> the queue_sync_state() callback to execute concurrently with remove(). This
> opens the door for all kinds of UAF conditions in drivers.

If that were the case, this whole function would be unsafe even before
this change. I assume this isn't because of how the function is being
called, but I may be wrong.

Anyway, let me add a get/put_device() here somewhere, to ensure we
prevent this from happening. I assume that is what you are proposing?

>
> This also made me aware that the above dev_has_sync_state() is probably broken,
> as it also performs the following check without the device lock being held.
>
>         dev->driver && dev->driver->sync_state
>
> I think nothing prevents dev->driver to become NULL concurrently; in this case
> READ_ONCE() should be sufficient though as it doesn't execute the callback.
>
> I will send a patch for this.

Okay, thanks!

>
> > +
> >       list_for_each_entry(link, &dev->links.consumers, s_node) {
> >               if (!device_link_test(link, DL_FLAG_MANAGED))
> >                       continue;
> > diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h
> > index bbc67ec513ed..bc9ae1cbe03c 100644
> > --- a/include/linux/device/driver.h
> > +++ b/include/linux/device/driver.h
> > @@ -68,6 +68,12 @@ enum probe_type {
> >   *           be called at late_initcall_sync level. If the device has
> >   *           consumers that are never bound to a driver, this function
> >   *           will never get called until they do.
> > + * @queue_sync_state: Similar to the ->sync_state() callback, but called to
> > + *           allow syncing device state to software state in a more fine
> > + *           grained way. It is called when there is an updated state that
> > + *           may be worth to consider for any of the consumers linked to
> > + *           this device. If implemented, the ->sync_state() callback is
> > + *           required too.
>
> What happens if this is not the case? Maybe worth to check and warn about this
> in driver_register().

Good point!

I believe I should also add a check in dev_set_drv_queue_sync_state()
that is added in patch2.

>
> >   * @remove:  Called when the device is removed from the system to
> >   *           unbind a device from this driver.
> >   * @shutdown:        Called at shut-down time to quiesce the device.
> > @@ -110,6 +116,7 @@ struct device_driver {
> >
> >       int (*probe) (struct device *dev);
> >       void (*sync_state)(struct device *dev);
> > +     void (*queue_sync_state)(struct device *dev);
> >       int (*remove) (struct device *dev);
> >       void (*shutdown) (struct device *dev);
> >       int (*suspend) (struct device *dev, pm_message_t state);
> > --
> > 2.43.0
>

Thanks for reviewing!

Kind regards
Uffe


^ permalink raw reply

* [PATCH v2 2/4] KVM: arm64: timer: Kill the per-timer level cache
From: Marc Zyngier @ 2026-04-22 10:02 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Deepanshu Kartikey, Joey Gouly, Suzuki K Poulose, Oliver Upton,
	Zenghui Yu
In-Reply-To: <20260422100210.3008156-1-maz@kernel.org>

The timer code makes use of a per-timer irq level cache, which
looks like a very minor optimisation to avoid taking a lock upon
updating the GIC view of the interrupt when it is unchanged from
the previous state.

This is coming in the way of more important correctness issues,
so get rid of the cache, which simplifies a couple of minor things.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/arch_timer.c  | 20 +++++++++-----------
 include/kvm/arm_arch_timer.h |  5 -----
 2 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 22e79ecb34bc4..5cfe223da2996 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -445,9 +445,8 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
 {
 	kvm_timer_update_status(timer_ctx, new_level);
 
-	timer_ctx->irq.level = new_level;
 	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_irq(timer_ctx),
-				   timer_ctx->irq.level);
+				   new_level);
 
 	if (userspace_irqchip(vcpu->kvm))
 		return;
@@ -465,7 +464,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
 
 	kvm_vgic_inject_irq(vcpu->kvm, vcpu,
 			    timer_irq(timer_ctx),
-			    timer_ctx->irq.level,
+			    new_level,
 			    timer_ctx);
 }
 
@@ -476,10 +475,7 @@ static void timer_emulate(struct arch_timer_context *ctx)
 
 	trace_kvm_timer_emulate(ctx, pending);
 
-	if (pending != ctx->irq.level)
-		kvm_timer_update_irq(timer_context_to_vcpu(ctx), pending, ctx);
-
-	kvm_timer_update_status(ctx, pending);
+	kvm_timer_update_irq(timer_context_to_vcpu(ctx), pending, ctx);
 
 	/*
 	 * If the timer can fire now, we don't need to have a soft timer
@@ -676,6 +672,7 @@ static inline void set_timer_irq_phys_active(struct arch_timer_context *ctx, boo
 static void kvm_timer_vcpu_load_gic(struct arch_timer_context *ctx)
 {
 	struct kvm_vcpu *vcpu = timer_context_to_vcpu(ctx);
+	bool pending = kvm_timer_pending(ctx);
 	bool phys_active = false;
 
 	/*
@@ -684,12 +681,12 @@ static void kvm_timer_vcpu_load_gic(struct arch_timer_context *ctx)
 	 * this point and the register restoration, we'll take the
 	 * interrupt anyway.
 	 */
-	kvm_timer_update_irq(vcpu, kvm_timer_pending(ctx), ctx);
+	kvm_timer_update_irq(vcpu, pending, ctx);
 
 	if (irqchip_in_kernel(vcpu->kvm))
 		phys_active = kvm_vgic_map_is_active(vcpu, timer_irq(ctx));
 
-	phys_active |= ctx->irq.level;
+	phys_active |= pending;
 	phys_active |= vgic_is_v5(vcpu->kvm);
 
 	set_timer_irq_phys_active(ctx, phys_active);
@@ -698,6 +695,7 @@ static void kvm_timer_vcpu_load_gic(struct arch_timer_context *ctx)
 static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
 {
 	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+	bool pending = kvm_timer_pending(vtimer);
 
 	/*
 	 * Update the timer output so that it is likely to match the
@@ -705,7 +703,7 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
 	 * this point and the register restoration, we'll take the
 	 * interrupt anyway.
 	 */
-	kvm_timer_update_irq(vcpu, kvm_timer_pending(vtimer), vtimer);
+	kvm_timer_update_irq(vcpu, pending, vtimer);
 
 	/*
 	 * When using a userspace irqchip with the architected timers and a
@@ -717,7 +715,7 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
 	 * being de-asserted, we unmask the interrupt again so that we exit
 	 * from the guest when the timer fires.
 	 */
-	if (vtimer->irq.level)
+	if (pending)
 		disable_percpu_irq(host_vtimer_irq);
 	else
 		enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index bf8cc9589bd09..2c26d457c3510 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -66,11 +66,6 @@ struct arch_timer_context {
 	 */
 	bool				loaded;
 
-	/* Output level of the timer IRQ */
-	struct {
-		bool			level;
-	} irq;
-
 	/* Who am I? */
 	enum kvm_arch_timers		timer_id;
 
-- 
2.47.3



^ permalink raw reply related

* [PATCH v2 4/4] KVM: arm64: vgic-v2: Don't init the vgic on in-kernel interrupt injection
From: Marc Zyngier @ 2026-04-22 10:02 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Deepanshu Kartikey, Joey Gouly, Suzuki K Poulose, Oliver Upton,
	Zenghui Yu
In-Reply-To: <20260422100210.3008156-1-maz@kernel.org>

We how have the lazy init on three paths:

- on first run of a vcpu
- on first injection of an interrupt from userspace and irqfd
- on first injection of an interrupt from kernel space as
  part of the device emulation (timers, PMU, vgic MI)

Given that we recompute the state of each in-kernel interrupt
every time we are about to enter the guest, we can drop the lazy
init from the kernel injection path.

This solves a bunch of issues related to vgic_lazy_init() being called
in non-preemptible context, such as vcpu reset.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/vgic/vgic.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index 1e9fe8764584d..9e29f03d3463c 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -534,11 +534,9 @@ int kvm_vgic_inject_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 {
 	struct vgic_irq *irq;
 	unsigned long flags;
-	int ret;
 
-	ret = vgic_lazy_init(kvm);
-	if (ret)
-		return ret;
+	if (unlikely(!vgic_initialized(kvm)))
+		return 0;
 
 	if (!vcpu && irq_is_private(kvm, intid))
 		return -EINVAL;
-- 
2.47.3



^ permalink raw reply related

* [PATCH v2 1/4] KVM: arm64: timer: Repaint kvm_timer_{should,irq_can}_fire() to kvm_timer_{pending,enabled}()
From: Marc Zyngier @ 2026-04-22 10:02 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Deepanshu Kartikey, Joey Gouly, Suzuki K Poulose, Oliver Upton,
	Zenghui Yu
In-Reply-To: <20260422100210.3008156-1-maz@kernel.org>

kvm_timer_should_fire() seems to date back to a time where the author
of the timer code didn't seem to have made the word "pending" part of
their vocabulary.

Having since slightly improved on that front, let's rename this predicate
to kvm_timer_pending(), which clearly indicates whether the timer
interrupt is pending or not.

Similarly, kvm_timer_irq_can_fire() is renamed to kvm_timer_enabled().

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/arch_timer.c | 49 ++++++++++++++++++-------------------
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index cbea4d9ee9552..22e79ecb34bc4 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -39,10 +39,9 @@ static const u8 default_ppi[] = {
 	[TIMER_HVTIMER] = 28,
 };
 
-static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx);
 static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
 				 struct arch_timer_context *timer_ctx);
-static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx);
+static bool kvm_timer_pending(struct arch_timer_context *timer_ctx);
 static void kvm_arm_timer_write(struct kvm_vcpu *vcpu,
 				struct arch_timer_context *timer,
 				enum kvm_arch_timer_regs treg,
@@ -224,7 +223,7 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
 	else
 		ctx = map.direct_ptimer;
 
-	if (kvm_timer_should_fire(ctx))
+	if (kvm_timer_pending(ctx))
 		kvm_timer_update_irq(vcpu, true, ctx);
 
 	if (userspace_irqchip(vcpu->kvm) &&
@@ -257,7 +256,7 @@ static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
 	return kvm_counter_compute_delta(timer_ctx, timer_get_cval(timer_ctx));
 }
 
-static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
+static bool kvm_timer_enabled(struct arch_timer_context *timer_ctx)
 {
 	WARN_ON(timer_ctx && timer_ctx->loaded);
 	return timer_ctx &&
@@ -294,7 +293,7 @@ static u64 kvm_timer_earliest_exp(struct kvm_vcpu *vcpu)
 		struct arch_timer_context *ctx = &vcpu->arch.timer_cpu.timers[i];
 
 		WARN(ctx->loaded, "timer %d loaded\n", i);
-		if (kvm_timer_irq_can_fire(ctx))
+		if (kvm_timer_enabled(ctx))
 			min_delta = min(min_delta, kvm_timer_compute_delta(ctx));
 	}
 
@@ -358,7 +357,7 @@ static enum hrtimer_restart kvm_hrtimer_expire(struct hrtimer *hrt)
 	return HRTIMER_NORESTART;
 }
 
-static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
+static bool kvm_timer_pending(struct arch_timer_context *timer_ctx)
 {
 	enum kvm_arch_timers index;
 	u64 cval, now;
@@ -391,7 +390,7 @@ static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
 		       !(cnt_ctl & ARCH_TIMER_CTRL_IT_MASK);
 	}
 
-	if (!kvm_timer_irq_can_fire(timer_ctx))
+	if (!kvm_timer_enabled(timer_ctx))
 		return false;
 
 	cval = timer_get_cval(timer_ctx);
@@ -417,9 +416,9 @@ void kvm_timer_update_run(struct kvm_vcpu *vcpu)
 	/* Populate the device bitmap with the timer states */
 	regs->device_irq_level &= ~(KVM_ARM_DEV_EL1_VTIMER |
 				    KVM_ARM_DEV_EL1_PTIMER);
-	if (kvm_timer_should_fire(vtimer))
+	if (kvm_timer_pending(vtimer))
 		regs->device_irq_level |= KVM_ARM_DEV_EL1_VTIMER;
-	if (kvm_timer_should_fire(ptimer))
+	if (kvm_timer_pending(ptimer))
 		regs->device_irq_level |= KVM_ARM_DEV_EL1_PTIMER;
 }
 
@@ -473,21 +472,21 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
 /* Only called for a fully emulated timer */
 static void timer_emulate(struct arch_timer_context *ctx)
 {
-	bool should_fire = kvm_timer_should_fire(ctx);
+	bool pending = kvm_timer_pending(ctx);
 
-	trace_kvm_timer_emulate(ctx, should_fire);
+	trace_kvm_timer_emulate(ctx, pending);
 
-	if (should_fire != ctx->irq.level)
-		kvm_timer_update_irq(timer_context_to_vcpu(ctx), should_fire, ctx);
+	if (pending != ctx->irq.level)
+		kvm_timer_update_irq(timer_context_to_vcpu(ctx), pending, ctx);
 
-	kvm_timer_update_status(ctx, should_fire);
+	kvm_timer_update_status(ctx, pending);
 
 	/*
 	 * If the timer can fire now, we don't need to have a soft timer
 	 * scheduled for the future.  If the timer cannot fire at all,
 	 * then we also don't need a soft timer.
 	 */
-	if (should_fire || !kvm_timer_irq_can_fire(ctx))
+	if (pending || !kvm_timer_enabled(ctx))
 		return;
 
 	soft_timer_start(&ctx->hrtimer, kvm_timer_compute_delta(ctx));
@@ -594,10 +593,10 @@ static void kvm_timer_blocking(struct kvm_vcpu *vcpu)
 	 * If no timers are capable of raising interrupts (disabled or
 	 * masked), then there's no more work for us to do.
 	 */
-	if (!kvm_timer_irq_can_fire(map.direct_vtimer) &&
-	    !kvm_timer_irq_can_fire(map.direct_ptimer) &&
-	    !kvm_timer_irq_can_fire(map.emul_vtimer) &&
-	    !kvm_timer_irq_can_fire(map.emul_ptimer) &&
+	if (!kvm_timer_enabled(map.direct_vtimer) &&
+	    !kvm_timer_enabled(map.direct_ptimer) &&
+	    !kvm_timer_enabled(map.emul_vtimer) &&
+	    !kvm_timer_enabled(map.emul_ptimer) &&
 	    !vcpu_has_wfit_active(vcpu))
 		return;
 
@@ -685,7 +684,7 @@ static void kvm_timer_vcpu_load_gic(struct arch_timer_context *ctx)
 	 * this point and the register restoration, we'll take the
 	 * interrupt anyway.
 	 */
-	kvm_timer_update_irq(vcpu, kvm_timer_should_fire(ctx), ctx);
+	kvm_timer_update_irq(vcpu, kvm_timer_pending(ctx), ctx);
 
 	if (irqchip_in_kernel(vcpu->kvm))
 		phys_active = kvm_vgic_map_is_active(vcpu, timer_irq(ctx));
@@ -706,7 +705,7 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
 	 * this point and the register restoration, we'll take the
 	 * interrupt anyway.
 	 */
-	kvm_timer_update_irq(vcpu, kvm_timer_should_fire(vtimer), vtimer);
+	kvm_timer_update_irq(vcpu, kvm_timer_pending(vtimer), vtimer);
 
 	/*
 	 * When using a userspace irqchip with the architected timers and a
@@ -917,8 +916,8 @@ bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu)
 	vlevel = sregs->device_irq_level & KVM_ARM_DEV_EL1_VTIMER;
 	plevel = sregs->device_irq_level & KVM_ARM_DEV_EL1_PTIMER;
 
-	return kvm_timer_should_fire(vtimer) != vlevel ||
-	       kvm_timer_should_fire(ptimer) != plevel;
+	return kvm_timer_pending(vtimer) != vlevel ||
+	       kvm_timer_pending(ptimer) != plevel;
 }
 
 void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
@@ -1006,7 +1005,7 @@ static void unmask_vtimer_irq_user(struct kvm_vcpu *vcpu)
 {
 	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
 
-	if (!kvm_timer_should_fire(vtimer)) {
+	if (!kvm_timer_pending(vtimer)) {
 		kvm_timer_update_irq(vcpu, false, vtimer);
 		if (static_branch_likely(&has_gic_active_state))
 			set_timer_irq_phys_active(vtimer, false);
@@ -1579,7 +1578,7 @@ static bool kvm_arch_timer_get_input_level(int vintid)
 
 		ctx = vcpu_get_timer(vcpu, i);
 		if (timer_irq(ctx) == vintid)
-			return kvm_timer_should_fire(ctx);
+			return kvm_timer_pending(ctx);
 	}
 
 	/* A timer IRQ has fired, but no matching timer was found? */
-- 
2.47.3



^ permalink raw reply related

* [PATCH v2 3/4] KVM: arm64: vgic-v2: Force vgic init on injection outside the run loop
From: Marc Zyngier @ 2026-04-22 10:02 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Deepanshu Kartikey, Joey Gouly, Suzuki K Poulose, Oliver Upton,
	Zenghui Yu
In-Reply-To: <20260422100210.3008156-1-maz@kernel.org>

Make sure that any attempt to inject an interrupt from userspace
or an irqfd results in the GICv2 lazy init to take place.

This is not currently necessary as the init is also performed on
*any* interrupt injection. But as we're about to remove that,
let's introduce it here.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/arm.c             | 7 +++++++
 arch/arm64/kvm/vgic/vgic-irqfd.c | 6 ++++++
 2 files changed, 13 insertions(+)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 176cbe8baad30..e856cf4099f42 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -51,6 +51,7 @@
 
 #include <linux/irqchip/arm-gic-v5.h>
 
+#include "vgic/vgic.h"
 #include "sys_regs.h"
 
 static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT;
@@ -1475,6 +1476,12 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
 
 	trace_kvm_irq_line(irq_type, vcpu_id, irq_num, irq_level->level);
 
+	if (irqchip_in_kernel(kvm)) {
+		int ret = vgic_lazy_init(kvm);
+		if (ret)
+			return ret;
+	}
+
 	switch (irq_type) {
 	case KVM_ARM_IRQ_TYPE_CPU:
 		if (irqchip_in_kernel(kvm))
diff --git a/arch/arm64/kvm/vgic/vgic-irqfd.c b/arch/arm64/kvm/vgic/vgic-irqfd.c
index b9b86e3a6c862..19a1094536e6a 100644
--- a/arch/arm64/kvm/vgic/vgic-irqfd.c
+++ b/arch/arm64/kvm/vgic/vgic-irqfd.c
@@ -20,9 +20,15 @@ static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
 			int level, bool line_status)
 {
 	unsigned int spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
+	int ret;
 
 	if (!vgic_valid_spi(kvm, spi_id))
 		return -EINVAL;
+
+	ret = vgic_lazy_init(kvm);
+	if (ret)
+		return ret;
+
 	return kvm_vgic_inject_irq(kvm, NULL, spi_id, level, NULL);
 }
 
-- 
2.47.3



^ permalink raw reply related

* [PATCH v2 0/4] KVM: arm64: Don't perform vgic-v2 lazy init on timer injection
From: Marc Zyngier @ 2026-04-22 10:02 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Deepanshu Kartikey, Joey Gouly, Suzuki K Poulose, Oliver Upton,
	Zenghui Yu

This is the second version of this series aiming at fixing issues
with vgic-v2 being initialised from non-preemptible context.

* From v1 [1]:

  - Repaint kvm_timer_irq_can_fire() to kvm_timer_enabled()

  - Drop duplicate kvm_timer_update_status() call

  - Force lazy init on the irqfd slow-path for SPIs

[1] https://lore.kernel.org/r/20260417124612.2770268-1-maz@kernel.org

Marc Zyngier (4):
  KVM: arm64: timer: Repaint kvm_timer_{should,irq_can}_fire() to
    kvm_timer_{pending,enabled}()
  KVM: arm64: timer: Kill the per-timer level cache
  KVM: arm64: vgic-v2: Force vgic init on injection outside the run loop
  KVM: arm64: vgic-v2: Don't init the vgic on in-kernel interrupt
    injection

 arch/arm64/kvm/arch_timer.c      | 59 +++++++++++++++-----------------
 arch/arm64/kvm/arm.c             |  7 ++++
 arch/arm64/kvm/vgic/vgic-irqfd.c |  6 ++++
 arch/arm64/kvm/vgic/vgic.c       |  6 ++--
 include/kvm/arm_arch_timer.h     |  5 ---
 5 files changed, 43 insertions(+), 40 deletions(-)

-- 
2.47.3



^ permalink raw reply

* [PATCH v4 2/2] arm64: dts: amlogic: add support for Amediatech X98Q
From: christian.koever-draxl @ 2026-04-22  9:58 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, neil.armstrong, khilman
  Cc: jbrunet, martin.blumenstingl, devicetree, linux-amlogic,
	linux-arm-kernel, linux-kernel,
	Christian Stefan Kövér-Draxl
In-Reply-To: <20260422095840.26139-1-christian.koever-draxl@student.uibk.ac.at>

From: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>

Add dts enabling core hardware for the Amediatech X98Q TV box.

The board features:
- Amlogic S905W2 (Meson S4) SoC
- 1 GiB RAM (2 GiB variants exist)
- eMMC and microSD card slot
- SDIO-based WiFi module (unsupported)
- RMII Ethernet with internal PHY
- IR receiver and UART console
- Status LED

Enabled peripherals:
- eMMC (HS200)
- SD card interface
- SDIO bus (WiFi, no driver yet)
- Ethernet (RMII)
- UART_B
- IR receiver
- PWM-controlled CPU regulator
- PWM and Fixed regulators for core and IO rails

Known limitations:
- No support for the onboard WiFi module
- Missing multimedia (HDMI/audio)

Signed-off-by: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
---
 arch/arm64/boot/dts/amlogic/Makefile          |   1 +
 .../boot/dts/amlogic/meson-s4-s905w2-x98q.dts | 249 ++++++++++++++++++
 2 files changed, 250 insertions(+)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts

diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 15f9c817e502..c7752684dea6 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -85,6 +85,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-ugoos-am3.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-wetek-core2.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-s4-s805x2-aq222.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905w2-x98q.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905y4-khadas-vim1s.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air-gbit.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air.dtb
diff --git a/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
index 000000000000..3eecbc858522
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2026 Christian Stefan Köver-Draxl
+ * Based on meson-s4-s905y4-khadas-vim1s.dts:
+ *  - Copyright (c) 2026 Khadas Technology Co., Ltd.
+ */
+
+/dts-v1/;
+
+#include "meson-s4.dtsi"
+
+/ {
+	model = "Shenzhen Amediatech Technology Co., Ltd X98Q";
+	compatible = "amediatech,x98q", "amlogic,s905w2", "amlogic,s4";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		mmc0 = &emmc; /* eMMC */
+		mmc1 = &sd; /* SD card */
+		mmc2 = &sdio; /* SDIO */
+		serial0 = &uart_b;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x40000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 52 MiB reserved for ARM Trusted Firmware */
+		secmon_reserved: secmon@5000000 {
+			reg = <0x0 0x05000000 0x0 0x3400000>;
+			no-map;
+		};
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio GPIOB_9 GPIO_ACTIVE_LOW>;
+	};
+
+	sdio_32k: sdio-32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+		clocks = <&sdio_32k>;
+		clock-names = "ext_clock";
+	};
+
+	main_5v: regulator-main-5v {
+		compatible = "regulator-fixed";
+		regulator-name = "5V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	sd_3v3: regulator-sd-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "SD_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio GPIOD_4 GPIO_ACTIVE_LOW>;
+		regulator-always-on;
+	};
+
+	vddio_sd: regulator-vddio-sd {
+		compatible = "regulator-gpio";
+		regulator-name = "VDDIO_SD";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		gpios = <&gpio GPIOD_9 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <1800000 1 3300000 0>;
+	};
+
+	vddao_3v3: regulator-vddao-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&main_5v>;
+		regulator-always-on;
+	};
+
+	vddio_ao1v8: regulator-vddio-ao1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_AO1V8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vddao_3v3>;
+		regulator-always-on;
+	};
+
+	/* SY8120B1ABC DC/DC Regulator. */
+	vddcpu: regulator-vddcpu {
+		compatible = "pwm-regulator";
+
+		regulator-name = "VDDCPU";
+		regulator-min-microvolt = <689000>;
+		regulator-max-microvolt = <1049000>;
+
+		vin-supply = <&main_5v>;
+
+		pwms = <&pwm_ij 1 1500 0>;
+		pwm-dutycycle-range = <100 0>;
+
+		regulator-boot-on;
+		regulator-always-on;
+		/* Voltage Duty-Cycle */
+		voltage-table = <1049000 0>,
+				<1039000 3>,
+				<1029000 6>,
+				<1019000 9>,
+				<1009000 12>,
+				<999000 14>,
+				<989000 17>,
+				<979000 20>,
+				<969000 23>,
+				<959000 26>,
+				<949000 29>,
+				<939000 31>,
+				<929000 34>,
+				<919000 37>,
+				<909000 40>,
+				<899000 43>,
+				<889000 45>,
+				<879000 48>,
+				<869000 51>,
+				<859000 54>,
+				<849000 56>,
+				<839000 59>,
+				<829000 62>,
+				<819000 65>,
+				<809000 68>,
+				<799000 70>,
+				<789000 73>,
+				<779000 76>,
+				<769000 79>,
+				<759000 81>,
+				<749000 84>,
+				<739000 87>,
+				<729000 89>,
+				<719000 92>,
+				<709000 95>,
+				<699000 98>,
+				<689000 100>;
+	};
+};
+
+&emmc {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
+	pinctrl-1 = <&emmc_clk_gate_pins>;
+	pinctrl-names = "default", "clk-gate";
+
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_ao1v8>;
+};
+
+&ethmac {
+	status = "okay";
+	phy-handle = <&internal_ephy>;
+	phy-mode = "rmii";
+};
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_pins>;
+	pinctrl-names = "default";
+};
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins1>;
+	pinctrl-names = "default";
+};
+
+&pwm_ij {
+	status = "okay";
+};
+
+&sd {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-1 = <&sdcard_clk_gate_pins>;
+	pinctrl-names = "default", "clk-gate";
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <50000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddao_3v3>;
+};
+
+     /*
+      * Wireless SDIO Module (Amlogic W150S1)
+      * Note: There is no driver for this at the moment.
+      */
+
+&sdio {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-1 = <&sdio_clk_gate_pins>;
+	pinctrl-names = "default", "clk-gate";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	bus-width = <4>;
+	cap-sd-highspeed;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+
+	no-sd;
+	no-mmc;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_ao1v8>;
+};
+
+&uart_b {
+	status = "okay";
+};
-- 
2.53.0



^ permalink raw reply related

* [PATCH v4 0/2] Add support for Amediatech X98Q (Amlogic S905W2)
From: christian.koever-draxl @ 2026-04-22  9:58 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, neil.armstrong, khilman
  Cc: jbrunet, martin.blumenstingl, devicetree, linux-amlogic,
	linux-arm-kernel, linux-kernel,
	Christian Stefan Kövér-Draxl

From: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>

Supported features:
- 1GB RAM (2GB variants exist)
- 10/100 Ethernet (Internal PHY)
- eMMC and SD card storage
- PWM-based CPU voltage regulation
- UART (Serial console)

Notes:
- The console uses uart_b at 921600 baud.
- Verified memory via /proc/device-tree; U-Boot patches the node.
- Tested on the 2GB RAM plus 16GB eMMC variant. 

Changes in v4:
- Add/Change hardware description to cover letter and dts patch.

Changes in v3:
- Change position of the entry in the amlogic.yaml.
- Change formatting of the Amlogic W150S1 Wi-Fi module comment.
- Fix several formatting issues.

Changes in v2:
- Split dt-bindings and dts changes into separate patches.
- Updated model string to match documented vendor prefix.
- Put vddio_sd states array in a single line.
- Added a comment for the unsupported Amlogic W150S1 Wi-Fi module. 

Christian Stefan Kövér-Draxl (2):
  dt-bindings: arm: amlogic: add support for Amediatech X98Q
  arm64: dts: amlogic: add support for Amediatech X98Q

 .../devicetree/bindings/arm/amlogic.yaml      |   7 +
 arch/arm64/boot/dts/amlogic/Makefile          |   1 +
 .../boot/dts/amlogic/meson-s4-s905w2-x98q.dts | 249 ++++++++++++++++++
 3 files changed, 257 insertions(+)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts

-- 
2.53.0



^ permalink raw reply

* [PATCH v4 1/2] dt-bindings: arm: amlogic: add support for Amediatech X98Q
From: christian.koever-draxl @ 2026-04-22  9:58 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, neil.armstrong, khilman
  Cc: jbrunet, martin.blumenstingl, devicetree, linux-amlogic,
	linux-arm-kernel, linux-kernel,
	Christian Stefan Kövér-Draxl, Conor Dooley
In-Reply-To: <20260422095840.26139-1-christian.koever-draxl@student.uibk.ac.at>

From: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>

Add the board binding for the Amediatech X98Q TV box.

Signed-off-by: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index a885278bc4e2..c0167fbc310a 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -248,6 +248,13 @@ properties:
           - const: amlogic,s805x2
           - const: amlogic,s4
 
+      - description: Boards with the Amlogic Meson S4 S905W2 SoC
+        items:
+          - enum:
+              - amediatech,x98q
+          - const: amlogic,s905w2
+          - const: amlogic,s4
+
       - description: Boards with the Amlogic Meson S4 S905Y4 SoC
         items:
           - enum:
-- 
2.53.0



^ permalink raw reply related

* [PATCH] arm64: smp: Limit nr_cpu_ids under nosmp
From: Pengjie Zhang @ 2026-04-22  9:58 UTC (permalink / raw)
  To: catalin.marinas, will
  Cc: maz, timothy.hayes, lpieralisi, mrigendra.chaubey, arnd,
	linux-arm-kernel, linux-kernel, zhanjie9, zhenglifeng1, lihuisong,
	yubowen8, linhongye, linuxarm, zhangpengjie2, wangzhi12

Under nosmp (maxcpus=0), arm64 never brings up secondary CPUs.

However, arm64 still enumerates firmware-described CPUs during SMP
initialization, so secondary CPUs can remain visible to
for_each_possible_cpu() users even though they never reach the
bringup path in this configuration.

This is not just a cosmetic mask mismatch: code iterating over
possible CPUs may observe secondary CPU per-CPU state that is never
fully initialized under nosmp.

Limit nr_cpu_ids to 1 in arch_disable_smp_support() so that
secondary CPUs are not set up on arm64 when nosmp/maxcpus=0 is in
effect.

Signed-off-by: Pengjie Zhang <zhangpengjie2@huawei.com>
---
 arch/arm64/kernel/smp.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 1aa324104afb..cc34c68871e9 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -435,6 +435,15 @@ static void __init hyp_mode_check(void)
 	}
 }
 
+void __init arch_disable_smp_support(void)
+{
+	/*
+	 * Under nosmp/maxcpus=0, only the boot CPU can ever be brought up.
+	 * Limit nr_cpu_ids so that secondary CPUs are never set up.
+	 */
+	set_nr_cpu_ids(1);
+}
+
 void __init smp_cpus_done(unsigned int max_cpus)
 {
 	pr_info("SMP: Total of %d processors activated.\n", num_online_cpus());
-- 
2.33.0



^ permalink raw reply related

* Re: [PATCH v6 1/2] dma: arm-dma350: enable ANYCH interrupt for shared IRQ wiring
From: Frank Li @ 2026-04-22  9:54 UTC (permalink / raw)
  To: Jun Guo
  Cc: peter.chen, fugang.duan, robh, krzk+dt, conor+dt, vkoul, ychuang3,
	schung, robin.murphy, Frank.Li, dmaengine, devicetree,
	linux-kernel, cix-kernel-upstream, linux-arm-kernel
In-Reply-To: <932db8ad-a9d8-47ff-bf3c-62a54c42bb76@cixtech.com>

On Tue, Apr 21, 2026 at 03:24:11PM +0800, Jun Guo wrote:
> Hi Robin,
>
> Just pinging. I’d like to ask if you have any comments on the latest patch?
>
> On 3/25/2026 7:21 PM, Jun Guo wrote:
> > Enable DMANSECCTRL.INTREN_ANYCHINTR during probe so channel
> > interrupts are propagated when integrators wire DMA-350 channels
> > onto a shared IRQ line.

Your tag is wrong

dmaegine: arm-dma350: enable ANYCH ...

> >
> > Signed-off-by: Jun Guo <jun.guo@cixtech.com>
> > ---
> >   drivers/dma/arm-dma350.c | 9 +++++++++
> >   1 file changed, 9 insertions(+)
> >
> > diff --git a/drivers/dma/arm-dma350.c b/drivers/dma/arm-dma350.c
> > index 84220fa83029..09403aca8bb0 100644
> > --- a/drivers/dma/arm-dma350.c
> > +++ b/drivers/dma/arm-dma350.c
> > @@ -13,6 +13,11 @@
> >   #include "dmaengine.h"
> >   #include "virt-dma.h"

extra empty line between header file and macro


> > +#define DMANSECCTRL		0x200
> > +
> > +#define NSEC_CTRL		0x0c

why need two layer regiser define, your use DMANSECCTRL + NSEC_CTRL,

why not use one macro for 0x20c

Frank

> > +#define INTREN_ANYCHINTR_EN	BIT(0)
> > +
> >   #define DMAINFO			0x0f00
> >   #define DMA_BUILDCFG0		0xb0
> > @@ -582,6 +587,10 @@ static int d350_probe(struct platform_device *pdev)
> >   	dmac->dma.device_issue_pending = d350_issue_pending;
> >   	INIT_LIST_HEAD(&dmac->dma.channels);
> > +	reg = readl_relaxed(base + DMANSECCTRL + NSEC_CTRL);
> > +	writel_relaxed(reg | INTREN_ANYCHINTR_EN,
> > +		       base + DMANSECCTRL + NSEC_CTRL);
> > +
> >   	/* Would be nice to have per-channel caps for this... */
> >   	memset = true;
> >   	for (int i = 0; i < nchan; i++) {
>


^ permalink raw reply


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