* [PATCH 6/8] arm64: dts: amlogic: t7: Add thermal sensor nodes
From: Ronald Claveau @ 2026-04-10 16:48 UTC (permalink / raw)
To: Guillaume La Roque, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl
Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
linux-arm-kernel, Ronald Claveau
In-Reply-To: <20260410-add-thermal-t7-vim4-v1-0-19f2b8da74d7@aliel.fr>
Add six temperature sensor nodes using the amlogic,t7-thermal compatible:
a73, a53, gpu, nna, vpu, and hevc. Each sensor retrieves its calibration
data from the secure monitor via the amlogic,secure-monitor phandle with
the corresponding tsensor_id argument.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 58 +++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index 7aec65f036a9c..62f259b2b17d2 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -656,6 +656,24 @@ sec_ao: ao-secure@10220 {
amlogic,has-chip-id;
};
+ a73_tsensor: temperature-sensor@20000 {
+ compatible = "amlogic,t7-thermal";
+ reg = <0x0 0x20000 0x0 0x50>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc_periphs CLKID_TS>;
+ #thermal-sensor-cells = <0>;
+ amlogic,secure-monitor = <&sm 1>;
+ };
+
+ a53_tsensor: temperature-sensor@22000 {
+ compatible = "amlogic,t7-thermal";
+ reg = <0x0 0x22000 0x0 0x50>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc_periphs CLKID_TS>;
+ #thermal-sensor-cells = <0>;
+ amlogic,secure-monitor = <&sm 2>;
+ };
+
pwm_ao_ef: pwm@30000 {
compatible = "amlogic,t7-pwm", "amlogic,meson-s4-pwm";
reg = <0x0 0x30000 0x0 0x24>;
@@ -770,6 +788,46 @@ sd_emmc_c: mmc@8c000 {
assigned-clock-parents = <&xtal>;
status = "disabled";
};
+
+ gpu_tsensor: temperature-sensor@94000 {
+ compatible = "amlogic,t7-thermal";
+ reg = <0x0 0x94000 0x0 0x50>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc_periphs CLKID_TS>;
+ power-domains = <&pwrc PWRC_T7_MALI_TOP_ID>;
+ #thermal-sensor-cells = <0>;
+ amlogic,secure-monitor = <&sm 3>;
+ };
+
+ nna_tsensor: temperature-sensor@96000 {
+ compatible = "amlogic,t7-thermal";
+ reg = <0x0 0x96000 0x0 0x50>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc_periphs CLKID_TS>;
+ power-domains = <&pwrc PWRC_T7_NNA_TOP_ID>;
+ #thermal-sensor-cells = <0>;
+ amlogic,secure-monitor = <&sm 4>;
+ };
+
+ vpu_tsensor: temperature-sensor@98000 {
+ compatible = "amlogic,t7-thermal";
+ reg = <0x0 0x98000 0x0 0x50>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc_periphs CLKID_TS>;
+ power-domains = <&pwrc PWRC_T7_VPU_HDMI_ID>;
+ #thermal-sensor-cells = <0>;
+ amlogic,secure-monitor = <&sm 6>;
+ };
+
+ hevc_tsensor: temperature-sensor@9a000 {
+ compatible = "amlogic,t7-thermal";
+ reg = <0x0 0x9a000 0x0 0x50>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc_periphs CLKID_TS>;
+ power-domains = <&pwrc PWRC_T7_DOS_HEVC_ID>;
+ #thermal-sensor-cells = <0>;
+ amlogic,secure-monitor = <&sm 5>;
+ };
};
};
--
2.49.0
^ permalink raw reply related
* [PATCH 8/8] arm64: dts: amlogic: t7: khadas-vim4: Add fan cooling to thermal zones
From: Ronald Claveau @ 2026-04-10 16:48 UTC (permalink / raw)
To: Guillaume La Roque, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl
Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
linux-arm-kernel, Ronald Claveau
In-Reply-To: <20260410-add-thermal-t7-vim4-v1-0-19f2b8da74d7@aliel.fr>
Add an active trip at 50°C to all six thermal zones and map it to the
khadas_mcu fan controller, using cooling states 30 to 100.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
.../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 102 +++++++++++++++++++++
1 file changed, 102 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
index 5d7f5390f3a66..ba9219073dd0a 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
@@ -157,6 +157,74 @@ wifi32k: wifi32k {
};
};
+&a53_thermal {
+ trips {
+ a53_active: a53-active {
+ temperature = <50000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map {
+ trip = <&a53_active>;
+ cooling-device = <&khadas_mcu 30 100>;
+ };
+ };
+};
+
+&a73_thermal {
+ trips {
+ a73_active: a73-active {
+ temperature = <50000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map {
+ trip = <&a73_active>;
+ cooling-device = <&khadas_mcu 30 100>;
+ };
+ };
+};
+
+&gpu_thermal {
+ trips {
+ gpu_active: gpu-active {
+ temperature = <50000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map {
+ trip = <&gpu_active>;
+ cooling-device = <&khadas_mcu 30 100>;
+ };
+ };
+};
+
+&hevc_thermal {
+ trips {
+ hevc_active: hevc-active {
+ temperature = <50000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map {
+ trip = <&hevc_active>;
+ cooling-device = <&khadas_mcu 30 100>;
+ };
+ };
+};
+
&i2c_m_ao_a {
status = "okay";
pinctrl-0 = <&i2c0_ao_d_pins>;
@@ -170,6 +238,23 @@ khadas_mcu: system-controller@18 {
};
};
+&nna_thermal {
+ trips {
+ nna_active: nna-active {
+ temperature = <50000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map {
+ trip = <&nna_active>;
+ cooling-device = <&khadas_mcu 30 100>;
+ };
+ };
+};
+
&pwm_ab {
status = "okay";
pinctrl-0 = <&pwm_a_pins>;
@@ -266,3 +351,20 @@ &uart_a {
clocks = <&xtal>, <&xtal>, <&xtal>;
clock-names = "xtal", "pclk", "baud";
};
+
+&vpu_thermal {
+ trips {
+ vpu_active: vpu-active {
+ temperature = <50000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map {
+ trip = <&vpu_active>;
+ cooling-device = <&khadas_mcu 30 100>;
+ };
+ };
+};
--
2.49.0
^ permalink raw reply related
* Re: [PATCH v2 0/6] perf arm_spe: Dump IMPDEF events
From: Namhyung Kim @ 2026-04-10 16:50 UTC (permalink / raw)
To: James Clark
Cc: John Garry, Will Deacon, Mike Leach, Leo Yan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Al Grant, linux-arm-kernel, linux-perf-users, linux-kernel,
Leo Yan
In-Reply-To: <20260407-james-spe-impdef-decode-v2-0-55d3ef997c48@linaro.org>
Hi James,
On Tue, Apr 07, 2026 at 03:05:14PM +0100, James Clark wrote:
> In the Arm SPE raw data dump, IMPDEF events aren't printed. Add the
> ability to add names for some known events or print the raw event number
> for unknown events.
>
> For example:
>
> $ perf report -D
>
> ... ARM SPE data: size 0xd000 bytes
> 00000000: b0 18 c6 32 80 00 80 ff a0 PC 0xff80008032c618 el1 ns=1
> 00000009: 64 e7 42 00 00 CONTEXT 0x42e7 el1
> 0000000e: 00 00 00 00 00 PAD
> 00000013: 49 00 LD GP-REG
> 00000015: 52 16 10 EV RETIRED L1D-ACCESS TLB-ACCESS
>
> On N1 the event line becomes:
>
> 00000015: 52 16 10 EV RETIRED L1D-ACCESS TLB-ACCESS LATE-PREFETCH
>
> Or on other cores it becomes:
>
> 00000015: 52 16 10 EV RETIRED L1D-ACCESS TLB-ACCESS IMPDEF:12
>
> Signed-off-by: James Clark <james.clark@linaro.org>
> ---
> Changes in v2:
> - Put MIDR in arm_spe_pkt (Leo)
> - Use for_each_set_bit() (Leo)
> - Use BIT_ULL() to fix 32bit builds (Ian)
> - Don't call strtol() with NULL (Ian)
> - Link to v1: https://lore.kernel.org/r/20260401-james-spe-impdef-decode-v1-0-ad0d372c220c@linaro.org
I'm getting this on 32-bit build.
In file included from /linux/tools/include/linux/bitmap.h:8,
from util/arm-spe-decoder/arm-spe-pkt-decoder.c:11:
util/arm-spe-decoder/arm-spe-pkt-decoder.c: In function 'arm_spe_pkt_desc_event':
util/arm-spe-decoder/arm-spe-pkt-decoder.c:377:37: error: passing argument 1 of 'find_first_bit' from incompatible pointer type [-Werror=incompatible-pointer-types]
377 | for_each_set_bit(i, &payload, 64) {
/linux/tools/include/linux/bitops.h:55:38: note: in definition of macro 'for_each_set_bit'
55 | for ((bit) = find_first_bit((addr), (size)); \
| ^~~~
In file included from /linux/tools/include/linux/bitmap.h:9:
/linux/tools/include/linux/find.h:118:51: note: expected 'const long unsigned int *' but argument is of type 'u64 *' {aka 'long long unsigned int *'}
118 | unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
| ~~~~~~~~~~~~~~~~~~~~~^~~~
Thanks,
Namhyung
>
> ---
> James Clark (6):
> perf arm_spe: Make a function to get the MIDR
> perf arm_spe: Handle missing CPU IDs
> perf arm_spe: Store MIDR in arm_spe_pkt
> perf arm_spe: Turn event name mappings into an array
> perf arm_spe: Decode Arm N1 IMPDEF events
> perf arm_spe: Print remaining IMPDEF event numbers
>
> tools/perf/util/arm-spe-decoder/Build | 2 +
> tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 17 ++-
> tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 3 +-
> .../util/arm-spe-decoder/arm-spe-pkt-decoder.c | 144 ++++++++++++++-------
> .../util/arm-spe-decoder/arm-spe-pkt-decoder.h | 5 +-
> tools/perf/util/arm-spe.c | 62 ++++++---
> 6 files changed, 158 insertions(+), 75 deletions(-)
> ---
> base-commit: 74e2dbe7be5037a5e5eed6bc1ad562747ac88566
> change-id: 20260331-james-spe-impdef-decode-d944f4fdcff7
>
> Best regards,
> --
> James Clark <james.clark@linaro.org>
>
^ permalink raw reply
* Re: [PATCH 1/1] virt: arm-cca-guest: fix error check for RSI_INCOMPLETE
From: Yeoreum Yun @ 2026-04-10 16:51 UTC (permalink / raw)
To: Sami Mujawar
Cc: linux-arm-kernel, linux-kernel, catalin.marinas, will,
steven.price, suzuki.poulose, gshan, Jagdish Gediya
In-Reply-To: <20260410163636.259443-1-sami.mujawar@arm.com>
Look good to me.
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
On Fri, Apr 10, 2026 at 05:36:36PM +0100, Sami Mujawar wrote:
> The RSI interface can return RSI_INCOMPLETE when a report spans
> multiple granules. This is an expected condition and should not be
> treated as a fatal error.
>
> Currently, arm_cca_report_new() checks for `info.result != RSI_SUCCESS`
> and bails out, which incorrectly flags RSI_INCOMPLETE as a failure.
> Fix the check to only break out on results other than RSI_SUCCESS or
> RSI_INCOMPLETE.
>
> This ensures partial reports are handled correctly and avoids spurious
> -ENXIO errors when generating attestation reports.
>
> Fixes: 7999edc484ca ("virt: arm-cca-guest: TSM_REPORT support for realms")
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> Reported-by: Jagdish Gediya <Jagdish.Gediya@arm.com>
> ---
> drivers/virt/coco/arm-cca-guest/arm-cca-guest.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> index 0c9ea24a200c..66d00b6ceb78 100644
> --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> +++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> @@ -157,7 +157,8 @@ static int arm_cca_report_new(struct tsm_report *report, void *data)
> } while (info.result == RSI_INCOMPLETE &&
> info.offset < RSI_GRANULE_SIZE);
>
> - if (info.result != RSI_SUCCESS) {
> + /* Break out in case of failure */
> + if (info.result != RSI_SUCCESS && info.result != RSI_INCOMPLETE) {
> ret = -ENXIO;
> token_size = 0;
> goto exit_free_granule_page;
> --
> SAMI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
>
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
* Re: [PATCH 4/4] arm64: dts: amlogic: t7: Add clk measure support
From: Ronald Claveau @ 2026-04-10 16:58 UTC (permalink / raw)
To: Jian Hu
Cc: devicetree, linux-amlogic, linux-kernel, linux-arm-kernel,
Neil Armstrong, Jerome Brunet, Kevin Hilman, Michael Turquette,
Martin Blumenstingl, robh+dt, Rob Herring, Krzysztof Kozlowski
In-Reply-To: <20260410100329.3167482-5-jian.hu@amlogic.com>
Hello Jian,
On 4/10/26 12:03 PM, Jian Hu wrote:
> Add the clock measure device to the T7 SoC family.
>
> Signed-off-by: Jian Hu <jian.hu@amlogic.com>
> ---
> arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> index 7fe72c94ed62..cec2ea74850d 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> @@ -701,6 +701,11 @@ pwm_ao_cd: pwm@60000 {
> status = "disabled";
> };
>
> + clock-measurer@48000 {
> + compatible = "amlogic,t7-clk-measure";
> + reg = <0x0 0x48000 0x0 0x1c>;
> + };
> +
Can you please order by reg, it should be between pwm_ao_gh and pwm_ab.
Thank you.
> sd_emmc_a: mmc@88000 {
> compatible = "amlogic,t7-mmc", "amlogic,meson-axg-mmc";
> reg = <0x0 0x88000 0x0 0x800>;
--
Best regards,
Ronald
^ permalink raw reply
* Re: [PATCH] firmware: raspberrypi: Change dependency to ARCH_BCM2835 and COMPILE_TEST
From: Florian Fainelli @ 2026-04-10 17:15 UTC (permalink / raw)
To: Chen-Yu Tsai, Broadcom internal kernel review list
Cc: linux-rpi-kernel, linux-arm-kernel, linux-kernel
In-Reply-To: <20260408081150.1710717-1-wenst@chromium.org>
On 4/8/26 01:11, Chen-Yu Tsai wrote:
> The Raspberry Pi firmware driver has no compile dependencies on the
> BCM2835 mailbox driver. It's just a indirect runtime dependency: the
> driver only works on a Raspberry Pi.
>
> Change the dependency from BCM2835_MBOX to ARCH_BCM2835. Also allow
> compile tests. This allows drivers that have build time dependencies
> on this firmware driver to be compile tested as well.
>
> Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
No objection, however I think this should also have:
default ARCH_BRCM2835
because without the firmware driver there is effectively nothing that
works. See this patch series:
https://lists.infradead.org/pipermail/linux-arm-kernel/2024-May/927679.html
> ---
> drivers/firmware/Kconfig | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index bbd2155d8483..f99d27c1f6a4 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -114,7 +114,7 @@ config ISCSI_IBFT
>
> config RASPBERRYPI_FIRMWARE
> tristate "Raspberry Pi Firmware Driver"
> - depends on BCM2835_MBOX
> + depends on ARCH_BCM2835 || COMPILE_TEST
> help
> This option enables support for communicating with the firmware on the
> Raspberry Pi.
--
Florian
^ permalink raw reply
* [PATCH v5 0/4] arm64: Add HPE GSC platform support
From: nick.hawkins @ 2026-04-10 17:16 UTC (permalink / raw)
To: catalin.marinas, will
Cc: robh, krzk+dt, conor+dt, krzysztof.kozlowski, devicetree,
linux-arm-kernel, linux-kernel, Nick Hawkins
From: Nick Hawkins <nick.hawkins@hpe.com>
Add initial platform support for the HPE GSC ARM64 BMC SoC.
Changes since v4:
- All patches: Removed duplicate From: field in commit message body
Changes since v3:
- Patch 1: Moved GSC entry before GXP in hpe,gxp.yaml to maintain
alphabetical ordering by fallback compatible (Krzysztof Kozlowski)
- Patch 2: Added Reviewed-by from Krzysztof Kozlowski
- Patch 3: Changed SPDX in gsc-dl340gen12.dts from GPL-2.0-only to
GPL-2.0 to be consistent with gsc.dtsi (Krzysztof Kozlowski);
reordered nodes within soc by ascending unit-address, placing UARTs
before GIC per DTS coding style (Krzysztof Kozlowski);
moved interrupt-parent before interrupts in timer and all UART nodes
per DTS coding style (Krzysztof Kozlowski);
reordered root-level nodes alphabetically: clock-33333333 before cpus
before timer per DTS coding style (Krzysztof Kozlowski);
reordered properties within all nodes to follow DTS coding style:
compatible, reg first, then remaining alphabetically (Krzysztof
Kozlowski)
- Patch 4: New patch adding CONFIG_ARCH_HPE=y to arm64 defconfig
(Krzysztof Kozlowski)
Changes since v2:
- Patch 1: Removed separate ARM64/HPE GSC MAINTAINERS entry; instead
renamed existing ARM/HPE GXP to ARM/HPE GXP/GSC and added arm64 DTS
path there (Conor Dooley)
- Patch 2: Replaced menuconfig ARCH_HPE + nested ARCH_HPE_GSC with a
single config ARCH_HPE; removed extra blank line (Krzysztof Kozlowski)
- Patch 3: Dropped clocks wrapper node, renamed fixed clock to
clock-33333333; renamed ahb bus node to soc; reordered UART nodes by
address for DTS coding style; replaced raw interrupt triplets with
GIC_SPI/IRQ_TYPE_LEVEL_HIGH defines (Krzysztof Kozlowski)
Nick Hawkins (4):
dt-bindings: arm: hpe,gxp: Add HPE GSC platform compatible
arm64: Kconfig: Add ARCH_HPE platform
arm64: dts: hpe: Add HPE GSC SoC and DL340 Gen12 board DTS
arm64: defconfig: Enable ARCH_HPE
.../devicetree/bindings/arm/hpe,gxp.yaml | 7 +-
MAINTAINERS | 3 +-
arch/arm64/Kconfig.platforms | 11 ++
arch/arm64/boot/dts/hpe/Makefile | 2 +
arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts | 18 +++
arch/arm64/boot/dts/hpe/gsc.dtsi | 104 ++++++++++++++++++
arch/arm64/configs/defconfig | 1 +
7 files changed, 144 insertions(+), 2 deletions(-)
create mode 100644 arch/arm64/boot/dts/hpe/Makefile
create mode 100644 arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
create mode 100644 arch/arm64/boot/dts/hpe/gsc.dtsi
--
2.34.1
^ permalink raw reply
* [PATCH v5 1/4] dt-bindings: arm: hpe,gxp: Add HPE GSC platform compatible
From: nick.hawkins @ 2026-04-10 17:16 UTC (permalink / raw)
To: catalin.marinas, will
Cc: robh, krzk+dt, conor+dt, krzysztof.kozlowski, devicetree,
linux-arm-kernel, linux-kernel, Nick Hawkins
In-Reply-To: <20260410171611.2547255-1-nick.hawkins@hpe.com>
From: Nick Hawkins <nick.hawkins@hpe.com>
Add the HPE GSC ARM64 BMC SoC compatibles to the existing
hpe,gxp.yaml binding.
The initial board compatible is hpe,gsc-dl340gen12 for the DL340 Gen12
server platform.
Add the arm64 DTS path to the existing ARM/HPE GXP MAINTAINERS entry,
renamed to ARM/HPE GXP/GSC ARCHITECTURE.
Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
Documentation/devicetree/bindings/arm/hpe,gxp.yaml | 7 ++++++-
MAINTAINERS | 3 ++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/hpe,gxp.yaml b/Documentation/devicetree/bindings/arm/hpe,gxp.yaml
index 224bbcb93f95..6f057cd58571 100644
--- a/Documentation/devicetree/bindings/arm/hpe,gxp.yaml
+++ b/Documentation/devicetree/bindings/arm/hpe,gxp.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/arm/hpe,gxp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: HPE BMC GXP platforms
+title: HPE BMC GXP and GSC platforms
maintainers:
- Nick Hawkins <nick.hawkins@hpe.com>
@@ -15,6 +15,11 @@ properties:
oneOf:
+ - description: GSC Based Boards
+ items:
+ - enum:
+ - hpe,gsc-dl340gen12
+ - const: hpe,gsc
- description: GXP Based Boards
items:
- enum:
- hpe,gxp-dl360gen10
- const: hpe,gxp
required:
- compatible
diff --git a/MAINTAINERS b/MAINTAINERS
index 2265e2c9bfbe..80c66de5e342 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2859,7 +2859,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
F: arch/arm/mach-sa1100/include/mach/jornada720.h
F: arch/arm/mach-sa1100/jornada720.c
-ARM/HPE GXP ARCHITECTURE
+ARM/HPE GXP/GSC ARCHITECTURE
M: Jean-Marie Verdun <verdun@hpe.com>
M: Nick Hawkins <nick.hawkins@hpe.com>
S: Maintained
@@ -2870,6 +2870,7 @@ F: Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml
F: Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
F: Documentation/hwmon/gxp-fan-ctrl.rst
F: arch/arm/boot/dts/hpe/
+F: arch/arm64/boot/dts/hpe/
F: drivers/clocksource/timer-gxp.c
F: drivers/hwmon/gxp-fan-ctrl.c
F: drivers/i2c/busses/i2c-gxp.c
--
2.34.1
^ permalink raw reply related
* [PATCH v5 2/4] arm64: Kconfig: Add ARCH_HPE platform
From: nick.hawkins @ 2026-04-10 17:16 UTC (permalink / raw)
To: catalin.marinas, will
Cc: robh, krzk+dt, conor+dt, krzysztof.kozlowski, devicetree,
linux-arm-kernel, linux-kernel, Nick Hawkins
In-Reply-To: <20260410171611.2547255-1-nick.hawkins@hpe.com>
From: Nick Hawkins <nick.hawkins@hpe.com>
Add the ARCH_HPE config for HPE ARM64 BMC SoCs to Kconfig.platforms.
Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
arch/arm64/Kconfig.platforms | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 54eb1d7fd419..b4217809c774 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -168,6 +168,17 @@ config ARCH_HISI
help
This enables support for Hisilicon ARMv8 SoC family
+config ARCH_HPE
+ bool "HPE SoC Support"
+ select PINCTRL
+ select GENERIC_IRQ_CHIP
+ select CLKSRC_MMIO
+ help
+ This enables support for HPE ARM-based SoC chips used
+ on HPE servers. HPE SoCs serve as the Baseboard
+ Management Controller (BMC) providing out-of-band server
+ management.
+
config ARCH_KEEMBAY
bool "Keem Bay SoC"
help
--
2.34.1
^ permalink raw reply related
* [PATCH v5 3/4] arm64: dts: hpe: Add HPE GSC SoC and DL340 Gen12 board DTS
From: nick.hawkins @ 2026-04-10 17:16 UTC (permalink / raw)
To: catalin.marinas, will
Cc: robh, krzk+dt, conor+dt, krzysztof.kozlowski, devicetree,
linux-arm-kernel, linux-kernel, Nick Hawkins
In-Reply-To: <20260410171611.2547255-1-nick.hawkins@hpe.com>
From: Nick Hawkins <nick.hawkins@hpe.com>
Add SoC-level DTSI for the HPE GSC ARM64 BMC SoC, covering the CPU
cluster, GIC v3 interrupt controller, ARM64 generic timer, and console
UART.
Add the board-level DTS for the HPE DL340 Gen12, which includes
gsc.dtsi and adds memory and chosen nodes.
Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
---
arch/arm64/boot/dts/hpe/Makefile | 2 +
arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts | 18 ++++
arch/arm64/boot/dts/hpe/gsc.dtsi | 104 +++++++++++++++++++++
3 files changed, 124 insertions(+)
create mode 100644 arch/arm64/boot/dts/hpe/Makefile
create mode 100644 arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
create mode 100644 arch/arm64/boot/dts/hpe/gsc.dtsi
diff --git a/arch/arm64/boot/dts/hpe/Makefile b/arch/arm64/boot/dts/hpe/Makefile
new file mode 100644
index 000000000000..6b547b8a8154
--- /dev/null
+++ b/arch/arm64/boot/dts/hpe/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+dtb-$(CONFIG_ARCH_HPE) += gsc-dl340gen12.dtb
diff --git a/arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts b/arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
new file mode 100644
index 000000000000..7a3d9f1c4b2e
--- /dev/null
+++ b/arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include "gsc.dtsi"
+
+/ {
+ compatible = "hpe,gsc-dl340gen12", "hpe,gsc";
+ model = "HPE ProLiant DL340 Gen12";
+
+ chosen {
+ stdout-path = &uartc;
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x40000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/hpe/gsc.dtsi b/arch/arm64/boot/dts/hpe/gsc.dtsi
new file mode 100644
index 000000000000..1f4c2a7b3d91
--- /dev/null
+++ b/arch/arm64/boot/dts/hpe/gsc.dtsi
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for HPE GSC
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ osc: clock-33333333 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "osc";
+ clock-frequency = <33333333>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0xa0008048>;
+ };
+
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <1>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0xa0008048>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ soc: soc@80000000 {
+ compatible = "simple-bus";
+ reg = <0x80000000 0x80000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ uarta: serial@c00000e0 {
+ compatible = "ns16550a";
+ reg = <0xc00000e0 0x8>;
+ clock-frequency = <1846153>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <0>;
+ };
+
+ uartb: serial@c00000e8 {
+ compatible = "ns16550a";
+ reg = <0xc00000e8 0x8>;
+ clock-frequency = <1846153>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <0>;
+ };
+
+ uartc: serial@c00000f0 {
+ compatible = "ns16550a";
+ reg = <0xc00000f0 0x8>;
+ clock-frequency = <1846153>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <0>;
+ };
+
+ uarte: serial@c00003e0 {
+ compatible = "ns16550a";
+ reg = <0xc00003e0 0x8>;
+ clock-frequency = <1846153>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <0>;
+ };
+
+ gic: gic@ce000000 {
+ compatible = "arm,gic-v3";
+ reg = <0xce000000 0x10000>,
+ <0xce060000 0x40000>,
+ <0xce200000 0x40000>;
+ #address-cells = <0>;
+ #interrupt-cells = <3>;
+ #redistributor-regions = <1>;
+ interrupt-controller;
+ redistributor-stride = <0x0 0x20000>;
+ };
+ };
+};
--
2.34.1
^ permalink raw reply related
* [PATCH v5 4/4] arm64: defconfig: Enable ARCH_HPE
From: nick.hawkins @ 2026-04-10 17:16 UTC (permalink / raw)
To: catalin.marinas, will
Cc: robh, krzk+dt, conor+dt, krzysztof.kozlowski, devicetree,
linux-arm-kernel, linux-kernel, Nick Hawkins
In-Reply-To: <20260410171611.2547255-1-nick.hawkins@hpe.com>
From: Nick Hawkins <nick.hawkins@hpe.com>
Enable ARCH_HPE in the arm64 defconfig to include HPE GSC BMC SoC
support in the default build.
Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index xxxxxxxxxxxxxxx..xxxxxxxxxxxxxxx 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -xx,6 +xx,7 @@
CONFIG_ARCH_HISI=y
+CONFIG_ARCH_HPE=y
CONFIG_ARCH_KEEMBAY=y
--
2.34.1
^ permalink raw reply
* Re: [PATCH 1/1] virt: arm-cca-guest: fix error check for RSI_INCOMPLETE
From: Suzuki K Poulose @ 2026-04-10 17:29 UTC (permalink / raw)
To: Sami Mujawar, linux-arm-kernel, linux-kernel
Cc: catalin.marinas, will, steven.price, gshan, YeoReum.Yun,
Jagdish Gediya
In-Reply-To: <20260410163636.259443-1-sami.mujawar@arm.com>
On 10/04/2026 17:36, Sami Mujawar wrote:
> The RSI interface can return RSI_INCOMPLETE when a report spans
> multiple granules. This is an expected condition and should not be
> treated as a fatal error.
>
> Currently, arm_cca_report_new() checks for `info.result != RSI_SUCCESS`
> and bails out, which incorrectly flags RSI_INCOMPLETE as a failure.
> Fix the check to only break out on results other than RSI_SUCCESS or
> RSI_INCOMPLETE.
>
> This ensures partial reports are handled correctly and avoids spurious
> -ENXIO errors when generating attestation reports.
>
> Fixes: 7999edc484ca ("virt: arm-cca-guest: TSM_REPORT support for realms")
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> Reported-by: Jagdish Gediya <Jagdish.Gediya@arm.com>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
> drivers/virt/coco/arm-cca-guest/arm-cca-guest.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> index 0c9ea24a200c..66d00b6ceb78 100644
> --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> +++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> @@ -157,7 +157,8 @@ static int arm_cca_report_new(struct tsm_report *report, void *data)
> } while (info.result == RSI_INCOMPLETE &&
> info.offset < RSI_GRANULE_SIZE);
>
> - if (info.result != RSI_SUCCESS) {
> + /* Break out in case of failure */
> + if (info.result != RSI_SUCCESS && info.result != RSI_INCOMPLETE) {
> ret = -ENXIO;
> token_size = 0;
> goto exit_free_granule_page;
^ permalink raw reply
* Re: [PATCH v2 2/3] pwm: rp1: Add RP1 PWM controller driver
From: Uwe Kleine-König @ 2026-04-10 17:31 UTC (permalink / raw)
To: Andrea della Porta
Cc: linux-pwm, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Florian Fainelli, Broadcom internal kernel review list,
devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
Naushir Patuck, Stanimir Varbanov, mbrugger
In-Reply-To: <0d99317b9150310dfbd98de1cb2a890f0bffe7cd.1775829499.git.andrea.porta@suse.com>
[-- Attachment #1: Type: text/plain, Size: 14571 bytes --]
Hello Andrea,
nice work for a v2!
On Fri, Apr 10, 2026 at 04:09:58PM +0200, Andrea della Porta wrote:
> From: Naushir Patuck <naush@raspberrypi.com>
>
> The Raspberry Pi RP1 southbridge features an embedded PWM
> controller with 4 output channels, alongside an RPM interface
> to read the fan speed on the Raspberry Pi 5.
>
> Add the supporting driver.
>
> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
> Co-developed-by: Stanimir Varbanov <svarbanov@suse.de>
> Signed-off-by: Stanimir Varbanov <svarbanov@suse.de>
> Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
> ---
> drivers/pwm/Kconfig | 9 ++
> drivers/pwm/Makefile | 1 +
> drivers/pwm/pwm-rp1.c | 344 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 354 insertions(+)
> create mode 100644 drivers/pwm/pwm-rp1.c
>
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index 6f3147518376a..32031f2af75af 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -625,6 +625,15 @@ config PWM_ROCKCHIP
> Generic PWM framework driver for the PWM controller found on
> Rockchip SoCs.
>
> +config PWM_RASPBERRYPI_RP1
> + bool "RP1 PWM support"
> + depends on MISC_RP1 || COMPILE_TEST
> + depends on HAS_IOMEM
> + select REGMAP_MMIO
> + select MFD_SYSCON
> + help
> + PWM framework driver for Raspberry Pi RP1 controller.
> +
> config PWM_SAMSUNG
> tristate "Samsung PWM support"
> depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index 0dc0d2b69025d..59f29f60f9123 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_PWM_RENESAS_RZG2L_GPT) += pwm-rzg2l-gpt.o
> obj-$(CONFIG_PWM_RENESAS_RZ_MTU3) += pwm-rz-mtu3.o
> obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o
> obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
> +obj-$(CONFIG_PWM_RASPBERRYPI_RP1) += pwm-rp1.o
> obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
> obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o
> obj-$(CONFIG_PWM_SL28CPLD) += pwm-sl28cpld.o
> diff --git a/drivers/pwm/pwm-rp1.c b/drivers/pwm/pwm-rp1.c
> new file mode 100644
> index 0000000000000..b88c697d9567e
> --- /dev/null
> +++ b/drivers/pwm/pwm-rp1.c
> @@ -0,0 +1,344 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * pwm-rp1.c
> + *
> + * Raspberry Pi RP1 PWM.
> + *
> + * Copyright © 2026 Raspberry Pi Ltd.
> + *
> + * Author: Naushir Patuck (naush@raspberrypi.com)
> + *
> + * Based on the pwm-bcm2835 driver by:
> + * Bart Tanghe <bart.tanghe@thomasmore.be>
> + *
> + * Datasheet: https://pip-assets.raspberrypi.com/categories/892-raspberry-pi-5/documents/RP-008370-DS-1-rp1-peripherals.pdf?disposition=inline
> + *
> + * Limitations:
> + * - Channels can be enabled/disabled and their duty cycle and period can
> + * be updated glitchlessly. Update are synchronized with the next strobe
> + * at the end of the current period of the respective channel, once the
> + * update bit is set. The update flag is global, not per-channel.
> + * - Channels are phase-capable, but on RPi5, the firmware can use a channel
> + * phase register to report the RPM of the fan connected to that PWM
> + * channel. As a result, phase control will be ignored for now.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +
> +#define RP1_PWM_GLOBAL_CTRL 0x000
> +#define RP1_PWM_CHANNEL_CTRL(x) (0x014 + ((x) * 0x10))
> +#define RP1_PWM_RANGE(x) (0x018 + ((x) * 0x10))
> +#define RP1_PWM_PHASE(x) (0x01C + ((x) * 0x10))
> +#define RP1_PWM_DUTY(x) (0x020 + ((x) * 0x10))
> +
> +/* 8:FIFO_POP_MASK + 0:Trailing edge M/S modulation */
> +#define RP1_PWM_CHANNEL_DEFAULT (BIT(8) + BIT(0))
Please add a #define for BIT(8) and then use that and
FIELD_PREP(RP1_PWM_MODE, RP1_PWM_MODE_SOMENICENAME) to define the
constant. Also I would define it below the register defines.
> +#define RP1_PWM_CHANNEL_ENABLE(x) BIT(x)
> +#define RP1_PWM_POLARITY BIT(3)
> +#define RP1_PWM_SET_UPDATE BIT(31)
> +#define RP1_PWM_MODE_MASK GENMASK(1, 0)
s/_MASK// please
It would be great if the bitfield's names started with the register
name.
> +
> +#define RP1_PWM_NUM_PWMS 4
> +
> +struct rp1_pwm {
> + struct regmap *regmap;
> + struct clk *clk;
> + unsigned long clk_rate;
> + bool clk_enabled;
> +};
> +
> +struct rp1_pwm_waveform {
> + u32 period_ticks;
> + u32 duty_ticks;
> + bool enabled;
> + bool inverted_polarity;
> +};
> +
> +static const struct regmap_config rp1_pwm_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x60,
I'm not a fan of aligning the = in a struct, still more if it fails like
here. Please consistently align all =s, or even better, use a single
space before each =. (Same for the struct definitions above, but I won't
insist.)
> +};
> +
> +static void rp1_pwm_apply_config(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> + struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> + u32 value;
> +
> + /* update the changed registers on the next strobe to avoid glitches */
> + regmap_read(rp1->regmap, RP1_PWM_GLOBAL_CTRL, &value);
> + value |= RP1_PWM_SET_UPDATE;
> + regmap_write(rp1->regmap, RP1_PWM_GLOBAL_CTRL, value);
I assume there is a glitch if I update two channels and the old
configuration of the first channel ends while I'm in the middle of
configuring the second?
> +}
> +
> +static int rp1_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> + struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> +
> + /* init channel to reset defaults */
> + regmap_write(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), RP1_PWM_CHANNEL_DEFAULT);
> + return 0;
> +}
> +
> +static int rp1_pwm_round_waveform_tohw(struct pwm_chip *chip,
> + struct pwm_device *pwm,
> + const struct pwm_waveform *wf,
> + void *_wfhw)
> +{
> + struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> + struct rp1_pwm_waveform *wfhw = _wfhw;
> + u64 clk_rate = rp1->clk_rate;
> + u64 ticks;
if (!wf->period_length_ns)
wfhw->enabled = false
return 0;
> + ticks = mul_u64_u64_div_u64(wf->period_length_ns, clk_rate, NSEC_PER_SEC);
To ensure this doesn't overflow please fail to probe the driver if
clk_rate > 1 GHz with an explaining comment. (Or alternatively calculate
the length of period_ticks = U32_MAX and skip the calculation if
wf->period_length_ns is bigger.)
> + if (ticks > U32_MAX)
> + ticks = U32_MAX;
> + wfhw->period_ticks = ticks;
What happens if wf->period_length_ns > 0 but ticks == 0?
> + if (wf->duty_offset_ns + wf->duty_length_ns >= wf->period_length_ns) {
The maybe surprising effect here is that in the two cases
wf->duty_offset_ns == wf->period_length_ns and wf->duty_length_ns == 0
and
wf->duty_length_ns == wf->period_length_ns and wf->duty_offset_ns == 0
you're configuring inverted polarity. I doesn't matter technically
because the result is the same, but for consumers still using pwm_state
this is irritating. That's why pwm-stm32 uses inverted polarity only if
also wf->duty_length_ns and wf->duty_offset_ns are non-zero.
> + ticks = mul_u64_u64_div_u64(wf->period_length_ns - wf->duty_length_ns,
> + clk_rate, NSEC_PER_SEC);
The rounding is wrong here. You should pick the biggest duty_length not
bigger than wf->duty_length_ns, so you have to use
ticks = wfhw->period_ticks - mul_u64_u64_div_u64(wf->duty_length_ns, clk_rate, NSEC_PER_SEC):
. I see this is a hole in the pwmtestperf coverage.
> + wfhw->inverted_polarity = true;
> + } else {
> + ticks = mul_u64_u64_div_u64(wf->duty_length_ns, clk_rate, NSEC_PER_SEC);
> + wfhw->inverted_polarity = false;
> + }
> +
> + if (ticks > wfhw->period_ticks)
> + ticks = wfhw->period_ticks;
You can and should assume that wf->duty_length_ns <=
wf->period_length_ns. Then the if condition can never become true.
> + wfhw->duty_ticks = ticks;
> +
> + wfhw->enabled = !!wfhw->duty_ticks;
> +
> + return 0;
> +}
> +
> +static int rp1_pwm_round_waveform_fromhw(struct pwm_chip *chip,
> + struct pwm_device *pwm,
> + const void *_wfhw,
> + struct pwm_waveform *wf)
> +{
> + struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> + const struct rp1_pwm_waveform *wfhw = _wfhw;
> + u64 clk_rate = rp1->clk_rate;
> + u32 ticks;
> +
> + memset(wf, 0, sizeof(*wf));
wf = (struct pwm_waveform){ };
is usually more efficient.
> + if (!wfhw->enabled)
> + return 0;
> +
> + wf->period_length_ns = DIV_ROUND_UP_ULL((u64)wfhw->period_ticks * NSEC_PER_SEC, clk_rate);
> +
> + if (wfhw->inverted_polarity) {
> + wf->duty_length_ns = DIV_ROUND_UP_ULL((u64)wfhw->duty_ticks * NSEC_PER_SEC,
> + clk_rate);
> + } else {
> + wf->duty_offset_ns = DIV_ROUND_UP_ULL((u64)wfhw->duty_ticks * NSEC_PER_SEC,
> + clk_rate);
> + ticks = wfhw->period_ticks - wfhw->duty_ticks;
> + wf->duty_length_ns = DIV_ROUND_UP_ULL((u64)ticks * NSEC_PER_SEC, clk_rate);
> + }
This needs adaption after the rounding issue in tohw is fixed.
> + return 0;
> +}
> +
> +static int rp1_pwm_write_waveform(struct pwm_chip *chip,
> + struct pwm_device *pwm,
> + const void *_wfhw)
> +{
> + struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> + const struct rp1_pwm_waveform *wfhw = _wfhw;
> + u32 value;
> +
> + /* set period and duty cycle */
> + regmap_write(rp1->regmap,
> + RP1_PWM_RANGE(pwm->hwpwm), wfhw->period_ticks);
> + regmap_write(rp1->regmap,
> + RP1_PWM_DUTY(pwm->hwpwm), wfhw->duty_ticks);
> +
> + /* set polarity */
> + regmap_read(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), &value);
> + if (!wfhw->inverted_polarity)
> + value &= ~RP1_PWM_POLARITY;
> + else
> + value |= RP1_PWM_POLARITY;
> + regmap_write(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), value);
> +
> + /* enable/disable */
> + regmap_read(rp1->regmap, RP1_PWM_GLOBAL_CTRL, &value);
> + if (wfhw->enabled)
> + value |= RP1_PWM_CHANNEL_ENABLE(pwm->hwpwm);
> + else
> + value &= ~RP1_PWM_CHANNEL_ENABLE(pwm->hwpwm);
> + regmap_write(rp1->regmap, RP1_PWM_GLOBAL_CTRL, value);
You can exit early if wfhw->enabled is false after clearing the channel
enable bit.
> + rp1_pwm_apply_config(chip, pwm);
> +
> + return 0;
> +}
> +
> +static int rp1_pwm_read_waveform(struct pwm_chip *chip,
> + struct pwm_device *pwm,
> + void *_wfhw)
> +{
> + struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> + struct rp1_pwm_waveform *wfhw = _wfhw;
> + u32 value;
> +
> + regmap_read(rp1->regmap, RP1_PWM_GLOBAL_CTRL, &value);
> + wfhw->enabled = !!(value & RP1_PWM_CHANNEL_ENABLE(pwm->hwpwm));
> +
> + regmap_read(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), &value);
> + wfhw->inverted_polarity = !!(value & RP1_PWM_POLARITY);
> +
> + if (wfhw->enabled) {
> + regmap_read(rp1->regmap, RP1_PWM_RANGE(pwm->hwpwm), &wfhw->period_ticks);
> + regmap_read(rp1->regmap, RP1_PWM_DUTY(pwm->hwpwm), &wfhw->duty_ticks);
> + } else {
> + wfhw->period_ticks = 0;
> + wfhw->duty_ticks = 0;
> + }
> +
> + return 0;
> +}
> +
> +static const struct pwm_ops rp1_pwm_ops = {
> + .sizeof_wfhw = sizeof(struct rp1_pwm_waveform),
> + .request = rp1_pwm_request,
> + .round_waveform_tohw = rp1_pwm_round_waveform_tohw,
> + .round_waveform_fromhw = rp1_pwm_round_waveform_fromhw,
> + .read_waveform = rp1_pwm_read_waveform,
> + .write_waveform = rp1_pwm_write_waveform,
> +};
> +
> +static int rp1_pwm_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + unsigned long clk_rate;
> + struct pwm_chip *chip;
> + void __iomem *base;
> + struct rp1_pwm *rp1;
> + int ret;
> +
> + chip = devm_pwmchip_alloc(dev, RP1_PWM_NUM_PWMS, sizeof(*rp1));
> + if (IS_ERR(chip))
> + return PTR_ERR(chip);
> +
> + rp1 = pwmchip_get_drvdata(chip);
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + rp1->regmap = devm_regmap_init_mmio(dev, base, &rp1_pwm_regmap_config);
> + if (IS_ERR(rp1->regmap))
> + return dev_err_probe(dev, PTR_ERR(rp1->regmap), "Cannot initialize regmap\n");
> +
> + ret = of_syscon_register_regmap(np, rp1->regmap);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to register syscon\n");
> +
> + rp1->clk = devm_clk_get(dev, NULL);
> + if (IS_ERR(rp1->clk))
> + return dev_err_probe(dev, PTR_ERR(rp1->clk), "Clock not found\n");
> +
> + ret = clk_prepare_enable(rp1->clk);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to enable clock\n");
> + rp1->clk_enabled = true;
> +
> + ret = devm_clk_rate_exclusive_get(dev, rp1->clk);
> + if (ret) {
> + dev_err_probe(dev, ret, "Fail to get exclusive rate\n");
s/Fail/Failed/
> + goto err_disable_clk;
> + }
> +
> + clk_rate = clk_get_rate(rp1->clk);
> + if (!clk_rate) {
> + ret = dev_err_probe(dev, -EINVAL, "Failed to get clock rate\n");
> + goto err_disable_clk;
> + }
> + rp1->clk_rate = clk_rate;
> +
> + chip->ops = &rp1_pwm_ops;
> +
> + platform_set_drvdata(pdev, chip);
> +
> + ret = devm_pwmchip_add(dev, chip);
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to register PWM chip\n");
> + goto err_disable_clk;
> + }
> +
> + return 0;
> +
> +err_disable_clk:
> + clk_disable_unprepare(rp1->clk);
> +
> + return ret;
> +}
On remove you miss to balance the call to clk_prepare_enable() (if no
failed call to clk_prepare_enable() in rp1_pwm_resume() happend).
> +
> +static int rp1_pwm_suspend(struct device *dev)
> +{
> + struct rp1_pwm *rp1 = dev_get_drvdata(dev);
> +
> + if (rp1->clk_enabled) {
> + clk_disable_unprepare(rp1->clk);
> + rp1->clk_enabled = false;
> + }
> +
> + return 0;
> +}
> +
> +static int rp1_pwm_resume(struct device *dev)
> +{
> + struct rp1_pwm *rp1 = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = clk_prepare_enable(rp1->clk);
> + if (ret) {
> + dev_err(dev, "Failed to enable clock on resume: %d\n", ret);
Please use %pe for error codes.
> + return ret;
> + }
> +
> + rp1->clk_enabled = true;
> +
> + return 0;
> +}
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* ✅ PASS (MISSED 51 of 56): Test report for for-kernelci (7.0.0-rc7, upstream-arm-next, 5988aa32)
From: cki-project @ 2026-04-10 18:13 UTC (permalink / raw)
To: catalin.marinas, will, linux-arm-kernel
Hi, we tested your kernel and here are the results:
Overall result: PASSED
Merge: OK
Compile: OK
Test: OK
Tested-by: CKI Project <cki-project@redhat.com>
Kernel information:
Commit message: Merge branch 'for-next/c1-pro-erratum-4193714' into for-kernelci
You can find all the details about the test run at
https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:2444539166
Tests that were not ran because of internal issues:
/distribution/check-install [aarch64]
/distribution/command [aarch64]
/test/misc/machineinfo [aarch64]
Boot test [aarch64]
CKI/restraint [aarch64]
Hardware - Firmware test suite [aarch64]
Reboot test [aarch64]
SELinux Custom Module Setup [aarch64]
selinux-policy: serge-testsuite [aarch64]
Storage - blktests - throtl [aarch64]
Storage - blktests - ublk [aarch64]
stress: stress-ng - cpu-cache [aarch64]
stress: stress-ng - memory [aarch64]
xfstests - btrfs [aarch64]
xfstests - ext4 [aarch64]
xfstests - xfs [aarch64]
If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.
Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.
,-. ,-.
( C ) ( K ) Continuous
`-',-.`-' Kernel
( I ) Integration
`-'
______________________________________________________________________________
^ permalink raw reply
* Re: [PATCH v2 2/4] perf: Fix uninitialized bitfields in perf_clear_branch_entry_bitfields()
From: Rob Herring @ 2026-04-10 18:17 UTC (permalink / raw)
To: Leo Yan
Cc: Puranjay Mohan, bpf, Puranjay Mohan, Alexei Starovoitov,
Andrii Nakryiko, Daniel Borkmann, Martin KaFai Lau,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Will Deacon,
Mark Rutland, Catalin Marinas, Breno Leitao, linux-arm-kernel,
linux-perf-users, kernel-team
In-Reply-To: <20260409162826.GX356832@e132581.arm.com>
On Thu, Apr 09, 2026 at 05:28:26PM +0100, Leo Yan wrote:
> On Wed, Mar 18, 2026 at 10:16:56AM -0700, Puranjay Mohan wrote:
>
> [...]
>
> > diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> > index 48d851fbd8ea..d7f39b7e9cda 100644
> > --- a/include/linux/perf_event.h
> > +++ b/include/linux/perf_event.h
>
> BTW, I found you didn't include correct maintainers for perf core
> changes. You might need to loop them in the new version.
Yes. And use get_maintainers.pl please. b4 tool will do that for you.
That will get everyone including authors of commits in "Fixes". That
would be Marc Z in this case.
Rob
^ permalink raw reply
* [PATCH] arm: Kconfig: fix duplicate words in help text
From: Michael Ugrin @ 2026-04-10 18:22 UTC (permalink / raw)
To: linux-arm-kernel; +Cc: linux-kernel, Michael Ugrin
Remove two instances of duplicate 'the'.
Signed-off-by: Michael Ugrin <mugrinphoto@gmail.com>
---
arch/arm/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ec33376f8e2ba..e62af2a34f59f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1486,7 +1486,7 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND
bool "Extend with bootloader kernel arguments"
help
The command-line arguments provided by the boot loader will be
- appended to the the device tree bootargs property.
+ appended to the device tree bootargs property.
endchoice
@@ -1628,7 +1628,7 @@ config DMI
continue to boot on existing non-UEFI platforms.
NOTE: This does *NOT* enable or encourage the use of DMI quirks,
- i.e., the the practice of identifying the platform via DMI to
+ i.e., the practice of identifying the platform via DMI to
decide whether certain workarounds for buggy hardware and/or
firmware need to be enabled. This would require the DMI subsystem
to be enabled much earlier than we do on ARM, which is non-trivial.
--
2.51.2.windows.1
^ permalink raw reply related
* Re: [PATCH v5 0/4] arm64: Work around C1-Pro erratum 4193714 (CVE-2026-0995)
From: Catalin Marinas @ 2026-04-10 18:47 UTC (permalink / raw)
To: linux-arm-kernel; +Cc: Will Deacon, James Morse, Mark Rutland, Mark Brown
In-Reply-To: <20260407102848.2266988-1-catalin.marinas@arm.com>
On Tue, 07 Apr 2026 11:28:40 +0100, Catalin Marinas wrote:
> That's version 5 of the C1-Pro workaround. Version 3 here:
>
> https://lore.kernel.org/r/20260402101246.3870036-1-catalin.marinas@arm.com
>
> Changes since v4:
>
> - Static sme_dvmsync_cpus mask to avoid allocating under stop_machine().
> Sashiko was right, even GFP_ATOMIC won't work under a raw_spin_lock()
>
> [...]
Applied to arm64 (for-next/c1-pro-erratum-4193714). I won't push it to
Linus in the first round, waiting for a bit more testing from Will. If
all goes well, I'll send it in the second part of the merging window.
[1/4] arm64: tlb: Introduce __tlbi_sync_s1ish_{kernel,batch}() for TLB maintenance
https://git.kernel.org/arm64/c/6bfbf574a391
[2/4] arm64: tlb: Pass the corresponding mm to __tlbi_sync_s1ish()
https://git.kernel.org/arm64/c/d9fb08ba946a
[3/4] arm64: cputype: Add C1-Pro definitions
https://git.kernel.org/arm64/c/2c99561016c5
[4/4] arm64: errata: Work around early CME DVMSync acknowledgement
https://git.kernel.org/arm64/c/0baba94a9779
^ permalink raw reply
* Re: [PATCH v4 03/10] iommu/arm-smmu-v3: Store IOTLB cache tags in struct arm_smmu_attach_state
From: Nicolin Chen @ 2026-04-10 18:52 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: will, robin.murphy, joro, jpb, praan, smostafa, linux-arm-kernel,
iommu, linux-kernel, linux-tegra, jonathan.cameron
In-Reply-To: <20260409234223.GX3357077@nvidia.com>
On Thu, Apr 09, 2026 at 08:42:23PM -0300, Jason Gunthorpe wrote:
> On Thu, Mar 19, 2026 at 12:51:49PM -0700, Nicolin Chen wrote:
> > So far, an IOTLB tag (ASID or VMID) has been stored in the arm_smmu_domain
> > +static int __arm_smmu_domain_find_iotlb_tag(struct arm_smmu_domain *smmu_domain,
> > + struct arm_smmu_inv *tag)
> > +{
> > + struct arm_smmu_invs *invs = rcu_dereference_protected(
> > + smmu_domain->invs, lockdep_is_held(&arm_smmu_asid_lock));
> > + size_t i;
> > +
> > + arm_smmu_inv_assert_iotlb_tag(tag);
> > +
> > + for (i = 0; i != invs->num_invs; i++) {
> > + if (invs->inv[i].type == tag->type &&
> > + invs->inv[i].smmu == tag->smmu &&
> > + READ_ONCE(invs->inv[i].users)) {
> > + *tag = invs->inv[i];
>
> This users thing has become to hard to understand and it isn't how it
> should be.
>
> All writers *with the possibility of concurrent access* need to use
> WRITE_ONCE since there is a RCU reader. IIRC that is just
> arm_smmu_invs_unref()
>
> The one in arm_smmu_invs_merge() is just writing to newly allocated
> memory so it shouldn't be marked.
>
> Only readers *with the possibility of concurrent access* should be
> marked with READ_ONCE. IIRC this is just the invalidation walker.
I added a cleanup patch to the beginning of the series and corrected
all the new reads/writes too.
> Places like this have to be protected by a lock or the whole thing is
> wrong, so it should have a lockdep annoation.
Hmm, is the lockdep_is_held() in rcu_dereference_protected() enough?
> Now what is the locking supposed to be? It looks wrong, it probably
> wants to be arm_smmu_asid_lock, but arm_smmu_mm_release() doesn't grab
> it.
>
> But why does arm_smmu_mm_release() need a tag in the first place? ASID
> isn't going to be used when EPD0|EPD1 is set, so the tag can just be
> 0. Probably make a patch with that change early on..
I see. I added a cleanup patch.
> All the locking is important because this:
>
> > +/* Find an existing IOTLB cache tag in smmu_domain->invs (users counter != 0) */
>
> Must be held as an invarient into the caller, meaning the caller must
> hold arm_smmu_asid_lock while it has an active tag on the stack, and
> that should be documented here. As well as a lockdep of course.
>
> From what I can tell the final result is correct (aside from
> arm_smmu_mm_release), just under documented.
Re-checking the locking in these functions and updating the kdocs.
Thanks
Nicolin
^ permalink raw reply
* Re: [PATCH v2 3/4] perf/arm64: Add BRBE support for bpf_get_branch_snapshot()
From: Rob Herring @ 2026-04-10 19:23 UTC (permalink / raw)
To: Puranjay Mohan
Cc: bpf, Puranjay Mohan, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Martin KaFai Lau, Eduard Zingerman,
Kumar Kartikeya Dwivedi, Will Deacon, Mark Rutland,
Catalin Marinas, Leo Yan, Breno Leitao, linux-arm-kernel,
linux-perf-users, kernel-team
In-Reply-To: <20260318171706.2840512-4-puranjay@kernel.org>
On Wed, Mar 18, 2026 at 10:16:57AM -0700, Puranjay Mohan wrote:
> Enable the bpf_get_branch_snapshot() BPF helper on ARM64 by implementing
> the perf_snapshot_branch_stack static call for ARM's Branch Record Buffer
> Extension (BRBE).
>
> The BPF helper bpf_get_branch_snapshot() allows BPF programs to capture
> hardware branch records on-demand. This was previously only available on
> x86 (Intel LBR) but not on ARM64 despite BRBE being available since
> ARMv9.
>
> BRBE is paused before disabling interrupts because local_irq_save() can
> trigger trace_hardirqs_off() which performs stack walking and pollutes
> the branch buffer. The sysreg read/write and ISB used to pause BRBE are
> branchless, so pausing first avoids this pollution.
>
> All exceptions are masked after pausing BRBE using local_daif_save() to
> prevent pseudo-NMI from PMU counter overflow from interfering with the
> snapshot read. A PMU overflow arriving between the pause and
> local_daif_save() can re-enable BRBE via the interrupt handler; the
> snapshot detects this by re-checking BRBFCR_EL1.PAUSED and bailing out.
>
> Branch records are read using the existing perf_entry_from_brbe_regset()
> helper with a NULL event pointer, which bypasses event-specific filtering
> and captures all recorded branches. The BPF program is responsible for
> filtering entries based on its own criteria. The BRBE buffer is
> invalidated after reading to maintain contiguity for other consumers.
>
> On heterogeneous big.LITTLE systems, only some CPUs may implement
> FEAT_BRBE. The perf_snapshot_branch_stack static call is system-wide, so
> a per-CPU brbe_active flag is used to prevent BRBE sysreg access on CPUs
> that do not implement FEAT_BRBE, where such access would be UNDEFINED.
Is this something you've seen? IIRC, the existing assumption is all CPUs
have FEAT_BRBE or that perf has been limited to those CPUs. It is
allowed that the number of records can vary.
>
> Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
> ---
> drivers/perf/arm_brbe.c | 79 +++++++++++++++++++++++++++++++++++++++-
> drivers/perf/arm_brbe.h | 9 +++++
> drivers/perf/arm_pmuv3.c | 5 ++-
> 3 files changed, 90 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/perf/arm_brbe.c b/drivers/perf/arm_brbe.c
> index ba554e0c846c..527c2d5ebba6 100644
> --- a/drivers/perf/arm_brbe.c
> +++ b/drivers/perf/arm_brbe.c
> @@ -8,9 +8,13 @@
> */
> #include <linux/types.h>
> #include <linux/bitmap.h>
> +#include <linux/percpu.h>
> #include <linux/perf/arm_pmu.h>
> +#include <asm/daifflags.h>
> #include "arm_brbe.h"
>
> +static DEFINE_PER_CPU(bool, brbe_active);
> +
> #define BRBFCR_EL1_BRANCH_FILTERS (BRBFCR_EL1_DIRECT | \
> BRBFCR_EL1_INDIRECT | \
> BRBFCR_EL1_RTN | \
> @@ -533,6 +537,8 @@ void brbe_enable(const struct arm_pmu *arm_pmu)
> /* Finally write SYS_BRBFCR_EL to unpause BRBE */
> write_sysreg_s(brbfcr, SYS_BRBFCR_EL1);
> /* Synchronization in PMCR write ensures ordering WRT PMU enabling */
> +
> + this_cpu_write(brbe_active, true);
> }
>
> void brbe_disable(void)
> @@ -544,6 +550,7 @@ void brbe_disable(void)
> */
> write_sysreg_s(BRBFCR_EL1_PAUSED, SYS_BRBFCR_EL1);
> write_sysreg_s(0, SYS_BRBCR_EL1);
> + this_cpu_write(brbe_active, false);
> }
>
> static const int brbe_type_to_perf_type_map[BRBINFx_EL1_TYPE_DEBUG_EXIT + 1][2] = {
> @@ -618,10 +625,10 @@ static bool perf_entry_from_brbe_regset(int index, struct perf_branch_entry *ent
>
> brbe_set_perf_entry_type(entry, brbinf);
>
> - if (!branch_sample_no_cycles(event))
> + if (!event || !branch_sample_no_cycles(event))
> entry->cycles = brbinf_get_cycles(brbinf);
>
> - if (!branch_sample_no_flags(event)) {
> + if (!event || !branch_sample_no_flags(event)) {
> /* Mispredict info is available for source only and complete branch records. */
> if (!brbe_record_is_target_only(brbinf)) {
> entry->mispred = brbinf_get_mispredict(brbinf);
> @@ -803,3 +810,71 @@ void brbe_read_filtered_entries(struct perf_branch_stack *branch_stack,
> done:
> branch_stack->nr = nr_filtered;
> }
> +
> +/*
> + * Best-effort BRBE snapshot for BPF tracing. Pause BRBE to avoid
> + * self-recording and return 0 if the snapshot state appears disturbed.
> + */
> +int arm_brbe_snapshot_branch_stack(struct perf_branch_entry *entries, unsigned int cnt)
> +{
> + unsigned long flags;
> + int nr_hw, nr_banks, nr_copied = 0;
> + u64 brbidr, brbfcr, brbcr;
> +
> + if (!cnt || !__this_cpu_read(brbe_active))
> + return 0;
> +
> + /* Pause BRBE first to avoid recording our own branches. */
> + brbfcr = read_sysreg_s(SYS_BRBFCR_EL1);
> + brbcr = read_sysreg_s(SYS_BRBCR_EL1);
> + write_sysreg_s(brbfcr | BRBFCR_EL1_PAUSED, SYS_BRBFCR_EL1);
> + isb();
Is there something that guarantees BRBE is enabled when you enter this
function and that it is not disabled in this window? A context switch
could disable it unless it's a global event for example.
> +
> + /* Block local exception delivery while reading the buffer. */
> + flags = local_daif_save();
> +
> + /*
> + * A PMU overflow before local_daif_save() could have re-enabled
> + * BRBE, clearing the PAUSED bit. The overflow handler already
> + * restored BRBE to its correct state, so just bail out.
> + */
> + if (!(read_sysreg_s(SYS_BRBFCR_EL1) & BRBFCR_EL1_PAUSED)) {
> + local_daif_restore(flags);
> + return 0;
> + }
> +
> + brbidr = read_sysreg_s(SYS_BRBIDR0_EL1);
> + if (!valid_brbidr(brbidr))
This is not possibly true if brbe_active is true. If BRBIDR is not
valid, then we would have rejected any event requesting branch stack.
> + goto out;
> +
> + nr_hw = FIELD_GET(BRBIDR0_EL1_NUMREC_MASK, brbidr);
> + nr_banks = DIV_ROUND_UP(nr_hw, BRBE_BANK_MAX_ENTRIES);
> +
> + for (int bank = 0; bank < nr_banks; bank++) {
> + int nr_remaining = nr_hw - (bank * BRBE_BANK_MAX_ENTRIES);
> + int nr_this_bank = min(nr_remaining, BRBE_BANK_MAX_ENTRIES);
> +
> + select_brbe_bank(bank);
> +
> + for (int i = 0; i < nr_this_bank; i++) {
I don't love all this being duplicated. Perhaps an iterator would help
here (and the other copy):
static void next_slot(int *bank, int *bank_idx, int nr_hw)
{
*bank_idx++;
if (*bank_idx + (*bank * BRBE_BANK_MAX_ENTRIES) == nr_hw)
bank = BRBE_MAX_BANKS;
else if ((*bank_idx % BRBE_BANK_MAX_ENTRIES) == 0) {
*bank_idx = 0;
select_brbe_bank(++(*bank));
}
}
#define for_each_bank_slot(i, nr_hw) \
for (int bank = 0, int i = 0; bank < BRBE_MAX_BANKS; next_slot(&bank,
&i))
Then here you just have:
for_each_bank_slot(i, FIELD_GET(BRBIDR0_EL1_NUMREC_MASK, brbidr)) {
...
}
Feel free to come up with better naming. :)
> + if (nr_copied >= cnt)
> + goto done;
> +
> + if (!perf_entry_from_brbe_regset(i, &entries[nr_copied], NULL))
> + goto done;
> +
> + nr_copied++;
> + }
> + }
> +
> +done:
> + brbe_invalidate();
> +out:
> + /* Restore BRBCR before unpausing via BRBFCR, matching brbe_enable(). */
> + write_sysreg_s(brbcr, SYS_BRBCR_EL1);
> + isb();
> + write_sysreg_s(brbfcr, SYS_BRBFCR_EL1);
> + local_daif_restore(flags);
> +
> + return nr_copied;
> +}
^ permalink raw reply
* Re: [PATCH V3 7/7] arm64/hw_breakpoint: Enable FEAT_Debugv8p9
From: Rob Herring @ 2026-04-10 19:55 UTC (permalink / raw)
To: Mark Rutland
Cc: Anshuman Khandual, linux-arm-kernel, linux-kernel,
Jonathan Corbet, Marc Zyngier, Oliver Upton, James Morse,
Suzuki K Poulose, Catalin Marinas, Will Deacon, Mark Brown,
kvmarm
In-Reply-To: <adeE4MD0RgapI8aL@J2N7QTR9R3>
On Thu, Apr 9, 2026 at 5:52 AM Mark Rutland <mark.rutland@arm.com> wrote:
>
> On Thu, Apr 02, 2026 at 12:46:56PM -0500, Rob Herring wrote:
> > On Thu, Apr 2, 2026 at 5:37 AM Mark Rutland <mark.rutland@arm.com> wrote:
> > >
> > > On Tue, Mar 31, 2026 at 05:58:00PM -0500, Rob Herring wrote:
> > > > On Mon, Dec 16, 2024 at 10:58:29AM +0000, Mark Rutland wrote:
> > > > > On Mon, Dec 16, 2024 at 09:38:31AM +0530, Anshuman Khandual wrote:
> > > That said, the use of 'bp_per_reg' looks suspect given their
> > > arch_install_hw_breakpoint() and arch_uninstall_hw_breakpoint() modify
> > > that non-atomically.
> >
> > You don't believe the comment saying counter->ctx->lock is held?
>
> Sorry, my concern here was that hw_breakpoint_handler() (which cannot
> hold the lock) consumes bp_per_reg[], and could race with the non-atomic
> modification in arch_install_hw_breakpoint() or
> arch_uninstall_hw_breakpoint().
>
> I've sent a more elaborate mail to x86 folk, with that and another issue
> caused by taking a breakpoint under arch_uninstall_hw_breakpoint():
>
> https://lore.kernel.org/lkml/adZWmPW8S9Y2pwkv@J2N7QTR9R3.cambridge.arm.com/
>
> I think we have a similar latent issue where we can take an breakpoint
> or watchpoint ad infinitum, described in more detail at the end of this
> mail.
>
> [...]
>
> > > > > | What prevents a race with an exception handler? e.g.
> > > > > |
> > > > > | * Does the structure of the code prevent that somehow?
> > > >
> > > > If you can't set a breakpoint/watchpoint in NOKPROBE_SYMBOL() annotated
> > > > code, you can't race.
> > >
> > > As above, I agree (with caveats), but I couldn't spot where this is
> > > enforced.
> > >
> > > > However, there's no such annotation for data. It looks like the kernel
> > > > policy is "don't do that" or disable all breakpoints/watchpoints.
> > >
> > > If we have to transiently disable watchpoints/breakpoints when
> > > manipulating the relevant HW registers, that sounds fine to me.
> >
> > For wp/bp_on_reg, the ordering is 'data access, h/w accesses'. I think
> > we just need a barrier to enforce that ordering so the data access
> > (and then watchpoint) don't trigger in the middle of the h/w accesses.
>
> I assume that by 'h/w accesses' you mean MSRs to the system registers
> controlling breakpoints/watchpoints. Ordering-wise, I don't believe
> memory barriers are necessary here (explain in more detail below).
> However, I also think there's a latent issue here that might bite us
> with the new banking, described at the end of this mail.
>
> Both breakpoint and watchpoint exceptions are synchronous, meanning that
> they can only be taken from the specific instruction that triggered
> them. However, updates to the watchpoint control registers *do* need a
> context synchronization event before they're guarnateed to take effect.
>
> For a sequence:
>
> // Initially:
> // - MDSCR, MDCR, DAIF.D permit debug exceptions at CurrentEL
> // - No watchpoints enabled
>
> 0x000: LDR <val>, [<addr>]
> 0x004: MSR DBGWVR<n>_EL1, <addr>
> 0x008: MSR DBGWCR<n>_EL1, <configure_and_enable>
> 0x010: LDR <val>, [<addr>]
> 0x014: ISB
> 0x018: LDR <val>, [<addr>]
>
> ... we know:
>
> (a) The LDR at 0x000 *cannot* trigger the watchpoint.
Why not? Can't the LDR complete after the MSR? Is ordering ensured
between those? Surely the watchpoint triggers on completion of the
load and that wouldn't stall the PE from doing the MSR(s)?
> (b) The LDR at 0x010 *might* trigger the matchpoint.
> (c) The LDR at 0x018 *must* trigger the watchpoint.
>
> For C code, we can enforce this order with barrier(), e.g.
>
> val = *addr;
> barrier();
> write_sysreg(addr, DBGWVR<n>_EL1);
> write_sysreg(configure_and_enable, DBGWCR<n>_EL1);
> isb();
>
> ... where the compiler cannot re-order the memory access (or
> write_sysreg(), or isb()) across the barrier(), and as isb() has a
> memory clobber, the same is true for isb().
>
> Likewise, for the inverse sequence:
>
> // Initially:
> // - MDSCR, MDCR, DAIF.D permit debug exceptions at CurrentEL
> // - Watchpoint configured and enabled for <addr>
>
> 0x100: LDR <val>, [<addr>]
> 0x104: MSR DBGWCR<n>_EL1, <disable>
> 0x108: LDR <val>, [<addr>]
> 0x110: ISB
> 0x114: LDR <val>, [<addr>]
>
> ... we know:
>
> (a) The LDR at 0x100 *must* trigger the watchpoint.
> (b) The LDR at 0x108 *might* trigger the watchpoint.
> (c) The LDR at 0x114 *cannot* trigger the watchpoint.
>
> > Any guidance on the flavor of dsb here? (And is there any guarantee
> > that the access is visible to the watchpoint h/w after a dsb
> > completes?)
>
> Hopefully the above was sufficient?
>
> As mentioned above, I think we have a latent issue where we can take a
> breakpoint or watchpoint under arch_uninstall_hw_breakpoint(), where we
> have:
>
> arch_uninstall_hw_breakpoint(bp) {
> ...
> hw_breakpoint_control(bp, HW_BREAKPOINT_UNINSTALL) {
> ...
> hw_breakpoint_slot_setup(slots, max_slots, bp, HW_BREAKPOINT_UNINSTALL) {
> ...
> *slot = NULL;
> ...
> }
> ...
> write_wb_reg(ctrl_reg, i, 0) {
> ...
> write_sysreg(0, ...);
> isb();
> ...
> }
> }
> }
>
> The HW breakpoint/watchpoint associated with 'bp' could be triggered
> between setting '*slot' to NULL and the ISB. If that happens, then
> do_breakpoint() won't find 'bp', and will return *without* disabling the
> HW breakpoint or attempting to step.
>
> If that first exception was taken *before* the MSR in write_sysreg(),
> then nothing has changed, and the breakpoint/watchpoint will then be
> taken again ad infinitum.
>
> If that first exception was taken *after* the MSR in write_sysreg(), the
> context synchronization provided by exception entry/return will prevent
> it from being taken again.
>
> Building v6.19 and testing (with pseudo-NMI enabled):
>
> | # grep write_wb_reg /proc/kallsyms
> | ffff80008004b980 t write_wb_reg
> | # ./perf-6.19 stat -a -C 1 -e 'mem:0xffff80008004b980/4:xk' true
I'll give it a try with v4, but that should be prevented with my
changes to exclude kprobe regions.
Rob
^ permalink raw reply
* Re: [PATCH v4 03/10] iommu/arm-smmu-v3: Store IOTLB cache tags in struct arm_smmu_attach_state
From: Jason Gunthorpe @ 2026-04-10 20:47 UTC (permalink / raw)
To: Nicolin Chen
Cc: will, robin.murphy, joro, jpb, praan, smostafa, linux-arm-kernel,
iommu, linux-kernel, linux-tegra, jonathan.cameron
In-Reply-To: <adlG0QTAzdh9vA4M@Asurada-Nvidia>
On Fri, Apr 10, 2026 at 11:52:01AM -0700, Nicolin Chen wrote:
> > Only readers *with the possibility of concurrent access* should be
> > marked with READ_ONCE. IIRC this is just the invalidation walker.
>
> I added a cleanup patch to the beginning of the series and corrected
> all the new reads/writes too.
>
> > Places like this have to be protected by a lock or the whole thing is
> > wrong, so it should have a lockdep annoation.
>
> Hmm, is the lockdep_is_held() in rcu_dereference_protected() enough?
Yes.. but I didn't notice it there, not where I usually look for
lockdeps :)
But also that should have failed in your testing in the SVA case, so
make sure you test with lockdep on, and segfault some app using SVA to
trigger the error clean up flow.
> > But why does arm_smmu_mm_release() need a tag in the first place? ASID
> > isn't going to be used when EPD0|EPD1 is set, so the tag can just be
> > 0. Probably make a patch with that change early on..
>
> I see. I added a cleanup patch.
Also double check it still generates a hitless update, I think it
should but worth confirming.
Also is ASID 0 used at all?
Jason
^ permalink raw reply
* Re: [PATCH net-next v3 00/12] net: airoha: Support multiple net_devices connected to the same GDM port
From: Jakub Kicinski @ 2026-04-10 20:49 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Christian Marangi,
Benjamin Larsson, linux-arm-kernel, linux-mediatek, netdev,
devicetree, Xuegang Lu
In-Reply-To: <adiop-9Mo4ADfvfw@lore-desk>
On Fri, 10 Apr 2026 09:37:11 +0200 Lorenzo Bianconi wrote:
> > On Mon, 06 Apr 2026 12:34:05 +0200 Lorenzo Bianconi wrote:
> > > EN7581 or AN7583 SoCs support connecting multiple external SerDes (e.g.
> > > Ethernet or USB SerDes) to GDM3 or GDM4 ports via a hw arbiter that
> > > manages the traffic in a TDM manner. As a result multiple net_devices can
> > > connect to the same GDM{3,4} port and there is a theoretical "1:n"
> > > relation between GDM ports and net_devices.
> >
> > Looks like this driver uses page pool.
> > If you're sharing the same page pool across multiple netdevs
> > it must not be linked to a netdev.
>
> are you referring to slow.netdev pointer? If so, this is not set in airoha_eth
> driver.
Yes. Alright, thanks for checking. Pretty sure I saw it set somewhere
in a file called airoha* but must be another component :)
^ permalink raw reply
* Re: [PATCH 1/1] virt: arm-cca-guest: fix error check for RSI_INCOMPLETE
From: Gavin Shan @ 2026-04-10 20:50 UTC (permalink / raw)
To: Sami Mujawar, linux-arm-kernel, linux-kernel
Cc: catalin.marinas, will, steven.price, suzuki.poulose, YeoReum.Yun,
Jagdish Gediya
In-Reply-To: <20260410163636.259443-1-sami.mujawar@arm.com>
On 4/11/26 2:36 AM, Sami Mujawar wrote:
> The RSI interface can return RSI_INCOMPLETE when a report spans
> multiple granules. This is an expected condition and should not be
> treated as a fatal error.
>
> Currently, arm_cca_report_new() checks for `info.result != RSI_SUCCESS`
> and bails out, which incorrectly flags RSI_INCOMPLETE as a failure.
> Fix the check to only break out on results other than RSI_SUCCESS or
> RSI_INCOMPLETE.
>
> This ensures partial reports are handled correctly and avoids spurious
> -ENXIO errors when generating attestation reports.
>
> Fixes: 7999edc484ca ("virt: arm-cca-guest: TSM_REPORT support for realms")
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> Reported-by: Jagdish Gediya <Jagdish.Gediya@arm.com>
> ---
> drivers/virt/coco/arm-cca-guest/arm-cca-guest.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
Reviewed-by: Gavin Shan <gshan@redhat.com>
^ permalink raw reply
* [patch V1.1 02/38] x86: Cleanup include recursion hell
From: Thomas Gleixner @ 2026-04-10 20:55 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120317.709923681@kernel.org>
Including a random architecture specific header which requires global
headers just to avoid including that header at the two usage sites is
really beyond lazy and tasteless. Including global headers just to get the
__percpu macro from linux/compiler_types.h falls into the same category.
Remove the linux/percpu.h and asm/cpumask.h includes from msr.h and smp.h
and fix the resulting fallout by a simple forward struct declaration and by
including the x86 specific asm/cpumask.h header where it is actually
required.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
V1.1: Fix PARAVIRT_XXL fallout....
---
arch/x86/include/asm/cache.h | 1 +
arch/x86/include/asm/msr.h | 5 +++--
arch/x86/include/asm/paravirt.h | 3 ++-
arch/x86/include/asm/pvclock.h | 1 +
arch/x86/include/asm/smp.h | 2 --
arch/x86/include/asm/vdso/gettimeofday.h | 5 ++---
arch/x86/kernel/cpu/mce/core.c | 1 +
arch/x86/kernel/nmi.c | 1 +
arch/x86/kernel/smpboot.c | 1 +
9 files changed, 12 insertions(+), 8 deletions(-)
--- a/arch/x86/include/asm/cache.h
+++ b/arch/x86/include/asm/cache.h
@@ -2,6 +2,7 @@
#ifndef _ASM_X86_CACHE_H
#define _ASM_X86_CACHE_H
+#include <vdso/page.h>
#include <linux/linkage.h>
/* L1 cache line size */
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -8,12 +8,11 @@
#include <asm/asm.h>
#include <asm/errno.h>
-#include <asm/cpumask.h>
#include <uapi/asm/msr.h>
#include <asm/shared/msr.h>
+#include <linux/compiler_types.h>
#include <linux/types.h>
-#include <linux/percpu.h>
struct msr_info {
u32 msr_no;
@@ -256,6 +255,8 @@ int msr_set_bit(u32 msr, u8 bit);
int msr_clear_bit(u32 msr, u8 bit);
#ifdef CONFIG_SMP
+struct cpumask;
+
int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
int rdmsrq_on_cpu(unsigned int cpu, u32 msr_no, u64 *q);
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -16,9 +16,10 @@
#ifndef __ASSEMBLER__
#include <linux/types.h>
-#include <linux/cpumask.h>
#include <asm/frame.h>
+struct cpumask;
+
/* The paravirtualized I/O functions */
static inline void slow_down_io(void)
{
--- a/arch/x86/include/asm/pvclock.h
+++ b/arch/x86/include/asm/pvclock.h
@@ -2,6 +2,7 @@
#ifndef _ASM_X86_PVCLOCK_H
#define _ASM_X86_PVCLOCK_H
+#include <asm/barrier.h>
#include <asm/clocksource.h>
#include <asm/pvclock-abi.h>
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -5,8 +5,6 @@
#include <linux/cpumask.h>
#include <linux/thread_info.h>
-#include <asm/cpumask.h>
-
DECLARE_PER_CPU_CACHE_HOT(int, cpu_number);
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map);
--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -11,13 +11,12 @@
#define __ASM_VDSO_GETTIMEOFDAY_H
#ifndef __ASSEMBLER__
-
+#include <clocksource/hyperv_timer.h>
#include <uapi/linux/time.h>
+
#include <asm/vgtod.h>
#include <asm/unistd.h>
-#include <asm/msr.h>
#include <asm/pvclock.h>
-#include <clocksource/hyperv_timer.h>
#include <asm/vdso/sys_call.h>
#define VDSO_HAS_TIME 1
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -48,6 +48,7 @@
#include <linux/vmcore_info.h>
#include <asm/fred.h>
+#include <asm/cpumask.h>
#include <asm/cpu_device_id.h>
#include <asm/processor.h>
#include <asm/traps.h>
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -26,6 +26,7 @@
#include <linux/sched/clock.h>
#include <linux/kvm_types.h>
+#include <asm/cpumask.h>
#include <asm/cpu_entry_area.h>
#include <asm/traps.h>
#include <asm/mach_traps.h>
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -70,6 +70,7 @@
#include <asm/irq.h>
#include <asm/realmode.h>
#include <asm/cpu.h>
+#include <asm/cpumask.h>
#include <asm/numa.h>
#include <asm/tlbflush.h>
#include <asm/mtrr.h>
^ permalink raw reply
* [patch V1.1 11/38] misc: sgi-gru: Remove get_cycles() [ab]use
From: Thomas Gleixner @ 2026-04-10 20:56 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120318.320727701@kernel.org>
Calculating a timeout from get_cycles() is a historical leftover without
any functional requirement.
Use ktime_get() instead.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
V2: Fix typo
---
drivers/misc/sgi-gru/gruhandles.c | 20 ++++++++------------
drivers/misc/sgi-gru/grukservices.c | 3 ++-
drivers/misc/sgi-gru/grutlbpurge.c | 5 ++---
3 files changed, 12 insertions(+), 16 deletions(-)
--- a/drivers/misc/sgi-gru/gruhandles.c
+++ b/drivers/misc/sgi-gru/gruhandles.c
@@ -6,26 +6,22 @@
*/
#include <linux/kernel.h>
+#include <linux/timekeeping.h>
#include "gru.h"
#include "grulib.h"
#include "grutables.h"
-/* 10 sec */
#include <linux/sync_core.h>
-#include <asm/tsc.h>
-#define GRU_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
-#define CLKS2NSEC(c) ((c) * 1000000 / tsc_khz)
+
+#define GRU_OPERATION_TIMEOUT_NSEC (((ktime_t)10 * NSEC_PER_SEC))
/* Extract the status field from a kernel handle */
#define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3)
struct mcs_op_statistic mcs_op_statistics[mcsop_last];
-static void update_mcs_stats(enum mcs_op op, unsigned long clks)
+static void update_mcs_stats(enum mcs_op op, unsigned long nsec)
{
- unsigned long nsec;
-
- nsec = CLKS2NSEC(clks);
atomic_long_inc(&mcs_op_statistics[op].count);
atomic_long_add(nsec, &mcs_op_statistics[op].total);
if (mcs_op_statistics[op].max < nsec)
@@ -58,21 +54,21 @@ static void report_instruction_timeout(v
static int wait_instruction_complete(void *h, enum mcs_op opc)
{
+ ktime_t start_time = ktime_get();
int status;
- unsigned long start_time = get_cycles();
while (1) {
cpu_relax();
status = GET_MSEG_HANDLE_STATUS(h);
if (status != CCHSTATUS_ACTIVE)
break;
- if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time)) {
+ if (GRU_OPERATION_TIMEOUT_NSEC < (ktime_get() - start_time)) {
report_instruction_timeout(h);
- start_time = get_cycles();
+ start_time = ktime_get();
}
}
if (gru_options & OPT_STATS)
- update_mcs_stats(opc, get_cycles() - start_time);
+ update_mcs_stats(opc, (unsigned long)(ktime_get() - start_time));
return status;
}
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -20,6 +20,7 @@
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/export.h>
+#include <linux/random.h>
#include <asm/io_apic.h>
#include "gru.h"
#include "grulib.h"
@@ -1106,7 +1107,7 @@ static int quicktest3(unsigned long arg)
int ret = 0;
memset(buf2, 0, sizeof(buf2));
- memset(buf1, get_cycles() & 255, sizeof(buf1));
+ memset(buf1, get_random_u32() & 255, sizeof(buf1));
gru_copy_gpa(uv_gpa(buf2), uv_gpa(buf1), BUFSIZE);
if (memcmp(buf1, buf2, BUFSIZE)) {
printk(KERN_DEBUG "GRU:%d quicktest3 error\n", smp_processor_id());
--- a/drivers/misc/sgi-gru/grutlbpurge.c
+++ b/drivers/misc/sgi-gru/grutlbpurge.c
@@ -22,13 +22,12 @@
#include <linux/delay.h>
#include <linux/timex.h>
#include <linux/srcu.h>
+#include <linux/random.h>
#include <asm/processor.h>
#include "gru.h"
#include "grutables.h"
#include <asm/uv/uv_hub.h>
-#define gru_random() get_cycles()
-
/* ---------------------------------- TLB Invalidation functions --------
* get_tgh_handle
*
@@ -49,7 +48,7 @@ static inline int get_off_blade_tgh(stru
int n;
n = GRU_NUM_TGH - gru->gs_tgh_first_remote;
- n = gru_random() % n;
+ n = get_random_u32() % n;
n += gru->gs_tgh_first_remote;
return n;
}
^ permalink raw reply
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